sesgo de anticipación backtest que es y como evitarlo
El sesgo de anticipación filtra datos futuros en un backtest. Decisiones en la misma barra, supervivencia y cifras revisadas inflan resultados. Aprenda a detectarlo.
El sesgo de anticipación (look-ahead bias) ocurre cuando se utiliza información dentro de un backtest que nadie podría haber tenido en el momento en que se colocó la operación simulada. La curva de equity sube, las estadísticas se ven excelentes y nada de eso sobrevive al contacto con una orden en vivo. Esta página define el sesgo, explica tres mecanismos que lo producen y mide cada uno con datos reales de mercado.
Qué es el sesgo de anticipación
Un backtest es una afirmación sobre una decisión: en este momento, con esta información, la regla habría hecho esto. La afirmación solo se sostiene cuando cada insumo que la regla lee ya existía, en su forma final, antes de ese momento. El sesgo de anticipación es cualquier violación de esa condición, y es silencioso. Nada en una hoja de cálculo o un script se queja cuando una fila entrega un valor con una marca de tiempo posterior a la decisión que alimenta.
Tres violaciones cubren la mayor parte de lo que aparece en la práctica. Una decisión que lee una barra de precios dentro de la cual también opera. Un universo armado con los nombres que aún cotizan hoy. Un campo de datos que fue revisado después de la fecha que lleva.
Mecanismo uno: decidir sobre una barra que también se opera
Comience con una regla que suene inofensiva. Compre en fortaleza, es decir, en sesiones donde el fondo termina por encima de donde abrió. Codificado descuidadamente, la prueba entra en la apertura de esa sesión y sale en el cierre de esa sesión, mientras que la condición que evalúa es el precio de cierre de la misma barra. Nadie conoce el precio de cierre al toque de campana de apertura.
El panel a continuación ejecuta ambas versiones en SPY, el rastreador del S&P 500, durante diez años calendario. La primera columna es la imposible. La segunda retrasa la condición idéntica una sola sesión, que es lo más temprano que una cuenta fondeada podría actuar sobre ella.
El SQL exacto detrás de cada cifra
WITH bars AS (
SELECT date,
toFloat64(open) AS o,
toFloat64(close) AS c,
toFloat64(close) > toFloat64(open) AS up_day
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= toDate('2015-12-01')
AND date <= toDate('2025-12-31')
),
lagged AS (
SELECT date, o, c, up_day,
any(up_day) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prior_up
FROM bars
)
SELECT toYear(date) AS year,
countIf(up_day) AS signal_days,
round(100 * avgIf(c / o - 1, up_day), 3) AS same_bar_avg_pct,
round(100 * avgIf(c / o - 1, prior_up), 3) AS lagged_avg_pct,
round(100 * (avgIf(c / o - 1, up_day) - avgIf(c / o - 1, prior_up)), 3) AS gap_pp
FROM lagged
WHERE date >= toDate('2016-01-01')
GROUP BY year
ORDER BY yearLa separación no es sutil. En 2016, la versión de la misma barra promedió 0.447% por sesión calificada, mientras que la versión retrasada promedió -0.008%, un diferencial de 0.455 puntos porcentuales por día. En 2025, las dos leyeron 0.636% y -0.03%. Con aproximadamente 140 sesiones calificadas en un año, un diferencial de medio punto porcentual por sesión se compone en una curva de equity que ninguna cuenta en vivo ha impreso jamás.
Todo el margen es definicional. Seleccionar sesiones que cerraron por encima de su apertura y luego medir la apertura al cierre en esas mismas sesiones mide una cantidad garantizada como positiva. La regla descubrió su propio filtro.
Las variantes de esto se esconden todo el tiempo en datos diarios: un promedio móvil que incluye el cierre de hoy y se usa para operar hoy, una señal calculada sobre precios ya ajustados por un split que aún no había ocurrido, un stop intradiario colocado en un máximo de sesión que aún no se había impreso. La forma común es una marca de tiempo de decisión anterior a una de sus propias entradas.
Mecanismo dos: un universo extraído de los supervivientes de hoy
El segundo mecanismo nunca toca la regla. Se encuentra en la lista de nombres que la regla puede ver.
Tome una lista de tickers de un proveedor de datos actual, ejecútela diez años atrás, y la muestra excluye silenciosamente a todas las empresas que quebraron, fueron adquiridas o fueron excluidas de cotización en el camino. A la regla nunca se le ofrecieron los perdedores. El panel mide el tamaño de esa omisión: cada nombre cotizado en EE. UU. que negoció al menos 200 sesiones por encima de $1 en un año calendario determinado, la proporción de esa cohorte que aún imprime precios en julio de 2026, y el rendimiento mediano del año calendario de toda la cohorte junto con el mediano de solo los supervivientes.
El SQL exacto detrás de cada cifra
WITH recent AS (
SELECT DISTINCT ticker
FROM global_markets.stocks_daily_aggs
WHERE date >= toDate('2026-06-15')
AND date <= toDate('2026-07-28')
),
per_name AS (
SELECT toYear(date) AS year,
ticker,
argMin(toFloat64(close), date) AS first_close,
argMax(toFloat64(close), date) AS last_close,
count() AS sessions
FROM global_markets.stocks_daily_aggs
WHERE date >= toDate('2015-01-01')
AND date <= toDate('2024-12-31')
AND close > 1
GROUP BY year, ticker
HAVING sessions >= 200
)
SELECT year,
uniqExact(ticker) AS names_trading,
round(100 * uniqExactIf(ticker, ticker IN (SELECT ticker FROM recent)) / uniqExact(ticker), 1) AS still_listed_pct,
round(100 * quantileDeterministic(0.5)(last_close / first_close - 1, cityHash64(ticker)), 2) AS median_return_all_pct,
round(100 * quantileDeterministicIf(0.5)(last_close / first_close - 1, cityHash64(ticker), ticker IN (SELECT ticker FROM recent)), 2) AS median_return_survivors_pct,
round(100 * (quantileDeterministicIf(0.5)(last_close / first_close - 1, cityHash64(ticker), ticker IN (SELECT ticker FROM recent))
- quantileDeterministic(0.5)(last_close / first_close - 1, cityHash64(ticker))), 2) AS survivor_gap_pp
FROM per_name
GROUP BY year
ORDER BY yearDe los 7063 nombres que superaron la barra en 2015, 52.5% aún cotizaban en julio de 2026. Para la cohorte de 2024, la cifra es 87.5%, principalmente una cuestión de tiempo transcurrido: un nombre de 2024 ha tenido dos años para desaparecer y uno de 2015 ha tenido once.
Las columnas de rendimiento contienen el sesgo en sí mismo. En 2017, el nombre mediano rindió 7.51%, mientras que el superviviente mediano rindió 11.32%, una brecha de 3.81 puntos porcentuales entregados gratuitamente. La brecha es positiva en cada uno de los 10 años graficados. Una estrategia probada en supervivientes la hereda antes de tomar una sola decisión, y las reglas que filtran por debilidad heredan más que la mediana, ya que los nombres que desaparecieron se encuentran desproporcionadamente en ese grupo.
La corrección es un universo punto en el tiempo: la lista de nombres tal como estaba en cada fecha de rebalanceo, incluyendo las exclusiones, con una posición excluida cerrada en su último precio en lugar de eliminada del registro.
Mecanismo tres: datos que fueron revisados después de su sello de fecha
Los precios se sellan una vez. Los fundamentales no. Una cifra trimestral lleva la fecha de fin de trimestre, es enmendada por una presentación posterior, y una base de datos que solo almacena la versión actual servirá felizmente la cifra enmendada contra la fecha original. Una regla que filtra por esa cifra está leyendo una corrección que tardó meses en llegar.
El mismo patrón recorre las listas de miembros de índices reconstruidas con los constituyentes actuales, los historiales de estimaciones de analistas sobrescritos con el consenso final y los ajustes de acciones corporativas aplicados hacia atrás a través de una serie de precios completa. En cada caso, el registro almacenado es una instantánea en tiempo presente que lleva una fecha en tiempo pasado.
Dos prácticas lo contienen. Use una fuente que mantenga añadas, es decir, el valor tal como se conocía en cada fecha en lugar del valor tal como se conoce ahora. Cuando las añadas no estén disponibles, aplique un rezago de reporte lo suficientemente generoso para cubrir el real, y trate la longitud de ese rezago como un parámetro que vale la pena probar en lugar de un detalle que vale la pena adivinar.
Cómo se ve la curva cuando el futuro se filtra
El sesgo de anticipación tiene una firma: un rendimiento muy por encima de lo que ofreció el mercado subyacente. Un punto de referencia útil es el techo de la retrospectiva, el crecimiento que un pronóstico perfecto de un día de anticipación habría producido en un solo instrumento.
El SQL exacto detrás de cada cifra
WITH bars AS (
SELECT date,
toFloat64(close) AS c,
any(toFloat64(close)) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_c
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= toDate('2015-12-01')
AND date <= toDate('2025-12-31')
),
rets AS (
SELECT toYear(date) AS year,
c / prev_c - 1 AS r
FROM bars
WHERE date >= toDate('2016-01-01')
AND prev_c > 0
)
SELECT year,
count() AS sessions,
round(100 * (exp(sum(log(1 + r))) - 1), 1) AS buy_and_hold_pct,
round(100 * (exp(sumIf(log(1 + r), r < 0.02)) - 1), 1) AS without_big_up_days_pct,
round(exp(sum(log(1 + abs(r)))), 1) AS hindsight_ceiling_multiple
FROM rets
GROUP BY year
ORDER BY yearEl techo es enorme. En 2020, la previsión perfecta de un día en SPY multiplicó el capital 27.7 veces en 253 sesiones, frente a 16.2% por simplemente mantener el fondo. En el año más tranquilo de los diez, 2017, el mismo pronóstico perfecto rindió 2.2 veces el capital.
La columna del medio muestra cuán concentrado está ese techo. Elimine las sesiones que ganaron más del 2%, y 2020 pasa de 16.2% a -44.9%. Una filtración que vale solo un puñado de esas sesiones al año mueve un backtest muy lejos. Una curva con retrocesos poco profundos, una alta tasa de aciertos y sus mejores días agrupados en las sesiones más violentas del mercado se ha ganado una auditoría.
La calibración importa más que cualquier umbral único. Una regla que afirma un suave 40% anual durante una década está reclamando una gran fracción del techo de la retrospectiva, y la pregunta honesta es qué insumo le dijo lo que estaba a punto de suceder.
Cómo probar un backtest para detectar sesgo de anticipación
- Retrase todo una barra. Desplace cada señal un período completo más tarde y vuelva a ejecutar. Los bordes genuinos se deterioran un poco. Las filtraciones colapsan, a menudo a nada.
- Perturbe el futuro. Tome los datos después de cada marca de tiempo de decisión, reemplácelos con ruido o una reorganización, y vuelva a ejecutar la lógica de decisión. Cada decisión debería ser idéntica. Cualquier decisión que se mueva ha leído algo que no podría haber sabido.
- Trate las marcas de tiempo como datos. Para cada insumo, almacene el momento en que un valor estuvo disponible junto al momento que describe. Una unión que nunca compara esas dos columnas no puede hacer cumplir la regla.
- Reconstruya el universo a partir de la fecha. Incluya nombres excluidos y adquiridos, ciérrelos en su último precio y ejecute la misma regla en ambos universos para dimensionar la contribución de la supervivencia.
- Mida contra el techo. Coloque el rendimiento de la estrategia junto a una cifra de comprar y mantener y una cifra de previsión perfecta para la misma ventana. La distancia desde el techo es un contexto que un ratio de Sharpe por sí solo no proporciona.
El dimensionamiento de la posición está aguas abajo de todo esto. Una tasa de ganancia inflada alimenta un tamaño de apuesta inflado, que es donde el dimensionamiento de posición del criterio de Kelly convierte un error contable en un retroceso. La misma disciplina se aplica antes de que el capital real se mueva: el paper trading antes del dinero real prueba la mecánica de las órdenes, y los stacks automatizados conllevan el mismo peligro a velocidad de máquina, cubierto en sistemas de trading multiagente con IA. Los efectos que sobreviven a pruebas cuidadosas punto en el tiempo, como la anomalía de baja volatilidad, son interesantes precisamente por esa razón.
FAQ
¿Qué es el sesgo de anticipación en backtesting?
Es el uso de datos en una operación simulada que no estaban disponibles cuando se habría colocado la operación. Las formas comunes son decidir sobre una barra de precios dentro de la cual la operación también se ejecuta, filtrar un universo de empresas que aún cotizan hoy y leer una cifra financiera que fue revisada después de la fecha adjunta.
¿Cómo se puede detectar el sesgo de anticipación?
Retrase cada señal un período completo y vuelva a ejecutar: una filtración generalmente colapsa mientras que un borde real se deteriora suavemente. Una prueba más fuerte reemplaza todos los datos después de cada marca de tiempo de decisión con ruido y confirma que cada decisión sale sin cambios.
¿Es el sesgo de supervivencia lo mismo que el sesgo de anticipación?
Son distintos pero viajan juntos. El sesgo de supervivencia es una muestra construida a partir de los nombres que duraron, y saber qué nombres duraron es en sí mismo información del futuro, por lo que un universo de solo supervivientes es una filtración de anticipación ubicada en los datos y no en la regla.
¿Por qué los backtests con sesgo de anticipación se ven tan bien?
La filtración selecciona resultados en lugar de predecirlos. En el panel anterior, filtrar sesiones por su propio precio de cierre produjo una ganancia de sesión promedio de aproximadamente 0.455 puntos porcentuales por encima de la versión retrasada en 2016, una ventaja que es definicional en lugar de ganada.
¿Qué son los datos punto en el tiempo?
Los datos punto en el tiempo almacenan cada valor tal como se conocía en cada fecha histórica, incluida la cifra original y cada revisión posterior, junto con el universo de valores tal como estaba ese día. Es la referencia que un backtest necesita para mostrar que sus insumos existían antes de sus decisiones.
Cada cifra anterior es una consulta almacenada y versionada sobre barras diarias reales. Expanda el SQL de cualquier panel, o ejecute la prueba de rezago en su propia regla en el terminal de Strasmore.