Publicado como Idea de TradingView sobre ETHUSDT. Ver el gráfico en TradingView
Si alguna vez ha portado un indicador a Python para hacerle un backtest, o ha confiado en un script porque venía con una verificación, esto trata del hueco que dejan abierto esas dos cosas.
Reconstruimos tres de nuestros propios indicadores para poder pasarles un backtest. Las tres reconstrucciones llevaban dentro una constante equivocada. Las tres superaron su validación. Ninguna fue detectada por una prueba.
Por qué reconstruir un indicador siquiera
Un script de Pine se ejecuta en su gráfico. No recorre seis años de historial en un bucle, y no responde a si una señal realmente compensa. Para preguntar eso, se reconstruye en algo que se pueda ejecutar miles de veces.
Es en esa reconstrucción donde un indicador deja de ser, sin hacer ruido, el mismo indicador.
El error que más costó, y es una vela
Una de las longitudes dentro de Volume Oracle se deriva de la temporalidad:
target bars = 36 hours × 60 / 240 minutes = 9
regime length = round(9 × 2.5) = round(22.5)
El math.round de Pine resuelve los empates alejándose del cero. Da 23. El round() de Python 3 usa el redondeo bancario, que resuelve los empates hacia el número par. Da 22.
Ambas son implementaciones correctas del redondeo. Son simplemente convenciones distintas, y nada le avisa de que ha pasado de una a la otra.
Todos los retrocesos derivados de ese número se movieron con él. El resultado en la fila mejor respaldada de un barrido de 36 señales:
| versión | ventaja a 48 h | tasa de acierto | n |
|---|---|---|---|
| reconstruido, longitud 22 | +0,423 % | 51 | 1216 |
| correcto, longitud 23 | +0,260 % | 50 | 1223 |
Un recorte del 38 % por una convención de redondeo.
Después anotamos mal la lección
La nota que escribimos decía que ocurría solo en 4H. Se escribió desde la única temporalidad que estaba bajo prueba en ese momento, y así se quedó durante dos meses.
Ejecutando la misma aritmética en todas las temporalidades:
| temporalidad | longitud de régimen | longitud de flujo | resultado |
|---|---|---|---|
| 5m | 45 vs. 45 | 23 vs. 22 | diverge |
| 2H | 45 vs. 45 | 23 vs. 22 | diverge |
| 4H | 23 vs. 22 | 12 vs. 11 | diverge |
| 8H | 53 vs. 52 | 27 vs. 26 | diverge |
| 1D | 18 vs. 18 | 9 vs. 9 | empata, coincide |
| 3D, 1W | 15 vs. 15 | 8 vs. 8 | empata, coincide |
Cuatro de dieciséis, no una.
De esa tabla salen dos cosas que ningún razonamiento produjo.
Un empate no basta. 1D, 3D y 1W caen todas exactamente en ,5 y coinciden. El redondeo bancario solo mueve un empate cuya respuesta al redondear hacia arriba es impar, así que round(17.5) da 18 en cualquier caso. Aproximadamente la mitad de todos los empates son inofensivos, y precisamente por eso comprobar uno al azar no demuestra nada.
La divergencia puede llegar un paso más tarde. En 5m y 2H la primera longitud coincide en 45. La línea siguiente, round(45 × 0.5), vuelve a ser 22,5, y esa sí se separa. Si comprueba la primera constante y sigue adelante, da por buenas ambas temporalidades sin motivo.
Los otros dos, brevemente
Harmonic normaliza un oscilador recortándolo a una banda móvil. En el código fuente, cada vela se recorta con su propia banda. La reconstrucción recortaba una ventana entera de 200 velas usando la banda de la vela actual, que es una función distinta. Diferencia medida en 11.497 velas: 0,47 puntos de media. Un error de transcripción real sin efecto material.
Ese además lo inflamos antes de medirlo. Se anunció, con solo leer el código, como casi con seguridad la desviación del 9 %. El número era 0,47. Un error real y un error con efecto material son afirmaciones distintas, y la magnitud se mide antes de nombrar el impacto.
Plutus Flow promedia el volumen sobre 50 velas para detectar picos. La reconstrucción usó 20, porque ese era el número que creíamos saber. Efecto: menos de una décima de punto porcentual, sin cambios de signo. El veredicto no se movió, pero el número estaba mal y ahora está bien, que es el único criterio que importa.
La parte que es en realidad la lección
Esto es lo que informó en su momento la validación de cada reconstrucción.
| reconstrucción | su propia comprobación | qué significaba eso |
|---|---|---|
| Volume Oracle | 3 de 3 antes, 3 de 3 después | no supo distinguirlas |
| Harmonic | 6 de 8 antes, 5 de 8 después | puntuó más alto la versión con el error |
| Plutus Flow | nunca se ejecutó | — |
La fila del medio es la que conviene rumiar. La validación prefirió el código equivocado. Si hubiéramos dejado decidir a la comprobación, nos habría convencido de volver al error.
Una validación que compara un solo valor de salida no puede detectar una constante de entrada equivocada. La salida es un tamiz demasiado grueso. Muchos conjuntos de parámetros equivocados y distintos producen hoy la misma etiqueta de régimen, el mismo estado de cruce, el mismo color en el gráfico. Difieren en velas que usted no está mirando ahora mismo, que es exactamente donde vive un backtest.
Qué hacer en su lugar
Imprima todos los parámetros derivados. Todas las longitudes, todos los umbrales, todos los multiplicadores. Compárelos con el código fuente línea a línea antes de calificar nada.
Conserve la comprobación de salida. Detecta otra clase de error y es necesaria. Simplemente no es ni de lejos suficiente, y estos tres pasaron por delante de ella sin despeinarse.
El alcance honesto
El código Pine era correcto en los tres casos. Lo que estaba mal era el aparato construido para probarlo, que es la versión más incómoda del problema: el instrumento se desvió, y la autocomprobación del propio instrumento decía que no.
La cifra del 38 % es una fila, un barrido, una temporalidad, dentro de la muestra, y está citada de nuestro propio registro en lugar de recalculada. El resultado del redondeo es reproducible con una sola orden, y al corregirlo salió a la luz que nuestra propia nota al respecto llevaba dos meses equivocada.
Publicado como Idea de TradingView sobre ETHUSDT. Ver el gráfico en TradingView
Medición pasada de nuestras propias herramientas, descrita a posteriori. Nada de esto es una recomendación ni un indicio de resultados futuros.