Un backtest es la forma más fácil que existe de mentirte a vos mismo. Te muestra una curva de equity hermosa, te llena de confianza, y después el mercado real te cobra la factura. Antes de creerle a cualquier backtest —el tuyo o el de un curso— hay que entender cómo se rompe.
Los sesgos que te arruinan
1. Look-ahead bias (usar información del futuro)
Es el más letal y el más sutil. Pasa cuando tu sistema usa, para decidir hoy, información que en ese momento todavía no existía: el cierre del día para entrar a la apertura, datos que se revisan después (earnings restateados), o un indicador que se recalcula con la serie completa.
Si tu estrategia conoce el futuro, no es una estrategia: es una máquina del tiempo. Y esas no cotizan.
Cómo evitarlo: procesá los datos barra por barra, como si no supieras lo que viene. Si tenés dudas, agregá un delay explícito de una barra entre la señal y la ejecución.
2. Survivorship bias (solo los que sobrevivieron)
Si backtesteás con la lista de acciones que existen hoy, estás operando solo con las que no quebraron, no se deslistaron ni desaparecieron. La historia se ve siempre mejor cuando borrás a los muertos.
Cómo evitarlo: usá datasets point-in-time que incluyan tickers deslistados. Es caro y molesto, pero es la diferencia entre un backtest honesto y un cuento.
3. Overfitting y curve fitting (ajustar al ruido)
Si probás 500 combinaciones de parámetros y te quedás con la que mejor anduvo, no encontraste un edge: encontraste el ruido que mejor encajó en ese pasado. Cuantos más parámetros y más optimización, más alta la probabilidad de estar curve-fitteando.
Cómo evitarlo:
- Pocos parámetros, con sentido económico detrás.
- Out-of-sample: separá datos que el sistema nunca vio al diseñarlo.
- Walk-forward analysis en vez de una sola optimización global.
Las métricas que importan (no solo el retorno)
El retorno total no te dice nada sin el riesgo que tomaste para conseguirlo. Estas son las que miro:
| Métrica | Qué mide | Lectura rápida |
|---|---|---|
| Sharpe | Retorno por unidad de volatilidad total | > 1 decente, > 2 muy bueno |
| Sortino | Como Sharpe pero solo castiga la volatilidad a la baja | Más justo para sistemas asimétricos |
| Calmar | Retorno anual / Max Drawdown | Cuánto ganás vs. tu peor caída |
| Max Drawdown | La peor caída pico-a-valle | ¿Lo aguantás emocional y financieramente? |
| Profit Factor | Ganancia bruta / pérdida bruta | > 1 gana; > 1.5 sólido |
Un detalle clave: el Max Drawdown no es un número de Excel, es una pregunta personal. ¿Podés ver tu cuenta caer un 30% y seguir ejecutando el sistema sin romperlo? Si la respuesta es no, ese sistema no es para vos por más lindo que sea el Sharpe.
import numpy as np
def sharpe(returns, rf=0.0, periods=252):
excess = returns - rf / periods
return np.sqrt(periods) * excess.mean() / excess.std()
def max_drawdown(equity):
peak = np.maximum.accumulate(equity)
return ((equity - peak) / peak).min()
Checklist antes de creerle a un backtest
- ¿Hay delay entre señal y ejecución? (look-ahead)
- ¿Incluí tickers deslistados? (survivorship)
- ¿Probé en out-of-sample? (overfitting)
- ¿Resté comisiones, slippage y costo de borrow?
- ¿Miré el drawdown, no solo el retorno?
Si todas dan que sí, recién ahí empiezo a tomarme el resultado en serio. Y aun así, lo trato como una hipótesis, no como una verdad.
— José