El cBot puede abrir a la misma hora escrita en el código y llegar tarde a la sesión que pretendías operar. Para probar el cambio horario en cTrader necesitas fijar qué reloj manda, convertir cada fecha con las reglas reales de su zona y aislar los periodos donde cambia la relación entre relojes.
Aquí está la idea central: una zona horaria contiene historia; un offset fijo, no. Si la hipótesis habla de una apertura local, el backtest debe reconstruir esa apertura en cada fecha en lugar de desplazar todo el histórico con una constante.
Antes de mirar trades, escribe el contrato del reloj
La regla tiene que nombrar su referencia temporal. Puede seguir UTC, la hora civil de un mercado, el horario disponible del símbolo, el reloj del servidor del broker o el día contable de una prop firm. Son contratos distintos.
UTC identifica un instante sin ambigüedad. Una hora local solo queda definida al añadir una zona y una fecha, porque su relación con UTC puede cambiar. La base de zonas horarias de IANA conserva offsets históricos y reglas de cambio horario por ubicación. También explica que las autoridades pueden modificar esas reglas con poco aviso.
Por eso una tabla manual de conversiones no es un detalle inocente. Es una fuente de datos que debes mantener, versionar y auditar.
Los errores suelen aparecer en reglas como estas:
- formar el rango inicial de una apertura;
- activar entradas tras el inicio de una sesión;
- evitar una franja local de poca liquidez;
- cerrar o reducir exposición al final del día;
- agrupar resultados según el día de la cuenta;
- bloquear operaciones alrededor de una noticia con hora local.
No mezcles este problema con la rentabilidad del horario. El artículo sobre filtros horarios en backtesting prop estudia si una franja aporta algo. La prueba de cambio horario pregunta antes si el código eligió la franja que afirmaba elegir.
Los relojes que conviven dentro de cTrader
La plataforma presenta varias capas temporales. El backtest puede tener límites UTC, el cBot trabajar en otra zona, el gráfico mostrarse con la preferencia del usuario y el símbolo aportar su propio calendario de mercado.
La referencia oficial de RobotAttribute indica que TimeZone gobierna las referencias de fecha y hora del robot y realiza la conversión a esa zona. A la vez, BacktestingSettings define en UTC el inicio y el final del periodo. No hay contradicción: una cosa delimita la muestra y otra determina cómo el algoritmo interpreta el reloj.
El ajuste horario del usuario cambia lo que ves en gráficos y datos de operaciones. La propia documentación señala que esa preferencia no controla todos los relojes de la plataforma. Ver la apertura en el sitio correcto de la pantalla no demuestra que la condición del cBot se haya evaluado con la misma referencia.
También existe MarketHours, que expone el calendario negociable del símbolo. Que un instrumento admita órdenes no significa que haya comenzado la sesión económica nombrada por tu estrategia.
| Capa temporal | Función real | Comprobación necesaria |
|---|---|---|
| Timestamp UTC | Conserva el instante histórico | ¿Se mantuvo intacta la hora del tick o la barra? |
| Zona del algoritmo | Presenta las fechas al cBot | ¿Está declarada y guardada con el run? |
| Offset visual | Ajusta la pantalla del usuario | ¿Se confundió presentación con lógica? |
| MarketHours | Describe cuándo negocia el símbolo | ¿Se dedujo una sesión solo porque el mercado estaba abierto? |
| Día de cuenta prop | Agrupa actividad bajo una regla externa | ¿Se verificó la convención vigente en la fuente de la firma? |
Una prueba corta que encuentra fallos grandes
Empieza congelando versión del cBot, feed, símbolo, parámetros, sizing, costes y límites del periodo. Registra la zona declarada por el algoritmo y la versión de los datos horarios cuando el entorno te permita consultarla.
Después crea una tabla de referencia fuera del cBot. Para cada fecha debe incluir el instante UTC y la etiqueta local esperada de la sesión. Utiliza una biblioteca consciente de zonas horarias y reglas mantenidas; sumar siempre el mismo offset recrea precisamente el defecto que quieres detectar.
Contrasta esa tabla con:
- la primera y la última barra aceptadas por el filtro;
- la hora UTC de señales, órdenes y fills;
- las posiciones que atravesaron el cambio de reloj;
- la equity flotante cerca del límite de sesión;
- las etiquetas locales ausentes o repetidas en el log;
- cualquier cancelación ejecutada en el borde temporal.
No te quedes con la curva de todo el periodo. Separa bloques de offset estable, ventanas de transición y semanas en las que las regiones relevantes no cambian su reloj al mismo tiempo. Ese último grupo descubre enseguida si el código modeló dos sesiones o se limitó a asumir una distancia constante entre ellas.
Cuando la señal depende del interior de una barra, revisa esos bordes con suficiente resolución. Tener bien la zona no corrige una simulación que desconoce el recorrido intrabar; son defectos diferentes. La comparación de backtesting al cierre de barra e intrabar desarrolla esa segunda capa.
El control negativo que merece conservarse
Ejecuta la estrategia congelada con una conversión por zona, con un offset UTC fijo y con una regla puramente UTC. Añade además una variante que mueva el borde una barra a cada lado. No estás buscando la curva más bonita. Estás midiendo cuándo empiezan a divergir implementaciones que dicen representar la misma idea.
| Variante | Qué representa | Cómo leerla |
|---|---|---|
| Zona con reglas fechadas | La hora civil histórica | Referencia para una sesión local |
| Offset UTC fijo | Una relación constante durante toda la muestra | Control negativo alrededor de algunos cambios |
| Regla UTC pura | Una hipótesis que no sigue hora civil | Válida si así fue escrita desde el principio |
| Borde desplazado | Error de alineación de una barra | Sensibilidad del trigger temporal |
Localiza el primer timestamp que produce trades distintos. Ese punto explica el fallo mejor que comparar dos retornos finales. Después revisa visualmente algunos bordes. La guía de backtesting de cBots documenta los modos visual y no visual; el replay no aporta evidencia estadística, pero sí delata una condición que se activa sobre la barra equivocada.
El resultado correcto también tiene límites
Una conversión histórica correcta demuestra que el código escogió las horas previstas. No demuestra que exista edge en esa sesión, que la legislación horaria futura permanezca igual ni que el broker conserve el calendario del símbolo.
Tampoco confirma por sí sola cómo calcula una prop firm su pérdida diaria. Esa definición es externa y puede variar. El modelo de fondeo muestra por qué hay que enfrentar la ruta de la cuenta con la restricción pertinente, pero la firma sigue siendo la autoridad sobre su reloj de reset vigente.
realbacktesting es un estudio de software de trading para cTrader centrado en pruebas reproducibles e inspeccionables. La página de metodología publica los supuestos sobre datos, ejecución, costes y validación. Una estrategia de sesión necesita añadir ahí su definición temporal; sin ella, otro trader no puede reconstruir el mismo test.
Dudas frecuentes
¿Es mejor programar una sesión de cTrader en UTC?
Depende de la hipótesis. Si la regla sigue un evento local, convierte desde su zona con reglas fechadas; si fue definida expresamente en UTC, mantenla en UTC.
¿Cambiar la hora del gráfico modifica la lógica del cBot?
No lo des por hecho. cTrader trata el offset del usuario como presentación, mientras que la zona declarada por el robot controla sus referencias datetime.
¿Por qué no basta un offset constante?
Porque representa una sola relación con UTC. Una sesión civil que cambia de offset puede caer en otra ventana histórica aunque el número escrito en el filtro parezca idéntico.
¿Qué periodos conviene auditar aparte?
Las transiciones y las semanas de desfase entre regiones concentran los casos que exponen el problema. En el informe agregado, unos pocos trades mal ubicados pueden quedar diluidos.
Veredicto
Una estrategia de sesión empieza por definir el reloj. Si la zona queda implícita, el cambio horario cambia la regla sin tocar una línea del cBot.