De novato a experto: Sincronizador de períodos de mercado
Contenido
Introducción
Comprender las limitaciones de la visualización del período estándar en MetaTrader 5
Al analizar gráficos en marcos temporales superiores, como D1 o H4, los operadores suelen observar formaciones de velas japonesas que tienen un significado importante; por ejemplo, patrones Doji, Martillo o Envolvente Alcista. Sin embargo, estas velas de marcos temporales superiores representan la agregación de muchas velas más pequeñas y, como tales, ocultan con precisión cómo se movió el precio dentro de marcos temporales inferiores.
Cambiar el gráfico de un marco temporal superior a uno inferior no conserva la disposición visual de esos períodos más amplios. En consecuencia, los operadores pierden la capacidad de identificar fácilmente cómo evolucionó el precio dentro de cada vela principal; por ejemplo, dónde cambió el impulso o se produjo una consolidación dentro de una barra de un marco temporal superior.
Si bien MetaTrader 5 ofrece una opción integrada para mostrar separadores de períodos, esta función es estática y de alcance limitado. Resulta especialmente inadecuada cuando se trabaja con periodos inferiores a un día o cuando los operadores necesitan un mayor control sobre cómo se muestran estos periodos.
Presentamos el indicador sincronizador de períodos de mercado
Para superar esta limitación, presentamos una solución personalizada llamada Market Periods Synchronizer, un indicador desarrollado en MQL5 que permite la personalización completa de los marcadores de período verticales en múltiples marcos temporales. Esta herramienta sincroniza visualmente los límites de período de marcos temporales superiores dentro de los gráficos de marcos temporales inferiores, lo que permite a los operadores estudiar la acción del precio dentro del período en detalle, manteniendo al mismo tiempo el contexto del marco temporal superior.
Mediante este enfoque, los usuarios pueden:
- Visualice y codifique por colores los marcadores para múltiples marcos temporales superiores simultáneamente.
- Analice cómo las velas más pequeñas forman estructuras más grandes a lo largo de las diferentes fases del mercado.
- Personaliza los intervalos, la visibilidad y las combinaciones de colores de los marcadores.
- Resalte y rellene los cuerpos de las velas de marcos temporales superiores.
- Marcar líneas horizontales de precio de apertura y cierre para cada período superior.
- Limitar el dibujo al rango visible del gráfico (opción de rendimiento).
- Utilice varios intervalos menores que no se superpongan con los mayores.
La siguiente imagen muestra la visualización predeterminada de MetaTrader 5 antes de la mejora, lo que pone de manifiesto la carencia que el Sincronizador de Períodos de Mercado está diseñado para subsanar.

Figura 1: Configuración de los separadores de período predeterminados en MetaTrader 5
En la fase de implementación, nuestro objetivo es diseñar el indicador Sincronizador de Períodos de Mercado haciendo hincapié tanto en la claridad visual como en la profundidad analítica. Esta herramienta permitirá a los operadores explorar visualmente la evolución del precio dentro de cada barra, como por ejemplo cómo se forman las velas M1 o M5 dentro de una barra H1 o D1, revelando los cambios de impulso, los rechazos y las microestructuras que componen los patrones de marcos temporales superiores. Una ventaja clave de este diseño es que los usuarios también podrán observar la acción del precio de la mecha extendiéndose más allá de los cuerpos de las velas de marcos temporales superiores, lo que ofrece nuevas perspectivas sobre la volatilidad y el comportamiento de rechazo que dan forma a esas velas más grandes.
El indicador mostrará los límites de los marcos temporales principales y los intermedios (secundarios) opcionales en un único gráfico de marco temporal inferior, cada uno con un color y un estilo de línea independientes para una clara separación visual. Los usuarios pueden elegir qué periodos de tiempo mostrar, establecer la profundidad del historial y activar o desactivar series individuales, a la vez que personalizan los colores, los anchos y los estilos de línea para que coincidan con sus preferencias analíticas.
Para mejorar la interpretación, el sistema incluirá una opción para rellenar el rango de precios de cada vela de marco temporal superior (alcista, bajista o neutral) y para dibujar líneas horizontales cortas para los niveles de apertura y cierre, lo que ayudará a los operadores a estudiar los puntos de inflexión y las zonas de reacción dentro del período. Para garantizar un funcionamiento óptimo, el indicador optimizará las operaciones de dibujo dibujando únicamente los marcadores que se encuentren dentro de la ventana del gráfico visible actualmente, lo cual es especialmente importante al analizar grandes periodos de tiempo en gráficos M1 o M5. Finalmente, la implementación garantizará que los marcadores de intervalos de tiempo intermedios se posicionen estrictamente entre límites principales consecutivos, evitando cualquier superposición u obstrucción de los marcadores principales.
Implementación
Este indicador utiliza un búfer de trazado ficticio (para silenciar las advertencias de MetaTrader 5) y controla todos los elementos visuales con objetos de gráfico (OBJ_VLINE, OBJ_TEXT, etc.). Un temporizador actualiza los objetos periódicamente para que el indicador se actualice correctamente incluso cuando se adjunta a gráficos de marcos temporales bajos. La rutina principal es RefreshLines(), que copia los tiempos de las barras de marcos temporales superiores y crea/elimina objetos según corresponda. Las funciones auxiliares se encargan de la limpieza de objetos.
1. Encabezado del archivo y gráfico ficticio (metadatos)
Declaramos los metadatos del indicador y un búfer de trazado ficticio. En MQL5, un indicador debe implementar OnCalculate(), y normalmente se crean búferes de trazado que la terminal dibuja. Nuestra herramienta no dibuja datos de series temporales de precios; dibuja objetos gráficos (líneas verticales, rectángulos y texto). Pero el compilador y la terminal aún esperan al menos una definición de búfer/gráfico para un indicador. El truco habitual consiste en declarar un único búfer "ficticio", establecer su valor PLOT_EMPTY_VALUE en EMPTY_VALUE y nunca asignarle valores significativos. De esta forma, el indicador se considera válido en la terminal, pero no genera ninguna representación visible del búfer. Este patrón evita las advertencias al tiempo que nos permite gestionar los elementos visuales exclusivamente con objetos de gráfico.
Algunos detalles de MQL5 que conviene tener en cuenta:
- La propiedad #property indicator_chart_window indica a MetaTrader 5 que adjunte el indicador al gráfico de precios principal (de modo que los objetos se alineen con el eje de precios).
- Mantén el búfer ficticio simple y márcalo como INDICATOR_DATA al llamar a SetIndexBuffer.
- Llame siempre a ArraySetAsSeries() en OnCalculate() para los buffers que están indexados como las series de precios (0 = más reciente); lo mostraremos más adelante.
//+------------------------------------------------------------------+ //| MarketPeriodsSynchronizer.mq5 | //+------------------------------------------------------------------+ #property copyright "Clemence Benjamin" #property version "1.01" #property indicator_chart_window // Dummy buffer to satisfy MT5 (we draw with chart objects) #property indicator_buffers 1 #property indicator_plots 1 #property indicator_label1 "HiddenDummy" #property indicator_type1 DRAW_LINE #property indicator_width1 1 #property indicator_color1 clrSilver double PlotDummyBuffer[];
2. Parámetros de entrada
Los parámetros de entrada constituyen la API pública del indicador. Cuando declaras variables de entrada, MetaTrader crea campos de interfaz de usuario para ellas (en el cuadro de diálogo del indicador) y los configura como de solo lectura en tiempo de ejecución. Dado que las variables de entrada son constantes en el código, copiamos cualquier valor que pueda necesitar un ajuste interno en variables globales mutables (por ejemplo, g_lookback). Esta separación evita la modificación accidental de los valores de entrada, al tiempo que mantiene la flexibilidad de las variables en tiempo de ejecución para su optimización.
Puntos clave para cada tipo de entrada:
- ENUM_TIMEFRAMES: constantes tipadas muy prácticas para marcos de tiempo (PERIOD_M15, PERIOD_H1, etc.). Se compilan a números enteros, pero son más fáciles de leer.
- Colores: MQL5 acepta constantes de color con nombre (por ejemplo, clrRed) o valores ARGB enteros; los colores con nombre son más seguros para la legibilidad.
- Estilos de línea: las constantes de estilo, como STYLE_SOLID y STYLE_DASH, son constantes enteras; declare la entrada como int para un comportamiento robusto en diferentes terminales.
- Parámetros de rendimiento: InpLookback controla cuántas barras HTF copiamos. Un análisis retrospectivo amplio en M1/M5 puede resultar costoso; considere un valor predeterminado conservador (200) y agregue la optimización del rango visible más adelante.
- Las opciones booleanas para habilitar/deshabilitar funciones opcionales (rellenos, marcadores menores, líneas de apertura/cierre) permiten al usuario equilibrar riqueza visual y rendimiento.
//--- inputs (Major) input ENUM_TIMEFRAMES InpHigherTF = PERIOD_H1; // Major higher timeframe to mark input int InpLookback = 200; // How many higher-TF bars to draw input color InpColorMajor = clrRed; // Major line color input int InpWidthMajor = 2; // Major line width input int InpRefreshSec = 5; // Refresh interval in seconds //--- inputs (Open/Close horizontals for Major) input bool InpShowOpenClose = true; // Show open/close horizontal markers? input color InpColorOpen = clrGreen; // Open line color input color InpColorClose = clrLime; // Close line color input int InpWidthOC = 1; // Open/Close line width input int InpStyleOC = STYLE_DASH;// Open/Close line style (integer) input int InpHorizOffsetBars = 3; // Horizontal length in current TF bars //--- inputs (Body fill for Major) input bool InpShowFill = true; // Show body fill? input color InpFillBull = clrLime; // Bullish fill color input color InpFillBear = clrTomato; // Bearish fill color //--- inputs (Minor 1) input bool InpShowMinor1 = false; // Show intermediate Minor 1? input ENUM_TIMEFRAMES InpMinor1TF = PERIOD_M30; // Minor1 TF (default M30) input color InpColorMin1 = clrOrange; // Minor1 color input int InpWidthMin1 = 1; // Minor1 width //--- inputs (Minor 2) input bool InpShowMinor2 = false; // Show intermediate Minor 2? input ENUM_TIMEFRAMES InpMinor2TF = PERIOD_M15; // Minor2 TF (default M15) input color InpColorMin2 = clrYellow; // Minor2 color input int InpWidthMin2 = 1; // Minor2 width
3. Buffers, copias mutables y convenciones de nomenclatura
Una buena nomenclatura y un estado controlado hacen que el código sea mantenible y robusto. Algunos principios:
- Búfer ficticio: Declaramos PlotDummyBuffer[] anteriormente; nunca dibuja nada (lo llenaremos con EMPTY_VALUE).
- Copias mutables: g_lookback refleja a InpLookback, pero se puede ajustar internamente (por ejemplo, limitar).
- Prefijos para objetos: El uso de prefijos consistentes (por ejemplo, HTF_MAJ_, HTF_MIN1_) evita conflictos de nombres con otros objetos del gráfico y facilita la limpieza (busque "HTF_" al eliminar).
- Ciclo de vida de los arrays: utilice ArrayFree() antes de CopyTime() para asegurarse de que los arrays estén vacíos; utilice ArrayResize() para dimensionar los arrays cuando desee escribir por índice. ArraySetAsSeries() afecta al orden de los índices (0 = el más reciente); sea explícito sobre la orientación al leer/escribir matrices.
//--- indicator buffer (dummy) double PlotDummyBuffer[]; // mutable working copy of input(s) int g_lookback = 200; // name prefixes static string PREFIX_MAJ = "HTF_MAJ_"; static string PREFIX_MIN1 = "HTF_MIN1_"; static string PREFIX_MIN2 = "HTF_MIN2_";
4. Inicialización (OnInit): mecanismo del ciclo de vida y seguridad
OnInit() es el lugar para configurar: enlazar búferes, establecer PLOT_EMPTY_VALUE, copiar/validar entradas, establecer temporizadores y realizar el primer dibujo. Detalles importantes y posibles problemas:
- SetIndexBuffer(0, PlotDummyBuffer, INDICATOR_DATA) vincula el búfer al índice 0. INDICATOR_DATA es el indicador común para los búferes de indicadores.
- PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE) le indica a la terminal que EMPTY_VALUE significa "no hay gráfico"; al escribir EMPTY_VALUE en el búfer, el gráfico permanece invisible.
- EventSetTimer(MathMax(1, InpRefreshSec)) registra una devolución de llamada periódica a OnTimer(). Elija un tiempo mínimo razonable (1 segundo) para evitar sobrecargar la CPU. Recuerda llamar a EventKillTimer() en OnDeinit().
- Realiza una primera llamada a RefreshLines() para que el gráfico se sincronice inmediatamente después de la inicialización.
int OnInit() { SetIndexBuffer(0, PlotDummyBuffer, INDICATOR_DATA); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE); // copy input to mutable g_lookback = (InpLookback <= 0 ? 200 : InpLookback); // set timer (minimum 1s) EventSetTimer(MathMax(1, InpRefreshSec)); // initial draw RefreshLines(); return(INIT_SUCCEEDED); }
5. Desinicialización y temporizador: salida limpia y actualización controlada.
Finaliza correctamente el temporizador en OnDeinit() para que la terminal no deje temporizadores huérfanos, que pueden seguir llamando a OnTimer() después de que el indicador haya desaparecido. La función OnTimer() debe ser ligera: simplemente llama a RefreshLines() para mantener los objetos actualizados. Si posteriormente añades operaciones pesadas (entrada/salida de archivos, red), inclúyelas en comprobaciones para que OnTimer() siga siendo económico.
void OnDeinit(const int reason) { EventKillTimer(); // Optionally remove objects: // DeleteAllHTFLines(); } void OnTimer() { RefreshLines(); }
6. Mínimo OnCalculate: cumplimiento del modelo indicador y orientación del búfer
MetaTrader 5 espera que se llame a OnCalculate() para cada indicador. Aunque no utilicemos búferes para el dibujo, debemos implementarlo igualmente. Algunos conceptos importantes de MQL5 para los lectores:
- ArraySetAsSeries(array, true) establece la orientación de la serie donde el índice 0 es la barra más reciente. Esto es crucial si indexa matrices usando desplazamientos de barra (desplazamiento=0 barra actual).
- prev_calculated indica cuántas barras se calcularon previamente. Úselo para inicializarlo solo una vez y rellenar las barras añadidas recientemente con EMPTY_VALUE para mantener oculto el trazado ficticio.
- Siempre devuelva rates_total (el número de barras procesadas) al final; MetaTrader 5 utiliza el valor devuelto para establecer prev_calculated en la siguiente llamada.
int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { // make the dummy buffer a series (0 = newest) ArraySetAsSeries(PlotDummyBuffer, true); // initialize to EMPTY_VALUE so no visible plot appears if(prev_calculated < 1) ArrayInitialize(PlotDummyBuffer, EMPTY_VALUE); else { int to_fill = rates_total - prev_calculated; if(to_fill > 0) for(int i = 0; i < to_fill && i < rates_total; ++i) PlotDummyBuffer[i] = EMPTY_VALUE; } return(rates_total); }
7. Rutina principal: RefreshLines() con optimización del rango visible.
Esta es la función más importante. Explicaré los pasos, los problemas típicos de MQL5 e incluiré una implementación optimizada que restringe los marcadores a la ventana del gráfico visible (una gran mejora de rendimiento en M1/M5 con grandes periodos de análisis retrospectivo).
¿Por qué optimizar el rango visible?
Copiar historiales largos de HTF y crear cientos o miles de objetos gráficos en un marco temporal corto resulta costoso. Si el usuario solo está viendo una pequeña parte del historial, solo debe crear objetos que se encuentren dentro del intervalo de tiempo visible. MetaTrader 5 proporciona ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR) (índice de la primera barra visible) y ChartGetInteger(0, CHART_WIDTH_IN_BARS) (número de barras visibles); estos permiten calcular time_from y time_to en el marco temporal del gráfico actual y luego filtrar las marcas de tiempo HTF a ese intervalo.
Funciones importantes de MQL5 utilizadas:
- CopyTime(symbol, timeframe, start_shift, count, array): copia las marcas de tiempo del intervalo de tiempo especificado. Devuelve el número de elementos copiados. Nota: los resultados se muestran del más reciente al más antiguo (desplazamiento 0 = más reciente), por lo que normalmente invertimos el orden para mostrar los resultados del más antiguo al más antiguo en las comparaciones de intervalos.
- CopyOpen, CopyClose: similar a CopyTime pero copia los precios de apertura/cierre.
- PeriodSeconds(tf): devuelve el número de segundos en un intervalo de tiempo determinado (útil para calcular las horas de finalización del período).
- ObjectCreate(chart_id, name, type, sub_window, time1, price1, time2, price2): diferentes objetos requieren diferentes listas de parámetros:
- OBJ_VLINE: se aceptan time1 y price, pero solo importa el tiempo.
- OBJ_RECTANGLE: requiere (time1, price1, time2, price2): utilice low/high, open/close según corresponda.
- OBJ_TREND necesita dos puntos (time1, price1, time2, price2).
Manejo de errores:
- Compruebe siempre el valor de retorno de ObjectCreate() y llame a GetLastError() para registrar/diagnosticar los fallos de creación.
- Utilice ObjectFind() (devuelve el índice o -1) para comprobar la existencia antes de crearlo; esto evita duplicados.
Implementación (optimizada para el rango visible)
- Consulta CHART_FIRST_VISIBLE_BAR y CHART_WIDTH_IN_BARS para calcular t_from y t_to usando iTime() en el marco temporal del gráfico actual.
- Copia los tiempos HTF usando CopyTime pero sigue limitándolos con g_lookback; opcionalmente puedes reducir g_lookback a la cantidad requerida por el rango visible.
- Filtrar los tiempos HTF: solo se crean objetos para las marcas de tiempo HTF que se intersecan en [t_from - period_seconds, t_to + period_seconds] (añadir un pequeño margen para capturar objetos exactamente en el límite).
//--- helper: get visible chart time range (returns false if couldn't obtain) bool GetVisibleTimeRange(datetime &time_from, datetime &time_to) { // ChartGetInteger uses constants CHART_FIRST_VISIBLE_BAR and CHART_WIDTH_IN_BARS long first_visible = ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR); long visible_bars = ChartGetInteger(0, CHART_WIDTH_IN_BARS); if(first_visible < 0 || visible_bars <= 0) return(false); // first_visible is index in the time series (0 = newest) // iTime(symbol,period,shift) expects shift as bar index time_from = iTime(_Symbol, _Period, (int)first_visible); // time of first visible bar (leftmost) int last_index = (int)(first_visible + visible_bars - 1); // index of rightmost visible bar time_to = iTime(_Symbol, _Period, last_index); // time of last visible bar (rightmost) // If iTime returns 0 or invalid, fail gracefully if(time_from == 0 || time_to == 0) return(false); return(true); } //--- RefreshLines with visible-range filter void RefreshLines() { // determine visible chart time window (optional optimization) datetime vis_from = 0, vis_to = 0; bool have_vis = GetVisibleTimeRange(vis_from, vis_to); // optional: expand the visible window by one HTF period on each side uint64 ht_period_secs = (uint64)PeriodSeconds(InpHigherTF); datetime vis_from_margin = (have_vis ? vis_from - (int)ht_period_secs : 0); datetime vis_to_margin = (have_vis ? vis_to + (int)ht_period_secs : 0); // copy HTF times (newest-first) datetime major_times[]; ArrayFree(major_times); int copiedMaj = CopyTime(_Symbol, InpHigherTF, 0, g_lookback, major_times); if(copiedMaj <= 0) return; // copy opens & closes (same count) double major_opens[], major_closes[]; if(CopyOpen(_Symbol, InpHigherTF, 0, copiedMaj, major_opens) != copiedMaj || CopyClose(_Symbol, InpHigherTF, 0, copiedMaj, major_closes) != copiedMaj) return; // reverse to ascending order (oldest-first) — easier for interval checks datetime sorted_times[]; ArrayResize(sorted_times, copiedMaj); double sorted_opens[]; ArrayResize(sorted_opens, copiedMaj); double sorted_closes[]; ArrayResize(sorted_closes, copiedMaj); for(int k = 0; k < copiedMaj; ++k) { sorted_times[k] = major_times[copiedMaj - 1 - k]; sorted_opens[k] = major_opens[copiedMaj - 1 - k]; sorted_closes[k] = major_closes[copiedMaj - 1 - k]; } // Build keep-list (only include HTF entries in the visible window when available) string keepNames[]; ArrayResize(keepNames, 0); for(int i = 0; i < ArraySize(sorted_times); ++i) { datetime t = sorted_times[i]; // If we have a visible window, skip majors outside it (margin added) if(have_vis && (t < vis_from_margin || t > vis_to_margin)) continue; // create/vet major VLINE string name = PREFIX_MAJ + EnumToString(InpHigherTF) + "_" + IntegerToString((int)t); if(ObjectFind(0, name) == -1) { double dummy_price = 0.0; if(!ObjectCreate(0, name, OBJ_VLINE, 0, t, dummy_price)) PrintFormat("Failed to create major %s error %d", name, GetLastError()); else { ObjectSetInteger(0, name, OBJPROP_COLOR, InpColorMajor); ObjectSetInteger(0, name, OBJPROP_WIDTH, InpWidthMajor); ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, name, OBJPROP_HIDDEN, false); } } // push to keepNames int sz = ArraySize(keepNames); ArrayResize(keepNames, sz+1); keepNames[sz] = name; // (rest: fills, open/close trend lines, and adding their names to keepNames) // ... same logic as before, but guarded by have_vis if you want to only create their labels when visible. } // Cleanup: delete HTF_ objects not in keepNames[] int total = ObjectsTotal(0); for(int idx = total - 1; idx >= 0; --idx) { string oname = ObjectName(0, idx); if(StringFind(oname, "HTF_") != -1) { bool found = false; for(int k = 0; k < ArraySize(keepNames); ++k) if(oname == keepNames[k]) { found = true; break; } if(!found) ObjectDelete(0, oname); } } }
8. DrawMinorsBetweenIntervals
La función de este asistente es insertar marcadores de intervalos de tiempo intermedios (menores) solo donde corresponda, estrictamente entre marcas de tiempo principales consecutivas. Detalles y decisiones de implementación:
- Leemos todos los tiempos TF menores a través de CopyTime() (del más reciente al más antiguo) y luego invertimos para la lógica de intervalos.
- Para cada marca de tiempo menor mt, primero verificamos si es igual a alguna marca de tiempo mayor (omitimos las coincidencias exactas).
- Luego localizamos el intervalo j donde major[j] < mt < major[j+1]. Dado que los marcas temporales principales son ascendentes, un escaneo lineal es fácil y fiable.
- Cuando hay muchas marcas temporales menores, es posible que desee acelerar este proceso de la siguiente manera:
- Utilizando búsqueda binaria (ArrayBsearch) si major_times es grande y está ordenado (lo está),
- O construir un único paso a través de las ramas principales y secundarias simultáneamente (fusión-unión) para lograr una complejidad O(n) en lugar de O(n*m).
- Mantenga actualizada la lista de nombres para garantizar que la limpieza se realice correctamente.
void DrawMinorsBetweenIntervals(const string prefix, const ENUM_TIMEFRAMES minorTF, const color c, const int width, const datetime &major_times[], string &keepNames[]) { datetime minor_times[]; int copiedMin = CopyTime(_Symbol, minorTF, 0, g_lookback, minor_times); if(copiedMin <= 0) return; // Reverse to ascending (oldest-first) datetime sorted_minor_times[]; ArrayResize(sorted_minor_times, copiedMin); for(int k = 0; k < copiedMin; ++k) sorted_minor_times[k] = minor_times[copiedMin - 1 - k]; // Merge-like linear pass (more efficient than nested loops) — optional improvement: // if you expect many entries, implement two-pointer merge; below is the simpler approach. for(int m = 0; m < copiedMin; ++m) { datetime mt = sorted_minor_times[m]; // skip if equals any major time (linear check) bool equals_major = false; for(int kk = 0; kk < ArraySize(major_times); ++kk) if(major_times[kk] == mt) { equals_major = true; break; } if(equals_major) continue; // find interval where mt belongs bool placed = false; for(int j = 0; j < ArraySize(major_times)-1; ++j) { if(major_times[j] < mt && mt < major_times[j+1]) { string name = prefix + EnumToString(minorTF) + "_" + IntegerToString((int)mt); if(ObjectFind(0, name) == -1) { if(ObjectCreate(0, name, OBJ_VLINE, 0, mt, 0.0)) { ObjectSetInteger(0, name, OBJPROP_COLOR, c); ObjectSetInteger(0, name, OBJPROP_WIDTH, width); ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_DOT); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, name, OBJPROP_HIDDEN, false); } } // add to keepNames int sz = ArraySize(keepNames); ArrayResize(keepNames, sz+1); keepNames[sz] = name; placed = true; break; } } if(!placed) continue; } }
9. Limpieza y gestión de objetos
Al eliminar únicamente los objetos con nuestro prefijo, se evita la eliminación accidental de objetos de usuarios u otros indicadores. Algunas consideraciones adicionales:
- Prefiera usar ObjectFind(0, name) antes de llamar a ObjectCreate() para evitar duplicados.
- Utilice GetLastError() después de un error en ObjectCreate() para la depuración.
- Si su indicador crea muchos objetos, considere agruparlos por prefijo y, opcionalmente, almacenar un único "objeto de índice" maestro (texto pequeño) que contenga una lista de nombres creados separados por comas para realizar comprobaciones de existencia más rápidas; aunque la técnica keepNames[] que se muestra aquí suele ser suficiente.
void DeleteAllHTFLines() { int total = ObjectsTotal(0); for(int idx = total - 1; idx >= 0; --idx) { string oname = ObjectName(0, idx); if(StringFind(oname, "HTF_") != -1) ObjectDelete(0, oname); } }
Pruebas
Tras compilar la herramienta, probarla es muy sencillo: busque Market Periods Synchronizer en la carpeta Indicators del Navegador de MetaTrader 5 y adjúntelo a cualquier gráfico. Todas las funciones se pueden configurar desde los parámetros de entrada del indicador; por ejemplo, se puede elegir el marco temporal principal utilizado para los marcadores de período, establecer la profundidad del historial y ajustar los colores y los anchos. También puede habilitar marcadores intermedios opcionales y seleccionar sus intervalos de tiempo para que aparezcan estrictamente entre límites principales consecutivos.
El nombre Market Periods Synchronizer refleja el propósito de la herramienta: vincula visualmente la estructura de marcos temporales superiores con la acción del precio en marcos temporales inferiores. En la práctica, esto significa que puedes relacionar las mechas de marcos temporales superiores con las velas de marcos temporales inferiores exactas que las produjeron, lo que te permite inspeccionar cómo se formaron esas mechas (rechazos, colas, picos intrabarra, etc.). Las ilustraciones que aparecen a continuación muestran resultados típicos y ejemplos de configuración de entrada utilizados durante nuestras pruebas.

Figura 2: Configuración de parámetros del sincronizador de períodos de mercado

Figura 3: Agregar el indicador Sincronizador de períodos de mercado al gráfico

Figura 4: Tendencias formadas por los rellenos de períodos H1.
En la Figura 4, nuestro Sincronizador de Períodos de Mercado etiqueta la apertura y el cierre de cada período principal, lo que nos permite observar las tendencias emergentes a una escala más precisa. Dentro de cada intervalo marcado, la acción del precio en el marco temporal inferior se hace claramente visible, revelando cómo evoluciona la estructura intrabarra dentro de los límites de las velas del marco temporal superior.
Esto crea una visión de doble perspectiva, en la que los operadores pueden analizar simultáneamente tanto el contexto general de la tendencia como los micromovimientos detallados que la conforman. Los rellenos de color sirven como una abstracción visual de las velas japonesas de marcos temporales superiores, transformando eficazmente el gráfico en una representación multicapa del comportamiento del mercado.

Figura 5: Etiquetado de las partes de las velas
La figura 5 ilustra el etiquetado de una región delimitada por líneas rojas, que representa un único período horario. Esta sección funciona de forma muy similar a una vela japonesa ampliada: engloba la apertura, el cierre, el cuerpo, la mecha superior y la mecha inferior de una barra de un marco temporal superior. Dentro de esta zona delimitada, los operadores pueden interpretar el movimiento de los precios de la misma manera analítica que lo harían con los componentes tradicionales de las velas japonesas. En esencia, cada período resaltado sirve como una reconstrucción visual de una vela japonesa de un marco temporal superior, lo que permite un examen más detallado de cómo su estructura fue formada por las fluctuaciones de marcos temporales inferiores.
Conclusión
Hemos transformado con éxito una idea conceptual en una herramienta analítica totalmente funcional gracias al poder de la programación MQL5. El indicador Market Periods Synchronizer aporta una nueva dimensión al análisis de gráficos, ya que permite a los operadores visualizar estructuras de marcos temporales superiores e inferiores de forma conjunta en una interfaz integrada. Sincroniza visualmente los periodos del mercado en múltiples marcos temporales, lo que permite identificar claramente cómo las velas más pequeñas contribuyen a la formación de las principales fases del mercado y las estructuras de tendencia. Esta innovación subsana una carencia de larga data en las capacidades de visualización de MetaTrader 5, especialmente para los analistas que buscan una comprensión más profunda de la evolución de los precios en contextos temporales más amplios.
Una de las principales ventajas de esta herramienta reside en su capacidad para visualizar el cuerpo de cada período. Al rellenar los cuerpos de las velas de marcos temporales superiores con colores distintos, los operadores pueden reconocer de inmediato si un período fue alcista, bajista o neutral, y luego examinar cómo se comportaron las velas de marcos temporales inferiores dentro de esas regiones. Esto también revela la historia detrás de las formaciones de mechas, ya que los usuarios pueden observar la volatilidad en marcos temporales más cortos, los movimientos de liquidez y las reacciones dentro de la barra que crearon esos máximos o mínimos prolongados. Estos conocimientos son invaluables al analizar reversiones, falsas señales o patrones de continuación que de otro modo quedarían ocultos dentro de cuerpos de velas japonesas más grandes.
Igualmente importante es el alto nivel de personalización y optimización integrado en la herramienta. Los usuarios pueden configurar qué periodos de tiempo mostrar, establecer estilos y colores de línea independientes para cada uno, definir la profundidad del historial y alternar la visibilidad de las series para mantener un diseño de gráfico limpio pero informativo. Estas características ajustables hacen que el indicador sea adaptable a diversos estilos de negociación, desde los scalpers intradía que estudian el comportamiento de M1/M5 hasta los analistas a largo plazo que alinean las estructuras D1 y W1. Al ofrecer flexibilidad, el Sincronizador de Períodos de Mercado permite a los usuarios analizar los mercados de una manera que se adapte a su enfoque de negociación y flujo de trabajo cognitivo únicos.
Para los futuros desarrolladores de MQL5, este proyecto demuestra cómo los conceptos abstractos de negociación pueden traducirse en herramientas visuales e interactivas mediante prácticas de codificación estructuradas. Destaca habilidades prácticas como el manejo de eventos, la gestión de objetos gráficos y la sincronización de datos en múltiples marcos temporales, todos ellos temas fundamentales para cualquiera que desee dominar el lenguaje MQL5. Para los operadores, el indicador fomenta el hábito de la observación estructurada, ayudándoles a comprender no solo lo que está haciendo el mercado, sino también cómo evoluciona el precio a lo largo del tiempo en diferentes marcos temporales. Esta comprensión interdisciplinaria entre la programación y el análisis de mercado fomenta tanto la competencia técnica como la profundidad analítica, sentando una base sólida para la innovación futura en el desarrollo de herramientas de negociación.
En esencia, el Sincronizador de Períodos de Mercado representa tanto un avance funcional para el análisis técnico como una plataforma de aprendizaje para aquellos que se inician en el desarrollo MQL5. Refleja cómo la resolución creativa de problemas, guiada por desafíos reales del trading, puede dar lugar a herramientas valiosas que mejoran la claridad, la precisión y el valor educativo del análisis de gráficos dentro del entorno de MetaTrader 5.
Consulte la tabla que aparece a continuación para conocer las principales lecciones aprendidas durante el proceso de desarrollo, junto con el archivo fuente adjunto que se proporciona al final de este artículo.
Lecciones clave
| Lección clave | Descripción |
|---|---|
| 1. Gestión de datos en múltiples periodos de tiempo: | Aprende a acceder, comparar y alinear datos de marcos temporales superiores mientras trabajas en un gráfico de marco temporal inferior. El proyecto demuestra el uso correcto de las funciones iTime(), iOpen() e iClose() para sincronizar datos de diferentes períodos. |
| 2. Creación de objetos y elaboración de gráficos: | Aprenda a crear y administrar objetos de gráficos, como líneas verticales, rectángulos y etiquetas, mediante programación utilizando ObjectCreate() y ObjectSetInteger(). Se hace hincapié en el uso de convenciones de nomenclatura adecuadas y en la limpieza de recursos para evitar el desorden y las fugas de memoria. |
| 3. Diseño de parámetros de entrada: | Adquiera experiencia definiendo parámetros de entrada flexibles que permitan a los usuarios personalizar la selección de intervalos de tiempo, los colores, el grosor de las líneas y la visibilidad de los marcadores. El indicador muestra el uso práctico de las variables de entrada para lograr la máxima configurabilidad. |
| 4. Optimización de algoritmos y gestión de la CPU: | Aprenda a optimizar el rendimiento de los indicadores limitando el dibujo de objetos al rango visible del gráfico. Esto pone de manifiesto la importancia de los bucles eficientes, las comprobaciones condicionales y el uso mínimo de recursos al trabajar con actualizaciones de alta frecuencia en gráficos M1 o M5. |
| 5. Conceptos de sincronización visual: | Comprender cómo los elementos visuales pueden comunicar relaciones estructurales entre diferentes periodos de tiempo. Al marcar los períodos principales e intermedios, la herramienta ayuda a los usuarios a visualizar de forma intuitiva la evolución de los precios y a observar cómo las velas de marcos temporales inferiores construyen formaciones de marcos temporales superiores. |
| 6. Depuración y pruebas prácticas: | Explora el proceso de compilación, incorporación y prueba de indicadores personalizados en MetaTrader 5. Los desarrolladores aprenden a interpretar los mensajes del compilador, a gestionar errores como "número de parámetros incorrecto" y a validar la lógica paso a paso durante la ejecución del gráfico en tiempo real. |
| 7. Estructuración modular del código: | Experimente cómo la separación de la lógica en segmentos de inicialización, cálculo y visualización da como resultado un código limpio y fácil de mantener. Esto concuerda con las mejores prácticas de MQL5 para el diseño de indicadores reutilizables y extensibles. |
| 8. Uniendo análisis y automatización: | Reconocer cómo conceptos analíticos como la alineación de marcos temporales y el mapeo de la acción del precio pueden transformarse en herramientas visuales automatizadas. Esta fusión de programación y lógica de negociación fortalece tanto las habilidades de programación como las de pensamiento analítico. |
| 9. Comprender la microestructura del mercado: | Mediante la sincronización visual, los operadores pueden examinar la formación de mechas, las transiciones de impulso y las reacciones dentro de la barra, lo que les ayuda a interpretar cómo los movimientos de microprecios componen los cuerpos y las mechas de las velas en marcos temporales superiores. |
| 10. Valor educativo para nuevos desarrolladores: | El proyecto demuestra un ciclo de desarrollo completo, desde la concepción de la idea y la definición del problema hasta la codificación, la depuración y la publicación. Sirve como plantilla de aprendizaje práctica para los futuros desarrolladores de MQL5 que aspiran a crear sus propios indicadores profesionales. |
Archivos adjuntos
| Nombre del archivo | Versión | Descripción |
|---|---|---|
| MarketPeriodsSynchronizer.mq5 | 1.01 | Este indicador proporciona una herramienta de sincronización visual para observar cómo los movimientos de precios en marcos temporales inferiores forman la estructura de los períodos temporales superiores. Dibuja marcadores verticales y etiquetas opcionales que corresponden a los marcos temporales superiores seleccionados, lo que permite a los operadores identificar el inicio y el final de períodos de mercado más amplios directamente en gráficos de marcos temporales más pequeños. La herramienta se actualiza automáticamente y admite colores, anchos y profundidad de retrospectiva de marcadores personalizables. Se desarrolló utilizando las funcionalidades básicas de MQL5, incluidas CopyTime(), ObjectCreate() y los eventos de temporizador, lo que lo convierte en un caso de estudio práctico para combinar la visualización de gráficos con el procesamiento de datos de múltiples marcos temporales. |
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/19841
Advertencia: todos los derechos de estos materiales pertenecen a MetaQuotes Ltd. Queda totalmente prohibido el copiado total o parcial.
Este artículo ha sido escrito por un usuario del sitio web y refleja su punto de vista personal. MetaQuotes Ltd. no se responsabiliza de la exactitud de la información ofrecida, ni de las posibles consecuencias del uso de las soluciones, estrategias o recomendaciones descritas.
Utilizando redes neuronales en MetaTrader
Desarrollo de asesores expertos autooptimizables en MQL5 (Parte 8): Análisis de múltiples estrategias
Particularidades del trabajo con números del tipo double en MQL4
Desarrollo de asesores expertos autooptimizables en MQL5 (Parte 7): Trading con múltiples períodos simultáneamente
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso