Dejé que el futuro se filtrara en el pasado
Hubo un resultado de backtest, al principio, que era tan bueno que debería haberme hecho feliz. En cambio, tras unos minutos contemplándolo, me dejó profundamente inquieto. Las ganancias en la simulación eran grandes, suaves y demasiado limpias — el tipo de rendimiento que no ocurre en un mercado real, ruidoso y adversario. Y la razón por la que no ocurría en un mercado real es que mi prueba, en silencio y sin que yo lo notara, podía ver el futuro.
No a propósito. Yo no había escrito si sabes lo que pasa después, haz trampa. El futuro se había filtrado en el pasado a través de una docena de costuras diminutas y de apariencia inocente, y cada una de ellas premiaba a mi sistema por una especie de clarividencia que jamás, nunca, tendría cuando hubiera dinero real en juego.
El bug más seductor del backtesting
El nombre general de esto es sesgo de anticipación (look-ahead bias), o fuga (leakage). Ocurre siempre que a una decisión en tu simulación se le permite usar información que, en la vida real, todavía no habría existido en el momento en que se tomó la decisión.
Vale la pena detenerse en esto, porque es más sutil de lo que parece. Se supone que un backtest es una recreación fiel de la historia: en cada momento, el sistema solo puede saber lo que realmente era conocible en ese momento, y debe actuar usando únicamente eso. La fuga es cualquier grieta en ese muro — cualquier lugar por donde una astilla de la información de mañana se cuela en la decisión de hoy. Y en el instante en que lo hace, tu backtest deja de medir “cómo le habría ido a esto” y empieza a medir “cómo le iría a esto si pudiera espiar”.
Cómo se cuela el futuro
Quiero ser cuidadoso aquí y no describir los detalles de mi propio sistema, así que dejémoslo en el nivel de las formas generales que adoptan estas fugas, porque son notablemente comunes.
Una forma clásica: usar en una decisión un valor que en realidad solo se finalizó después del momento en que finges decidir. Otra: preparar tus datos escalándolos o normalizándolos con estadísticas — un promedio, un rango, un tamaño típico — calculadas sobre la totalidad de la historia, incluida la parte que, en tu momento simulado, todavía no había ocurrido. Otra: filtrar o etiquetar tus datos con el beneficio de la retrospectiva, excluyendo en silencio ciertos casos de una manera que solo podrías hacer si ya supieras cómo terminaron.
Cada una de estas es una sola línea de código de aspecto razonable. Ninguna se siente como hacer trampa mientras la escribes. Y cada una de ellas le entrega a tu sistema un pequeño y constante flujo de información proveniente del futuro.
Por qué es tan difícil de detectar
Lo más cruel de la fuga es que no parece un bug. El código corre sin error. Nada se cae. Y el resultado que produce no es una señal de alarma — es un número espléndido. Los números espléndidos no despiertan sospecha en la mayoría de la gente. Despiertan celebración, una captura de pantalla, la sensación callada de que quizás vas por buen camino.
Eso es exactamente lo que hace tan peligrosa a esta clase de bug. Se esconde dentro de resultados que parecen un éxito, que es el peor lugar posible donde un bug puede esconderse, porque el éxito es el único desenlace que tienes menos motivación de interrogar. Un crash exige ser arreglado. Una hermosa equity curve te invita a dejar de mirar.
La señal: resultados demasiado buenos para ser verdad
Durante mucho tiempo, la única alarma fiable que tuve fue mi propia incredulidad. Cuando un backtest vuelve dramáticamente mejor que cualquier cosa que pudieras esperar razonablemente — más suave, más rentable, más consistente de lo que el mercado tiene derecho a permitir — la primera hipótesis correcta no es “he encontrado algo brillante”. Es “hay información filtrándose en algún lugar, y necesito encontrarla”.
Este es un prior genuinamente útil, y he llegado a sostenerlo con fuerza: en un backtest, la excelencia es mucho más a menudo un síntoma de un bug que una prueba de tener una ventaja. El mercado es difícil. Los resultados que sugieren que es fácil suelen estar hablándote de tu código, no del mercado.
Encontrar las fugas
El trabajo real de cazar fugas es tedioso y nada glamoroso, y no he encontrado ningún atajo ingenioso que lo reemplace. La disciplina es esta: toma cada uno de los valores que alimentan una decisión, y trázalo hacia atrás hasta el momento preciso en que se habría vuelto conocido en la vida real. Luego pregunta, sin más, “en el instante en que finjo actuar, ¿podría haber tenido genuinamente este número todavía?”.
La mayoría de las fugas, cuando por fin las acorralas, resultan ser una trampa por el valor de un solo timestamp — un valor usado un instante antes de que realmente hubiera existido, un cálculo que llegó un paso más adentro de los datos de lo que tenía permitido. Costuras pequeñas. Pero una costura pequeña, repetida a lo largo de miles de decisiones, basta para fabricar una fortuna imaginaria entera.
El principio más profundo: respeta la flecha del tiempo
Debajo de todo esto hay un único principio que ahora trato como casi sagrado: respeta la flecha del tiempo. Un backtest es, en esencia, una promesa — la promesa de que solo usaste el pasado para actuar en el presente, nunca el futuro. Cada fuga es una pequeña promesa rota, un lugar donde tu código se adelantó en el tiempo, en silencio, para echarse una mano a sí mismo.
Así que construir una simulación confiable resultó tener mucho menos que ver con un modelado ingenioso y mucho más con defender una frontera: la línea entre lo que se sabía en un momento y lo que apenas era conocible más tarde. La mayor parte del esfuerzo de ingeniería, la parte sobre la que nadie escribe hilos admirados, consiste simplemente en custodiar esa frontera contra la tendencia constante y casual de tu propio código a espiar.
Por qué ahora desconfío de mis mejores resultados
El cambio duradero de todo esto fue que mi relación con las buenas noticias se invirtió. Un backtest decepcionante es simplemente decepcionante; lo miro, me encojo de hombros y sigo adelante. Uno espectacular ahora me pone nervioso antes de hacerme feliz. Cuanto mejor es el resultado, con más empeño salgo a buscar la fuga que lo produjo.
Suena triste, y a veces lo es. Pero proviene de un respeto ganado a pulso por la forma en que este juego en particular castiga el autoengaño. Las mentiras más peligrosas que un sistema te dirá jamás no son los fracasos feos. Son los éxitos magníficos — los que se parecen exactamente a lo que esperabas encontrar, y por esa misma razón son los últimos que se te ocurre poner en duda.
— Sin señales, sin retornos, esto no es asesoramiento de inversión.