10 min de lectura
Por qué casi todos los backtests mienten
Sobreajuste y sesgo de supervivencia explicados con un experimento que puedes reproducir en diez minutos: mil estrategias construidas sobre datos completamente aleatorios, y la mejor de todas parece brillante.
- backtesting
- validación
- sesgos
Un backtest es aplicar tus reglas a datos históricos para ver qué habría pasado. Es la herramienta más útil que tenemos y también la más fácil de romper sin darte cuenta.
Doy por hecho que ya tienes una regla escrita; si no es así, empieza por la guía de cómo se convierte una idea en una regla. No hablo de hacer trampas. Hablo de un proceso que parece riguroso, que sigues de buena fe, y que produce un resultado que no significa nada. Voy a enseñar el mecanismo con un ejemplo concreto y luego cómo lo intento evitar.
Un backtest no es una prueba, es una hipótesis
Empecemos por lo conceptual, porque de aquí sale todo lo demás.
Cuando pruebas una regla sobre diez años de datos, no estás comprobando si funciona. Estás comprobando si habría funcionado en esa muestra concreta. Es una diferencia enorme.
La muestra es un camino de los muchos que la historia podría haber tomado. Si tu conclusión cambia mucho al cambiar el trozo de historia que miras, entonces no has medido tu estrategia: has medido ese trozo de historia.
El experimento: mil estrategias sobre ruido puro
Este es el ejercicio que más me cambió la forma de trabajar. Se puede reproducir en un rato.
Genera una serie de precios completamente aleatoria. Sin memoria, sin tendencia, sin nada que predecir. Un paseo aleatorio: cada día, el precio sube o baja una cantidad al azar, independiente de lo anterior.
Sobre esa serie, define una familia de estrategias sencillas. Por ejemplo, cruces de dos medias móviles. Una media móvil es el promedio del precio de los últimos N días; la estrategia compra cuando la media corta cruza por encima de la larga y vende cuando cruza por debajo.
Ahora prueba todas las combinaciones de N corta y N larga entre 2 y 50. Salen más de mil combinaciones.
import numpy as np
import itertools
rng = np.random.default_rng(7)
# Paseo aleatorio: no hay absolutamente nada que aprender aquí.
retornos = rng.normal(0, 0.01, 2500)
precio = 100 * np.exp(np.cumsum(retornos))
def puntuacion(corta, larga):
"""Puntuación de la regla: media de retornos dividida por su desviación."""
if corta >= larga:
return None
mc = np.convolve(precio, np.ones(corta) / corta, mode="valid")
ml = np.convolve(precio, np.ones(larga) / larga, mode="valid")
n = min(len(mc), len(ml))
posicion = (mc[-n:] > ml[-n:]).astype(float)
r = retornos[-n + 1:] * posicion[:-1]
return r.mean() / (r.std() + 1e-12)
resultados = [
(c, l, puntuacion(c, l))
for c, l in itertools.product(range(2, 51), range(2, 51))
if c < l
]
resultados = [r for r in resultados if r[2] is not None]
mejor = max(resultados, key=lambda x: x[2])
print("combinaciones probadas:", len(resultados))
print("mejor combinación:", mejor[0], mejor[1])Lo que sale siempre, con cualquier semilla, es lo mismo: una de esas combinaciones destaca claramente sobre las demás. Su curva de resultados sube de forma convincente. Tiene una racha ganadora larga. Los parámetros parecen incluso razonables, algo así como 9 y 34, y a uno le entran ganas de justificarlos.
Y todo eso está construido sobre datos donde, por definición, no hay nada que encontrar.
Eso es el sobreajuste: ajustar tanto los parámetros a una muestra concreta que capturas su ruido en lugar de su estructura.
Lo que este experimento hace obvio
Tres consecuencias prácticas, todas incómodas.
Primera: el número de combinaciones que pruebas es un parámetro oculto de tu estrategia. Dos personas pueden presentarte exactamente la misma regla con exactamente el mismo resultado histórico y una ser mucho más creíble que la otra, en función de cuántas cosas probó antes de llegar ahí. Y ese número no aparece en ningún informe.
Segunda: la optimización de parámetros no mejora la estrategia, mejora el backtest. Son cosas distintas y muy fáciles de confundir.
Tercera: probar variantes a mano cuenta igual. Mucha gente no ejecuta un optimizador y cree que se libra. Pero si has probado la estrategia, no te ha gustado, has cambiado el filtro, la has vuelto a probar y así doce veces, has hecho una optimización manual de doce combinaciones. Con el agravante de que no la has apuntado.
Yo llevo un registro de cuántas variantes he probado por idea. La cifra siempre es más alta de lo que recordaba.
Sesgo de supervivencia: el universo que ya no existe
El segundo problema es de otro tipo. No está en tu código, está en tus datos.
El sesgo de supervivencia consiste en probar una estrategia sobre un conjunto de instrumentos que solo incluye los que han llegado hasta hoy.
El ejemplo clásico: descargas los componentes actuales de un índice bursátil y pruebas tu estrategia sobre esos valores desde 2005. Parece correcto. No lo es. Ese conjunto está elegido con información del futuro: son precisamente las empresas que en 2026 siguen siendo lo bastante grandes como para estar en el índice. Las que quebraron, las que fueron absorbidas y las que se hundieron y salieron del índice no están en tu fichero.
Tu estrategia se está probando en un mundo donde las empresas no quiebran. Y da igual lo que compres en ese mundo, va a salir bien.
Lo mismo pasa en cripto con más violencia, porque el ciclo de vida es más corto. Si descargas las cien monedas más grandes de hoy y pruebas una estrategia desde 2019, has eliminado del universo casi todas las que desaparecieron. Que eran muchísimas.
La solución técnica se llama point in time: los datos deben decirte qué instrumentos existían y cumplían tus criterios en cada fecha del pasado, no hoy. Es más caro y más engorroso, y es la diferencia entre medir algo y no medir nada.
Dos sesgos más que se cuelan solos
Sesgo de anticipación (look ahead). Usar en el momento T información que no estaba disponible hasta T más algo. Se cuela por sitios sutiles: un dato macroeconómico que se publica con retraso y luego se revisa, un cierre ajustado por un dividendo que se anunció después, o el error más común de todos, calcular una señal con la vela actual y ejecutarla al precio de apertura de esa misma vela. Una sola línea mal indexada convierte un backtest en una máquina del tiempo.
Costes ausentes u optimistas. Comisiones, horquilla entre compra y venta, deslizamiento, financiación de posiciones mantenidas. Cuanto más corto es tu marco temporal, más determinante es esto. Hay estrategias que sobreviven perfectamente al backtest y mueren en el primer céntimo de coste. Mi regla es sencilla: si la conclusión cambia al doblar los costes estimados, la estrategia no es viable, es una hoja de cálculo optimista.
Qué hago para no engañarme
No hay una solución, hay una batería de obstáculos. Cada uno elimina una parte del autoengaño.
Separo los datos antes de mirarlos. Un tramo para desarrollar y otro que no toco. El segundo se abre una sola vez, al final. Si el resultado no me gusta y vuelvo a ajustar, ese tramo ya está quemado y deja de ser independiente para siempre. Esto exige una disciplina que cuesta más de lo que parece.
Validación hacia delante (walk forward). En vez de un único corte, se avanza por ventanas: ajustas en un periodo, evalúas en el siguiente, desplazas la ventana y repites. Da una serie de resultados fuera de muestra en lugar de uno solo, y sobre todo enseña si los parámetros óptimos saltan de un sitio a otro en cada ventana. Si saltan, no hay señal estable.
Simulación de Monte Carlo. Reordeno al azar las operaciones muchas veces para ver el abanico de trayectorias posibles con los mismos resultados. Sirve para una cosa concreta: entender que la curva bonita que tienes delante es una realización entre muchas, y ver cuánto peor podía haber ido con las mismas operaciones en otro orden.
Prueba de superficie de parámetros. Miro el resultado de todas las combinaciones vecinas, no solo la mejor. Busco una meseta ancha donde todo el vecindario se comporte parecido. Un pico aislado rodeado de resultados malos es sobreajuste con casi total seguridad.
El experimento de la moneda como control. Antes de creerme un resultado, aplico el mismo proceso completo a datos aleatorios. Si mi proceso también produce una estrategia estupenda sobre ruido, mi proceso está roto, no importa lo bien que salga con datos reales.
Cuento las decisiones, no las operaciones. Mil operaciones generadas por una regla con veinte parámetros ajustados dan mucha menos información que cien operaciones de una regla con dos parámetros fijados de antemano.
La pregunta que resume todo
Cuando tengo un resultado que me gusta, me hago siempre la misma pregunta:
¿Cuántas cosas tuve que probar para llegar hasta aquí, y habría aceptado este mismo resultado si hubiera salido en el primer intento?
Si probé cien variantes, mi resultado no vale lo que parece. Si solo probé dos, empiezo a tener algo que merece atención.
No es una fórmula elegante. Pero es lo que más ideas malas me ha ahorrado, y las ideas malas se pagan siempre, antes o después, con dinero de verdad.
Contenido educativo. Nada de lo que leas aquí es una recomendación de inversión.
