Sintaxis de la cadena de sesión y sus dos trampas
Una cadena de sesión basada en tiempo es <periodo>:<días> [1].
El periodo es HHmm-HHmm en reloj de 24 horas, y pueden separarse varios por
comas. La parte de días son dígitos, y omitirla significa todos los días.
| Cadena | Significa [1] |
|---|---|
"0930-1700" | de 09:30 a 17:00, todos los días |
"0800-0900,1230-1630" | dos ventanas separadas en un día |
"0930-1700:146" | domingos, miércoles y viernes |
"1700-1630:23456" | una sesión nocturna, de lunes a viernes |
"24x7" | lo mismo que "0000-0000:1234567" |
Trampa uno: el 1 es domingo
Los días se numeran del 1 al 7 para domingo a sábado [1]. No de lunes a domingo.
Así que la forma instintiva de escribir «solo días laborables» — :12345 — en
realidad selecciona domingo a jueves. Incluye un día en que la mayoría de
mercados están cerrados y excluye el viernes, uno de los más activos. Lunes a
viernes es :23456.
Nada da error. El filtro funciona, en los días equivocados, y el backtest mide una estrategia que no diseñaste.
Trampa dos: la zona horaria es la del exchange, no la de tu gráfico
Las horas de sesión se interpretan en la zona horaria del exchange salvo que
pases un argumento timezone, y eso es distinto de la zona horaria que muestra
tu gráfico [1].
Si pones el gráfico en hora local, lees 08:00 en el eje y escribes
"0800-1600", has filtrado de 08:00 a 16:00 en hora del exchange. En un
símbolo de renta variable estadounidense visto desde Europa, eso es una ventana
en tu tarde y tu noche.
Esta conviene probarla en lugar de razonarla: dibuja el filtro y comprueba qué barras conserva realmente.
Solo tres funciones aceptan estas cadenas
time(), time_close() e input.session() son las únicas funciones que
aceptan una cadena de sesión basada en tiempo [1]. request.*() no: necesita
una sesión con nombre, mediante ticker.new() o ticker.modify() con
session.regular o session.extended.
// na fuera de la sesión, una marca de tiempo dentro
inSession = not na(time(timeframe.period, "0930-1600:23456"))
Alinea la sesión con tus barras
TradingView lo indica directamente: alinea las horas de inicio y fin de una sesión basada en tiempo con las de las barras del gráfico en la temporalidad que esperas [1]. Un límite de sesión que cae a mitad de barra produce resultados que parecen arbitrarios, porque lo son.
Estado de sesión, ATR y filtros de liquidez
Más allá de la sintaxis, Pine expone la sesión como estado que puedes leer directamente [1]:
| Variable | Verdadera cuando |
|---|---|
session.ismarket | dentro del horario regular |
session.ispremarket | en el horario extendido previo |
session.ispostmarket | en el horario extendido posterior |
session.isfirstbar | primera barra de la sesión del día |
session.isfirstbar_regular | primera barra de la sesión regular |
session.islastbar | última barra de la sesión del día |
session.islastbar_regular | última barra de la sesión regular |
Las variables de última barra pueden no activarse nunca
Está documentado y es importante: session.islastbar y
session.islastbar_regular podrían no ser true en ninguna barra de una
sesión si no hay actualizaciones de precio o volumen durante el periodo de esa
última barra [1].
Así que una estrategia que cierra su posición en la última barra puede, en un día tranquilo y un instrumento poco líquido, simplemente no cerrar. Nada da error, la posición pasa la noche abierta y el registro no da ninguna razón.
Si cerrar al final de la sesión es un requisito y no una preferencia, controla
la propia ventana de sesión — que not na(time(...)) pase a falso — en lugar de
confiar en que llegue una marca de última barra.
El horario extendido no es lo que supones en futuros
En la mayoría de futuros estadounidenses, el Electronic Trading Hours es la
sesión «regular» por defecto, y session.extended equivale a
session.regular [1]. Un filtro escrito para excluir el «horario extendido» en
un símbolo de futuros puede por tanto no excluir nada.
Filtros de volatilidad y liquidez
Un filtro de sesión responde cuándo. Un filtro de volatilidad responde si el mercado se mueve lo suficiente para que las suposiciones de la estrategia se sostengan — una regla de reversión a la media y una de ruptura quieren respuestas opuestas.
La forma honesta de construirlo es relativa, no absoluta. El ATR está denominado en el precio del instrumento, así que un umbral fijo no significa nada entre instrumentos ni entre periodos del mismo instrumento. Compara el ATR con su propia media reciente:
atrValue = ta.atr(14)
atrBaseline = ta.sma(atrValue, 100)
expanding = atrValue > atrBaseline
Esa comparación se transfiere. Un número publicado como «ATR por encima de 1,5» no, y cualquier artículo que te dé uno no ha pensado en el instrumento que operas.
La misma lógica vale para los filtros de volumen: compara el volumen con su propia media y no con una constante, porque una constante codifica la liquidez del instrumento que el autor tenía delante.
Combinar filtros te cuesta muestra
Cada filtro añadido elimina operaciones. Eso mejora las estadísticas sobre el papel y reduce a la vez la evidencia que las sostiene: una estrategia con 400 operaciones y una ventaja modesta es evidencia más fuerte que una con 25 y una espectacular. Vigila el número de operaciones al añadir filtros, no solo el rendimiento.
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).

