Repaint, lookahead y request.security en Pine (Basic sin MTF)

Por qué desaparecen señales, trampas de lookahead y por qué Basic no añade stacks multi-TF en esta academia.

📖 6 min read

📝 1,152 words

🏷️ Pine Script and TradingView

Compartir este artículo:

Qué significa realmente el repintado

Tres temporalidades apiladas: la mayor da contexto, la menor marca el momento de entrada.H4tendencia y contextoH1confirmaciónM15momento de entrada
Cómo se lee una regla multitemporal: contexto arriba, momento abajo.

El repintado ocurre cuando la salida de un script en una barra cambia según cuándo se calculó. La misma barra, el mismo script, dos respuestas distintas: una mientras la barra se formaba y otra después de cerrar, cuando el script recalculó desde el historial.

Se deriva de algo estructural, no de un error. Una barra histórica contiene cuatro números: apertura, máximo, mínimo y cierre. Una barra en tiempo real tiene un cierre que aún se mueve, y un máximo y un mínimo que pueden seguir extendiéndose [1]. Un script que lee high en una barra en formación lee un valor que no es definitivo. Cuando después vuelve a recorrer esa barra como historial, lee el definitivo.

No todo repintado es un defecto

Esta es la parte que se pierde, y equivocarse en cualquiera de los dos sentidos es caro.

Repintado que funciona como debe: un indicador que se actualiza mientras la barra actual se desarrolla. Eso lo quieres. Una señal que solo aparece tras el cierre es una señal que no puedes ejecutar al cierre.

Repintado que invalida un backtest: un script cuyos valores históricos no podrían haberse conocido en el momento en que se dibujan. Ese es el que hace que una curva de resultados parezca extraordinaria y no signifique nada, porque la ejecución histórica tuvo información que la ejecución en vivo nunca tendrá.

La prueba no es «¿cambia?», sino «¿podría haberse conocido este valor en esa barra, en ese momento, en tiempo real?». Si la respuesta es no, el backtest mide una estrategia que no puede existir.

TradingView es directo sobre la peor versión: los scripts que filtran datos futuros al historial son «extremadamente engañosos», y publicarlos no está permitido [2].


Las diez causas documentadas

TradingView documenta diez causas distintas [1]. No son igual de graves, así que aquí se agrupan por lo que hacen a un backtest y no por característica del lenguaje.

Fatales — el backtest mide algo imposible

CausaQué ocurre
Fuga de futuro vía request.security()Usar lookahead sin desplazamiento revela precios posteriores a la barra actual, solo en barras históricas
Dibujar en el pasadoDibujar retroactivamente en barras anteriores, de modo que el gráfico muestra una detección que no ocurrió entonces

Ambas producen un registro histórico que no podría haber existido en vivo. Nada más en esta lista está en la misma categoría.

Estructurales — espera una diferencia y tenla en cuenta

CausaQué ocurre
Valores de datos fluidosLas barras históricas solo tienen OHLC; en una barra en tiempo real el máximo, el mínimo y el cierre siguen moviéndose
Llamadas request.security() que repintanDevuelven un valor sin confirmar de la temporalidad superior en tiempo real, que cambia al reiniciarse el script
request.security() a temporalidad inferiorLas intrabarras no están ordenadas en tiempo real, así que el comportamiento en vivo no se reproduce desde el historial
Estrategias con calc_on_every_tickSe ejecutan en cada tick en tiempo real, pero solo al cierre de barra en el historial

Estas cuatro son la asimetría normal entre una barra terminada y una que no lo está. No convierten una estrategia en falsa; convierten un backtest en una aproximación, y conviene conocer el tamaño de la diferencia antes de confiar en un resultado.

Dependientes del diseño — correctas hasta que asumes lo contrario

CausaQué ocurre
Declaraciones varipMantienen estado entre actualizaciones en tiempo real de un modo que el historial no reproduce
Built-ins de estado de barrabarstate.isnew y similares se comportan distinto en tiempo real
timenowNecesariamente difiere entre una ejecución histórica y una en vivo
Variaciones del conjunto de datosDónde empieza el historial del gráfico, y las revisiones posteriores de datos, cambian los cálculos con el tiempo

La última sorprende a quien está seguro de que su script cambió cuando nada en él cambió. Un punto de inicio distinto del gráfico, o una revisión del feed, basta para mover un resultado [1].

La pregunta que hay que hacerse en cada caso

Para todas ellas la prueba útil es la misma: ¿habría tenido este valor una ejecución en vivo en ese momento? Las dos del grupo fatal responden que no. El resto responden que sí, con una diferencia de tiempo que puedes medir.


Lookahead y la fuga de futuro

request.security() acepta un parámetro lookahead con dos valores posibles [2]:

En barras históricasEn barras en tiempo real
barmerge.lookahead_off (por defecto)el último valor confirmado de la temporalidad superiorel valor actual sin confirmar del símbolo
barmerge.lookahead_onvalores de momentos posteriores a la barra en la que se ejecutael mismo valor sin confirmar que lookahead_off

Lee la segunda fila dos veces. En el historial, lookahead_on entrega al script datos del futuro. En tiempo real no puede, porque ese futuro todavía no existe, así que devuelve exactamente lo que devolvería lookahead_off.

Esa asimetría es todo el problema. La mitad histórica de la ejecución responde con información que la mitad en vivo nunca tendrá, y ambas mitades son el mismo script. El backtest no es optimista: describe una estrategia distinta.

Las palabras de TradingView: los programadores deben extremar la precaución con lookahead, especialmente en temporalidades superiores [2].

Usarlo correctamente

Lookahead no está prohibido, y hay un patrón documentado que lo hace seguro. Dos cosas juntas [2]: desplazar la expresión solicitada con el operador de historial y activar lookahead.

pine
float htfPrice = request.security(syminfo.tickerid, timeframe,
    high[1], lookahead = barmerge.lookahead_on)

El [1] es lo que lo hace correcto. Pedir el máximo de la barra anterior de la temporalidad superior, con lookahead activado, da un valor que realmente estaba disponible en ese momento: la serie se comporta igual en barras históricas y en tiempo real, y no repinta [2].

Sin el desplazamiento, esa misma llamada con lookahead_on es la fuga de futuro.

Si no escribiste tú el script

Dos comprobaciones, en orden, antes de confiar en una estrategia ajena:

  1. Busca lookahead. Si aparece barmerge.lookahead_on, localiza la expresión solicitada y confirma que está desplazada: high[1], no high.
  2. Comprueba si usa request.security() en absoluto. Si lo usa y el backtest parece extraordinario, esto es lo primero que hay que descartar.

Publicar un script que filtra datos futuros al historial no está permitido en TradingView [2], lo que indica lo común que es el error.



Tactix AI en este flujo

AlfaTactix incluye Tactix AI: usa Tactix Studio para describir tu idea en lenguaje natural y rellenar timeframes, señales, filtros y riesgo en el mismo formulario de seis pasos — o abre Tactix Guide en cualquier paso si solo necesitas explicar un campo. Revisa cada valor y luego exporta MQL5 o Pine Script desde Code Generator (form-first — no prompt-to-code sin probar).

Preguntas frecuentes

Suele ser repaint. Tester vs vivo.

Usar el futuro (p. ej. security mal). Basic sin MTF.

No en esta pista. Mapa MT5 vs TV.

Patrón de barra cerrada. v6 [2].

Tema TV. Cercano: Tester vs live MT5.