Actualización o reinicio de un indicador

 
Saludos colegas, espero que se encuentren bien.

Acabo de crear un indicador que muestras líneas en los niveles comerciales de la última hora en cualquier activo financiero, pero tengo un problema a medida que pasan las horas y es que cuando inicia la siguiente hora el indicador no actualiza las líneas que se deben marcar en los nuevos precios obtenidos a menos que cambie de temporalidad. ¿Alguien tiene alguna idea de que podría hacer para que las líneas en los precios obtenidos cada hora se actualicen automáticamente sin necesidad de cambiar de temporalidad o cargarlo de nuevo?

Acá les dejo el código en caso de que necesiten echarle un vistazo:

//+------------------------------------------------------------------+
//|                                                      OHLC_H1.mq5 |
//|                                      Copyright 2024, Saul Lopez. |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Saul Lopez."
#property link      ""
#property version   "1.02"
#property indicator_chart_window
#property indicator_plots 0 // Evita la advertencia de "no indicator plot defined"

// Parámetros para mostrar/ocultar líneas
sinput group                                  "*** Niveles comerciales - 0 para oculatar ***"
input int showOpenLine = 1;                   // Open
input int showHighLine = 1;                   // High
input int showLowLine = 1;                    // Low
input int showCloseLine = 1;                  // Close
input int showVerticalLine = 0;               // Separador de intervalos

// Parámetros de entrada
sinput group                                  "*** Personalización NC ***"
input int widthLines = 1;                    // Grosor de las líneas
input ENUM_LINE_STYLE lineStyle = STYLE_DOT;  // Estilo de las líneas
sinput group                                  "*** Colores ***"
input color colorOpenLine = clrYellow;        // Color de la línea de Open
input color colorHighLine = clrTeal;          // Color de la línea de High
input color colorLowLine = clrSteelBlue;      // Color de la línea de Low
input color colorCloseLine = clrDarkBlue;     // Color de la línea de Close
input color colorVerticalLine = clrGray;      // Color separador de intervalos
sinput group                                  "*** Intervalos de actualización ***"
input int updateInterval = 3600;              // Intervalo de actualización en segundos (3600s = 1 hora)

datetime lastUpdate = 0; // Tiempo de la última actualización

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   // Configurar temporizador para actualizar cada hora
   EventSetTimer(updateInterval);
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // Eliminar temporizador
   EventKillTimer();

   // Eliminar las líneas del gráfico
   ObjectDelete(0, "OpenLine");
   ObjectDelete(0, "HighLine");
   ObjectDelete(0, "LowLine");
   ObjectDelete(0, "CloseLine");
   ObjectDelete(0, "VerticalLine");
   ObjectDelete(0, "TradeRecommendation"); // Eliminar el label de recomendación
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
{
   datetime currentTime = TimeCurrent();

   // Verificar si ya se actualizó en la última hora
   if (currentTime - lastUpdate < updateInterval)
      return prev_calculated;

   // Reiniciar el indicador eliminando las líneas antes de la nueva actualización
   OnDeinit(0);

   // Obtener el inicio y fin de la hora anterior
   datetime startTime = iTime(NULL, PERIOD_H1, 1);
   datetime endTime = startTime + 3600; // Fin de la hora anterior

   // Escanear velas M1 para la hora anterior
   datetime firstM1Time = 0, lastM1Time = 0;
   double highestPrice = -DBL_MAX, lowestPrice = DBL_MAX;
   datetime highestTime = 0, lowestTime = 0;

   // Iterar sobre las velas M1 de la hora anterior
   for (int i = 0; i < iBars(NULL, PERIOD_M1); i++)
   {
      datetime m1Time = iTime(NULL, PERIOD_M1, i);

      if (m1Time >= startTime && m1Time < endTime)
      {
         // Encontrar la primera vela M1
         if (firstM1Time == 0)
            firstM1Time = m1Time;

         // Encontrar la última vela M1
         lastM1Time = m1Time;

         // Encontrar el high más alto
         double m1High = iHigh(NULL, PERIOD_M1, i);
         if (m1High > highestPrice)
         {
            highestPrice = m1High;
            highestTime = m1Time;
         }

         // Encontrar el low más bajo
         double m1Low = iLow(NULL, PERIOD_M1, i);
         if (m1Low < lowestPrice)
         {
            lowestPrice = m1Low;
            lowestTime = m1Time;
         }
      }
   }

   // Obtener el precio de apertura de la primera vela de M1 y el precio de cierre de la última
   double openPrice = iOpen(NULL, PERIOD_M1, iBarShift(NULL, PERIOD_M1, firstM1Time));
   double closePrice = iClose(NULL, PERIOD_M1, iBarShift(NULL, PERIOD_M1, lastM1Time));

   // Crear líneas para los niveles comerciales con los respectivos anclajes
   if (showOpenLine == 1)
      DrawLine("OpenLine", firstM1Time, openPrice, endTime, openPrice, colorOpenLine, widthLines, lineStyle); // Apertura
   if (showHighLine == 1)
      DrawLine("HighLine", highestTime, highestPrice, endTime, highestPrice, colorHighLine, widthLines, lineStyle); // High
   if (showLowLine == 1)
      DrawLine("LowLine", lowestTime, lowestPrice, endTime, lowestPrice, colorLowLine, widthLines, lineStyle); // Low
   if (showCloseLine == 1)
      DrawLine("CloseLine", lastM1Time, closePrice, endTime, closePrice, colorCloseLine, widthLines, lineStyle); // Cierre

   // Dibujar línea vertical en la primera vela de M1 (apertura) si está en las temporalidades de 1M o 5M
   if (showVerticalLine == 1 && (Period() == PERIOD_M1 || Period() == PERIOD_M5))
      DrawVerticalLine("VerticalLine", firstM1Time, colorVerticalLine, widthLines, lineStyle);

   // Evaluar precios y mostrar recomendación
   string recommendation = "";
   color commentColor = clrWhite; // Inicializar el color del comentario

   if (openPrice > closePrice)
   {
      recommendation = "Compras";
      commentColor = clrForestGreen; // Color si Open es mayor que Close
   }
   else if (openPrice < closePrice)
   {
      recommendation = "Ventas";
      commentColor = clrRed; // Color si Open es menor que Close
   }

   // Dibujar el label de recomendación
   if (recommendation != "")
      DrawLabel("TradeRecommendation", recommendation, firstM1Time, high[0] + 10 * _Point, commentColor, 10); // Ajusta la posición según sea necesario

   // Actualizar el tiempo de la última actualización
   lastUpdate = currentTime;

   return rates_total; // Retornar el total de tasas para la siguiente llamada
}

//+------------------------------------------------------------------+
//| Function to draw a line at a given time and price               |
//+------------------------------------------------------------------+
void DrawLine(string name, datetime time1, double price1, datetime time2, double price2, color lineColor, int lineWidth, ENUM_LINE_STYLE style)
{
   // Si la línea ya existe, la eliminamos antes de crearla de nuevo
   if (ObjectFind(0, name) != -1)
      ObjectDelete(0, name);

   // Crear la línea
   if (!ObjectCreate(0, name, OBJ_TREND, 0, time1, price1, time2, price2))
   {
      Print("Error al crear la línea: ", name);
      return;
   }

   // Configurar las propiedades de la línea
   ObjectSetInteger(0, name, OBJPROP_COLOR, lineColor);
   ObjectSetInteger(0, name, OBJPROP_WIDTH, lineWidth);
   ObjectSetInteger(0, name, OBJPROP_STYLE, style);
   ObjectSetInteger(0, name, OBJPROP_RAY_RIGHT, true);  // Extender la línea a la derecha
   ObjectSetInteger(0, name, OBJPROP_RAY_LEFT, false);  // No extender la línea a la izquierda
}

//+------------------------------------------------------------------+
//| Function to draw a vertical line                                 |
//+------------------------------------------------------------------+
void DrawVerticalLine(string name, datetime time, color lineColor, int lineWidth, ENUM_LINE_STYLE style)
{
   // Si la línea ya existe, la eliminamos antes de crearla de nuevo
   if (ObjectFind(0, name) != -1)
      ObjectDelete(0, name);

   // Crear la línea vertical
   if (!ObjectCreate(0, name, OBJ_VLINE, 0, time, 0))
   {
      Print("Error al crear la línea vertical: ", name);
      return;
   }

   // Configurar las propiedades de la línea
   ObjectSetInteger(0, name, OBJPROP_COLOR, lineColor);
   ObjectSetInteger(0, name, OBJPROP_WIDTH, lineWidth);
   ObjectSetInteger(0, name, OBJPROP_STYLE, style);
}

//+------------------------------------------------------------------+
//| Function to draw a label at a given time and price               |
//+------------------------------------------------------------------+
void DrawLabel(string name, string text, datetime time, double price, color textColor, int fontSize)
{
   // Si el label ya existe, lo eliminamos antes de crearlo de nuevo
   if (ObjectFind(0, name) != -1)
      ObjectDelete(0, name);

   // Crear el label
   if (!ObjectCreate(0, name, OBJ_LABEL, 0, time, price))
   {
      Print("Error al crear el label: ", name);
      return;
   }

   // Configurar las propiedades del label
   ObjectSetInteger(0, name, OBJPROP_COLOR, textColor);
   ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, 7);   // Distancia desde el borde derecho en píxeles
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, 25);  // Distancia desde el borde superior en píxeles
   ObjectSetString(0, name, OBJPROP_TEXT, text);
   ObjectSetInteger(0, name, OBJPROP_XSIZE, 100); // Ajustar el tamaño de la etiqueta
   ObjectSetInteger(0, name, OBJPROP_YSIZE, 20); // Ajustar el tamaño de la etiqueta
}
 
Elimina líneas al marcar para que se actualicen y estés feliz :)))
 

Veo que solo quieres actualizar el gráfico cuando ya ha pasado una hora completa:

   datetime currentTime = TimeCurrent();

   if (currentTime - lastUpdate < updateInterval)return prev_calculated;   // Verificar si ya se actualizó en la última hora

//Dado que mantienes los nombres, el borrado no sería necesario: Volviendo a crearlo se borran las anteriores
//   OnDeinit(0);   // Reiniciar el indicador eliminando las líneas antes de la nueva actualización

Es normal que así ocurra, y así lo veo:


Mañana, con el mercado abierto, probaré lo que comentas en vivo.
 
Juan Luis De Frutos Blanco #:

Veo que solo quieres actualizar el gráfico cuando ya ha pasado una hora completa:

Es normal que así ocurra, y así lo veo:


Mañana, con el mercado abierto, probaré lo que comentas en vivo.

Sí, quiero actualizar el gráfico cuando la hora del terminar cambie, como está actualmente solo logré que se actualice cuando transcurra una hora de haber inicializado el indicador, es decir que si son las 08:53 el indicador se actualizará a las 09:53 cuando en realidad debería actualizar todo a las 09:00.   

Como las líneas se actualizan al cambiar de temporalidad significa que los precios obtenidos si se actualizan al cambiar de hora en el terminal pero las líneas se quedan en los mismo precios a menos que cambie de temporalidad.

A lo que me refiero es que cuando la hora cambia no se actualizan las líneas automáticamente a menos que cambie de temporalidad, si te fijas en la imagen que enviaste cuando vuelvas abrir el gráfico las líneas seguirán en el mismo lugar (precios) y si cambias de temporalidad entonces las líneas se actualizaran en los nuevos precios obtenidos.

 

Si lo he entendido bien, lo tuyo se arreglaría manteniendo siempre la hora de actualización al final de la hora:

   // Actualizar el tiempo de la última actualización
   lastUpdate = iTime(NULL, PERIOD_H1, 0)+updateInterval;

y cambiando:

if (currentTime < lastUpdate)return prev_calculated;   // Verificar si ya se actualizó en la última hora

//Dado que mantienes los nombres, el borrado no sería necesario
//   OnDeinit(0);   // Reiniciar el indicador eliminando las líneas antes de la nueva actualización


Aunque ahora el dilema estaría en ver si hay intención de que updateInterval sea distinto de 1 hora.

 
Juan Luis De Frutos Blanco #:

Si lo he entendido bien, lo tuyo se arreglaría manteniendo siempre la hora de actualización al final de la hora:

y cambiando:


Aunque ahora el dilema estaría en ver si hay intención de que updateInterval sea distinto de 1 hora.

Lo integré al código y ni siquiera mostró las líneas, al parecer estos es un poco mas complejo de lo que parece, intenté obtener la hora del terminal para reiniciar el indicador utilizando "if" "else" pero no pude dar con la solución.