Posicion del texto en ventana del gráfico

 
Acabo de crear un indicador que muestra una línea en los niveles comerciales High y Low del día anterior y en la apertura del día actual, intenté añadirle un texto que defina la línea pero por mas que lo intento no logro posicionar el texto en el lugar deseado (el borde derecho de la ventana) (ver imagen adjunta). El texto sí se dibuja pero se posiciona en el tiempo actual del eje X ¿Alguien tiene alguna idea de como mejorar esto?

// Añadir texto para el high del día anterior
      if (ObjectFind(0, highTextName) == -1)
      {
         if (!ObjectCreate(0, highTextName, OBJ_TEXT, 0, TimeCurrent(), previous_high))
         {
            Print("Error al crear el texto del máximo del día anterior");
         }
         else
         {
            ObjectSetString(0, highTextName, OBJPROP_TEXT, "HD");
            ObjectSetInteger(0, highTextName, OBJPROP_COLOR, clrTeal);
            ObjectSetInteger(0, highTextName, OBJPROP_FONTSIZE, 8);
         }

// Añadir texto para el low del día anterior
      if (ObjectFind(0, lowTextName) == -1)
      {
         if (!ObjectCreate(0, lowTextName, OBJ_TEXT, 0, TimeCurrent(), previous_low))
         {
            Print("Error al crear el texto del mínimo del día anterior");
         }
         else
         {
            ObjectSetString(0, lowTextName, OBJPROP_TEXT, "LD");
            ObjectSetInteger(0, lowTextName, OBJPROP_COLOR, clrTeal);
            ObjectSetInteger(0, lowTextName, OBJPROP_FONTSIZE, 8);
         }

// Añadir texto para la apertura del día actual
      if (ObjectFind(0, openTextName) == -1)
      {
         if (!ObjectCreate(0, openTextName, OBJ_TEXT, 0, TimeCurrent(), current_open))
         {
            Print("Error al crear el texto de la apertura del día actual");
         }
         else
         {
            ObjectSetString(0, openTextName, OBJPROP_TEXT, "OD");
            ObjectSetInteger(0, openTextName, OBJPROP_COLOR, clrYellow);
            ObjectSetInteger(0, openTextName, OBJPROP_FONTSIZE, 8);
         }

   // Obtener el ancho del gráfico en píxeles
   long chartWidth = ChartGetInteger(0, CHART_WIDTH_IN_PIXELS);

   // Coordenadas de la línea del High
   int high_x = 0, high_y = 0;
   if (ChartTimePriceToXY(0, 0, TimeCurrent(), HighLineBuffer[0], high_x, high_y))
   {
      high_x = MathMin((int)chartWidth - 10, high_x); // Ajustar posición X
      ObjectSetInteger(0, highTextName, OBJPROP_XDISTANCE, (int)chartWidth - high_x - 10); // Ajustar posición X
      ObjectSetInteger(0, highTextName, OBJPROP_YDISTANCE, high_y);
   }

   // Coordenadas de la línea del Low
   int low_x = 0, low_y = 0;
   if (ChartTimePriceToXY(0, 0, TimeCurrent(), LowLineBuffer[0], low_x, low_y))
   {
      low_x = MathMin((int)chartWidth - 10, low_x); // Ajustar posición X
      ObjectSetInteger(0, lowTextName, OBJPROP_XDISTANCE, (int)chartWidth - low_x - 10); // Ajustar posición X
      ObjectSetInteger(0, lowTextName, OBJPROP_YDISTANCE, low_y);
   }

   // Coordenadas de la línea de Apertura
   int open_x = 0, open_y = 0;
   if (ChartTimePriceToXY(0, 0, TimeCurrent(), OpenLineBuffer[0], open_x, open_y))
   {
      open_x = MathMin((int)chartWidth - 10, open_x); // Ajustar posición X
      ObjectSetInteger(0, openTextName, OBJPROP_XDISTANCE, (int)chartWidth - open_x - 10); // Ajustar posición X
      ObjectSetInteger(0, openTextName, OBJPROP_YDISTANCE, open_y);
   }

   return rates_total;
}

Archivos adjuntos:
 
Saúl de:

Hola Sául, como no has puesto todo el código, no lo puedo compilar.

Aquí te dejo una muestra que se adapta mejor a lo que requieres, lo he escrito en forma de script:

//--- Definición de variables necesarias
double previous_high;     // Máximo del día anterior
double previous_low;      // Mínimo del día anterior
double current_open;      // Apertura del día actual

string highTextName = "HighText"; // Nombre del objeto de texto para el High
string lowTextName = "LowText";   // Nombre del objeto de texto para el Low
string openTextName = "OpenText"; // Nombre del objeto de texto para la Apertura

//--- Función OnStart
void OnStart()
{
    // Obtener el máximo y mínimo del día anterior y la apertura del día actual
    previous_high = iHigh(NULL, PERIOD_D1, 1); // Máximo del día anterior
    previous_low = iLow(NULL, PERIOD_D1, 1);   // Mínimo del día anterior
    current_open = iOpen(NULL, PERIOD_D1, 0);  // Apertura del día actual

    // Obtener el ancho y alto del gráfico en píxeles
    long chartWidth = ChartGetInteger(0, CHART_WIDTH_IN_PIXELS);
    int rightMargin = 10;  // Margen desde el borde derecho
    
    // --- Añadir texto para el High del día anterior
    if (ObjectFind(0, highTextName) == -1)
    {
        if (!ObjectCreate(0, highTextName, OBJ_TEXT, 0, TimeCurrent(), previous_high))
        {
            Print("Error al crear el texto del máximo del día anterior");
        }
        else
        {
            ObjectSetString(0, highTextName, OBJPROP_TEXT, "HD");
            ObjectSetInteger(0, highTextName, OBJPROP_COLOR, clrTeal);
            ObjectSetInteger(0, highTextName, OBJPROP_FONTSIZE, 8);

            // Coordenadas del High en píxeles
            int high_x = 0, high_y = 0;
            if (ChartTimePriceToXY(0, 0, TimeCurrent(), previous_high, high_x, high_y))
            {
                int rightEdge = (int)chartWidth - rightMargin; // Posición hacia el borde derecho
                ObjectSetInteger(0, highTextName, OBJPROP_XDISTANCE, rightEdge);
                ObjectSetInteger(0, highTextName, OBJPROP_YDISTANCE, high_y);
            }
        }
    }

    // --- Añadir texto para el Low del día anterior
    if (ObjectFind(0, lowTextName) == -1)
    {
        if (!ObjectCreate(0, lowTextName, OBJ_TEXT, 0, TimeCurrent(), previous_low))
        {
            Print("Error al crear el texto del mínimo del día anterior");
        }
        else
        {
            ObjectSetString(0, lowTextName, OBJPROP_TEXT, "LD");
            ObjectSetInteger(0, lowTextName, OBJPROP_COLOR, clrTeal);
            ObjectSetInteger(0, lowTextName, OBJPROP_FONTSIZE, 8);

            // Coordenadas del Low en píxeles
            int low_x = 0, low_y = 0;
            if (ChartTimePriceToXY(0, 0, TimeCurrent(), previous_low, low_x, low_y))
            {
                int rightEdge = (int)chartWidth - rightMargin; // Posición hacia el borde derecho
                ObjectSetInteger(0, lowTextName, OBJPROP_XDISTANCE, rightEdge);
                ObjectSetInteger(0, lowTextName, OBJPROP_YDISTANCE, low_y);
            }
        }
    }

    // --- Añadir texto para la apertura del día actual
    if (ObjectFind(0, openTextName) == -1)
    {
        if (!ObjectCreate(0, openTextName, OBJ_TEXT, 0, TimeCurrent(), current_open))
        {
            Print("Error al crear el texto de la apertura del día actual");
        }
        else
        {
            ObjectSetString(0, openTextName, OBJPROP_TEXT, "OD");
            ObjectSetInteger(0, openTextName, OBJPROP_COLOR, clrYellow);
            ObjectSetInteger(0, openTextName, OBJPROP_FONTSIZE, 8);

            // Coordenadas de la Apertura en píxeles
            int open_x = 0, open_y = 0;
            if (ChartTimePriceToXY(0, 0, TimeCurrent(), current_open, open_x, open_y))
            {
                int rightEdge = (int)chartWidth - rightMargin; // Posición hacia el borde derecho
                ObjectSetInteger(0, openTextName, OBJPROP_XDISTANCE, rightEdge);
                ObjectSetInteger(0, openTextName, OBJPROP_YDISTANCE, open_y);
            }
        }
    }
}

Ajusta los colores o lo que necesites, solo es un modelo de ejemplo



 
Enrique Enguix #:

Hola Sául, como no has puesto todo el código, no lo puedo compilar.

Aquí te dejo una muestra que se adapta mejor a lo que requieres, lo he escrito en forma de script:

Ajusta los colores o lo que necesites, solo es un modelo de ejemplo



Saludos Enrique, espero que estés bien.

Intenté utilizar esto que muestras pero el texto se posición en la vela mas reciente, quisiera poder colocarlo donde solo hay datos de tiempo y que el texto se mantenga ahí aunque cambie de temporalidad o de zoom. 

Se te ocurre algo?

Hasta ahora esto es lo que tengo pero no me funciona como espero.

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 Teal
#property indicator_color2 Teal
#property indicator_color3 Yellow  // Color para la línea de apertura

// Buffers para almacenar los valores de las líneas de tendencia
double HighLineBuffer[];
double LowLineBuffer[];
double OpenLineBuffer[];  // Buffer para la apertura del día actual

// Variable global para almacenar la fecha del último cálculo
datetime lastCalculationDay = 0;

// Variables para los objetos gráficos
string highLineName = "PreviousDayHighLine";
string lowLineName = "PreviousDayLowLine";
string openLineName = "CurrentDayOpenLine";

// Variables para las etiquetas de texto
string highLabelName = "PreviousDayHighLabel";
string lowLabelName = "PreviousDayLowLabel";
string openLabelName = "CurrentDayOpenLabel";

// Parámetros para ajustar la posición de las etiquetas
double xOffset = 10;  // Desplazamiento en X para las etiquetas
double yOffset = 5;   // Desplazamiento en Y para las etiquetas

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   SetIndexBuffer(0, HighLineBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, LowLineBuffer, INDICATOR_DATA);
   SetIndexBuffer(2, OpenLineBuffer, INDICATOR_DATA);  // Inicialización del buffer de apertura

   IndicatorSetString(INDICATOR_SHORTNAME, "Previous Day High/Low and Opening Lines");

   PlotIndexSetString(0, PLOT_LABEL, "High Line");
   PlotIndexSetString(1, PLOT_LABEL, "Low Line");
   PlotIndexSetString(2, PLOT_LABEL, "Open Line");  // Etiqueta para la línea de apertura

   return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| 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[])
{
   // Solo calcular si hay suficientes barras
   if (rates_total < 2)
      return 0;

   // Estructura de tiempo para comparar fechas
   MqlDateTime currentTime, lastCalcTime;
   TimeToStruct(time[0], currentTime);
   TimeToStruct(lastCalculationDay, lastCalcTime);

   // Comprobar si el día ha cambiado
   if (currentTime.day != lastCalcTime.day)
   {
      // Asegurarse de que los datos históricos estén disponibles
      if (SeriesInfoInteger(Symbol(), PERIOD_D1, SERIES_BARS_COUNT) < 2)
      {
         Print("Error: No hay suficientes datos históricos para el día anterior.");
         return 0;
      }

      // Obtener el high y low del día anterior solo una vez al día
      datetime previous_day = iTime(NULL, PERIOD_D1, 1);
      double previous_high = iHigh(NULL, PERIOD_D1, 1);
      double previous_low = iLow(NULL, PERIOD_D1, 1);

      // Almacenar los valores en los buffers
      HighLineBuffer[0] = previous_high;
      LowLineBuffer[0] = previous_low;

      // Dibujar la línea de tendencia en el high del día anterior
      if (ObjectFind(0, highLineName) == -1)
      {
         ObjectCreate(0, highLineName, OBJ_TREND, 0, previous_day, previous_high, TimeCurrent(), previous_high);
         ObjectSetInteger(0, highLineName, OBJPROP_COLOR, clrTeal);
         ObjectSetInteger(0, highLineName, OBJPROP_RAY_RIGHT, true);
         ObjectSetInteger(0, highLineName, OBJPROP_WIDTH, 2);  // Grosor de la línea
      }

      // Dibujar la línea de tendencia en el low del día anterior
      if (ObjectFind(0, lowLineName) == -1)
      {
         ObjectCreate(0, lowLineName, OBJ_TREND, 0, previous_day, previous_low, TimeCurrent(), previous_low);
         ObjectSetInteger(0, lowLineName, OBJPROP_COLOR, clrTeal);
         ObjectSetInteger(0, lowLineName, OBJPROP_RAY_RIGHT, true);
         ObjectSetInteger(0, lowLineName, OBJPROP_WIDTH, 2);  // Grosor de la línea
      }

      // Obtener el precio de apertura del día actual
      datetime current_day = iTime(NULL, PERIOD_D1, 0);
      double current_open = iOpen(NULL, PERIOD_D1, 0);

      // Almacenar el valor en el buffer de apertura
      OpenLineBuffer[0] = current_open;

      // Dibujar la línea de tendencia en la apertura del día actual
      if (ObjectFind(0, openLineName) == -1)
      {
         ObjectCreate(0, openLineName, OBJ_TREND, 0, current_day, current_open, TimeCurrent(), current_open);
         ObjectSetInteger(0, openLineName, OBJPROP_COLOR, clrYellow);
         ObjectSetInteger(0, openLineName, OBJPROP_RAY_RIGHT, true);
         ObjectSetInteger(0, openLineName, OBJPROP_WIDTH, 2);  // Grosor de la línea
      }

      // Actualizar la fecha de cálculo
      lastCalculationDay = time[0];
   }

   // Actualizar etiquetas en cada tick
   UpdateLabels();

   return rates_total;
}

//+------------------------------------------------------------------+
//| Función para actualizar las etiquetas de texto                   |
//+------------------------------------------------------------------+
void UpdateLabels()
{
   // Tiempo y precio de referencia para las etiquetas
   datetime future_time = TimeCurrent() + 8 * 3600;  // 8 horas en el futuro

   // Etiqueta del High
   double high_price = HighLineBuffer[0];
   if (ObjectFind(0, highLabelName) != -1)
   {
      ObjectMove(0, highLabelName, 0, future_time, high_price);
   }
   else
   {
      ObjectCreate(0, highLabelName, OBJ_TEXT, 0, future_time, high_price);
      ObjectSetString(0, highLabelName, OBJPROP_TEXT, "High Day");
      ObjectSetInteger(0, highLabelName, OBJPROP_COLOR, clrTeal);
      ObjectSetInteger(0, highLabelName, OBJPROP_FONTSIZE, 8);
      ObjectSetInteger(0, highLabelName, OBJPROP_CORNER, 0);  // Colocar en coordenadas de tiempo/precio
   }

   // Etiqueta del Low
   double low_price = LowLineBuffer[0];
   if (ObjectFind(0, lowLabelName) != -1)
   {
      ObjectMove(0, lowLabelName, 0, future_time, low_price);
   }
   else
   {
      ObjectCreate(0, lowLabelName, OBJ_TEXT, 0, future_time, low_price);
      ObjectSetString(0, lowLabelName, OBJPROP_TEXT, "Low Day");
      ObjectSetInteger(0, lowLabelName, OBJPROP_COLOR, clrTeal);
      ObjectSetInteger(0, lowLabelName, OBJPROP_FONTSIZE, 8);
      ObjectSetInteger(0, lowLabelName, OBJPROP_CORNER, 0);  // Colocar en coordenadas de tiempo/precio
   }

   // Etiqueta de la apertura
   double open_price = OpenLineBuffer[0];
   if (ObjectFind(0, openLabelName) != -1)
   {
      ObjectMove(0, openLabelName, 0, future_time, open_price);
   }
   else
   {
      ObjectCreate(0, openLabelName, OBJ_TEXT, 0, future_time, open_price);
      ObjectSetString(0, openLabelName, OBJPROP_TEXT, "Open");
      ObjectSetInteger(0, openLabelName, OBJPROP_COLOR, clrYellow);
      ObjectSetInteger(0, openLabelName, OBJPROP_FONTSIZE, 8);
      ObjectSetInteger(0, openLabelName, OBJPROP_CORNER, 0);  // Colocar en coordenadas de tiempo/precio
   }
}