DRAW_CANDLES

El estilo DRAW_CANDLES dibuja las velas japonesas basándose en los valores de cuatro búfers indicadores que contienen los precios Open, High, Low y Close. Se utiliza para crear sus propios indicadores personalizados en forma de velas japonesas, también en otra subventana del gráfico y para otros instrumentos financieros.

El color de las velas se puede definir usando las directivas del compilador, o dinámicamente a través de la función PlotIndexSetInteger(). El cambio dinámico de las propiedades de la construcción gráfica permite "vivificar" los indicadores, para que cambien su apariencia en función de la situación actual.

El indicador se dibuja sólo para las barras que tienen establecidos los valores no vacíos de todos los cuatro búfers indicadores. Para indicar qué valor se debe considerar "vacío", establezca este valor en la propiedad PLOT_EMPTY_VALUE:

//--- el valor 0 (valor vacío) no va a participar en el proceso de trazado
   PlotIndexSetDouble(índice_ de_construcción_DRAW_CANDLES,PLOT_EMPTY_VALUE,0);

Rellene siempre los búfers indicadores con valores de forma explícita, para las barras que se ignoran indique en el búfer un valor vacío.

El número de búfers requeridos para construir DRAW_CANDLES – 4. Todos los búfers que se utilizan para la construcción deben ir en serie uno detrás del otro en orden establecido: Open, High, Low y Close. Ninguno de los búfers puede contener sólo los valores vacíos, porque si es así, no se dibuja nada.

Para el estilo DRAW_CANDLES es posible indicar de uno a tres colores, dependiendo de ello, cambiará el aspecto exterior de las velas. Si se indica solo un color, entonces todas las velas del gráfico se colorearán por entero de ese color.

//--- velas iguales, coloreadas en un solo color
#property indicator_label1  "One color candles"
#property indicator_type1   DRAW_CANDLES
//--- solo se ha indicado un color, por eso todas las velas serán de un solo color
#property indicator_color1  clrGreen  

Si indicamos dos colores a través de un guión, los contornos se dibujarán con el primer color, y el cuerpo con el segundo.

//--- el color de las velas se distingue del color de las sombras
#property indicator_label1  "Two color candles"
#property indicator_type1   DRAW_CANDLES
//--- las sombras y el contorno de las velas son de color verde, el cuerpo, de color blanco
#property indicator_color1  clrGreen,clrWhite 

Para que sea posible mostrar las velas crecientes y decrecientes de forma distinta, es necesario indicar los tres colores con ayuda de comas. En este caso, el contorno de la vela se dibujará con el primer color, y el color de la vela alcista y bajista se establecerá con el segundo y el tercer color.

//--- el color de las velas se distingue del color de las sombras
#property indicator_label1  "One color candles"
#property indicator_type1   DRAW_CANDLES
//--- las sombras y el contorno en color verde, el cuerpo de la vela alcista en color blanco, el cuerpo de la vela bajista en color rojo
#property indicator_color1  clrGreen,clrWhite,clrRed

De esta forma, con la ayuda del estilo DRAW_CANDLES se pueden crear variantes personalizadas propias del color de las velas. Asimismo, todos los colores pueden cambiarse de forma dinámica durante el proceso del trabajo con la ayuda de la función PlotIndexSetInteger(índice_de_la_construcción_DRAW_CANDLES, PLOT_LINE_COLOR, número_del_modificador, color) , donde el número_del_modificador puede tener los valores siguientes:

  • 0 — color del contorno y las sombras
  • 1— color del cuerpo de la vela alcista
  • 2 - color del cuerpo de vela bajista

//--- establecemos el color del contorno y de las sombras
PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,clrBlue);
//--- establecemos el color del cuerpo para la vela alcista
PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,clrGreen);
//--- establecemos el color del cuerpo para la vela bajista
PlotIndexSetInteger(0,PLOT_LINE_COLOR,2,clrRed);

Aquí tenemos un ejemplo del indicador que dibuja en una ventana separada las velas japonesas para el instrumento financiero especificado. El color de las velas se cambia aleatoriamente cada N tics. El parámetro N está sacado a los parámetros externos del indicador para que exista la posibilidad de establecerlo manualmente (pestaña "Parámetros" en la ventana de propiedades del indicador).

Ejemplo del estilo DRAW_CANDLES

Fíjense en que inicialmente para la construcción gráfica plot1 el color se establece mediante la directiva del compilador #property, y luego en la funciónOnCalculate() se elige aleatoriamente un nuevo color desde la lista previamente preparada.

//+------------------------------------------------------------------+
//|                                                 DRAW_CANDLES.mq5 |
//|                         Copyright 2000-2024, MetaQuotes Ltd. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
 
#property description "Indicador para demostrar DRAW_CANDLES."
#property description "Dibuja en la ventana separada las velas para el símbolo seleccionado al azar desde MarketWatch."
#property description " "
#property description "El color y el grosor de las velas, igual que el estilo, se cambian"
#property description "de forma aleatoria cada N tics."
 
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots   1
//--- plot Bars
#property indicator_label1  "DRAW_CANDLES1"
#property indicator_type1   DRAW_CANDLES
#property indicator_color1  clrGreen
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
 
//--- parámetros input
input int      N=5;              // número de tics para el cambio de apariencia
input int      bars=500;         // número de barras a mostrar
input bool     messages=false;   // mostrar mensajes en el log "Asesores Expertos"
//--- búfers indicadores
double         Candle1Buffer1[];
double         Candle1Buffer2[];
double         Candle1Buffer3[];
double         Candle1Buffer4[];
//--- nombre del símbolo
string symbol;
//--- array para almacenar colores
color colors[]={clrRed,clrBlue,clrGreen,clrPurple,clrBrown,clrIndianRed};
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- si bars es muy pequeño - finalizamos el trabajo antes de tiempo
   if(bars<50)
     {
      Comment("¡Por favor, indique el número más grande de barras! El trabajo del indicador ha sido finalizado");
      return(INIT_PARAMETERS_INCORRECT);
     }
//--- indicator buffers mapping
   SetIndexBuffer(0,Candle1Buffer1,INDICATOR_DATA);
   SetIndexBuffer(1,Candle1Buffer2,INDICATOR_DATA);
   SetIndexBuffer(2,Candle1Buffer3,INDICATOR_DATA);
   SetIndexBuffer(3,Candle1Buffer4,INDICATOR_DATA);
//--- valor vacío
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
//--- nombre del símbolo para el que se dibujan las barras
   symbol=_Symbol;
//--- estableceremos la visualización del símbolo
   PlotIndexSetString(0,PLOT_LABEL,symbol+" Open;"+symbol+" High;"+symbol+" Low;"+symbol+" Close");
   IndicatorSetString(INDICATOR_SHORTNAME,"DRAW_CANDLES("+symbol+")");
//---
   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[])
  {
   static int ticks=INT_MAX-100;
//--- contamos los tics para el cambio del estilo, color y grosor de la línea
   ticks++;
//--- si tenemos acumulado un número suficiente de tics
   if(ticks>=N)
     {
      //--- escogeremos nuevo símbolo en la ventana "Observación del mercado"
      symbol=GetRandomSymbolName();
      //--- cambiamos la apariencia
      ChangeLineAppearance();
      //--- escogeremos nuevo símbolo en la ventana "Observación del mercado"
      int tries=0;
      //--- haremos 5 intentos de llenar el búfer plot1 con los precios desde symbol
      while(!CopyFromSymbolToBuffers(symbol,rates_total,0,
            Candle1Buffer1,Candle1Buffer2,Candle1Buffer3,Candle1Buffer4)
            && tries<5)
        {
         //--- contador de llamadas a la función CopyFromSymbolToBuffers()
         tries++;
        }
      //--- actualizamos el contador de tics pasándolo a cero
      ticks=0;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|  Llena la vela indicada                                          |
//+------------------------------------------------------------------+
bool CopyFromSymbolToBuffers(string name,
                             int total,
                             int plot_index,
                             double &buff1[],
                             double &buff2[],
                             double &buff3[],
                             double &buff4[]
                             )
  {
//--- vamos a copiar los precios Open, High, Low y Close al array rates[]
   MqlRates rates[];
//--- contador de intentos
   int attempts=0;
//--- cantidad que se ha copiado ya
   int copied=0;
//--- hacemos 25 intentos de obtener la serie temporal para el símbolo necesario
   while(attempts<25 && (copied=CopyRates(name,_Period,0,bars,rates))<0)
     {
      Sleep(100);
      attempts++;
      if(messagesPrintFormat("%s CopyRates(%s) attempts=%d",__FUNCTION__,name,attempts);
     }
//--- si no se ha podido copiar la cantidad suficiente de barras
   if(copied!=bars)
     {
      //--- formaremos la cadena del mensaje
      string comm=StringFormat("Para el símbolo %s se ha logrado obtener sólo %d barras de %d solicitadas",
                               name,
                               copied,
                               bars
                               );
      //--- mostraremos el mensaje en un comentario en la ventana principal del gráfico
      Comment(comm);
      //--- mostramos el mensaje
      if(messagesPrint(comm);
      return(false);
     }
   else
     {
      //--- estableceremos la visualización del símbolo 
      PlotIndexSetString(plot_index,PLOT_LABEL,name+" Open;"+name+" High;"+name+" Low;"+name+" Close");
     }
//--- inicializaremos los búfers con valores vacíos
   ArrayInitialize(buff1,0.0);
   ArrayInitialize(buff2,0.0);
   ArrayInitialize(buff3,0.0);
   ArrayInitialize(buff4,0.0);
//--- en cada tic copiamos los precios a los búfers
   for(int i=0;i<copied;i++)
     {
      //--- calcularemos el índice correspondiente para los búfers
      int buffer_index=total-copied+i;
      //--- escribimos los precios en los búfers
      buff1[buffer_index]=rates[i].open;
      buff2[buffer_index]=rates[i].high;
      buff3[buffer_index]=rates[i].low;
      buff4[buffer_index]=rates[i].close;
     }
   return(true);
  }
//+------------------------------------------------------------------+
//| devuelve aleatoriamente el símbolo desde Market Watch            |
//+------------------------------------------------------------------+
string GetRandomSymbolName()
  {
//--- número de símbolos mostrados en la ventana "Observación del mercado"
   int symbols=SymbolsTotal(true);
//--- posición del símbolo en la lista - un número aleatorio de 0 a symbols
   int number=MathRand()%symbols;
//--- devolvemos el nombre del símbolo sobre la posición indicada
   return SymbolName(number,true);
  }
//+------------------------------------------------------------------+
//| cambia la apariencia de las barras                               |
//+------------------------------------------------------------------+
void ChangeLineAppearance()
  {
//--- cadena para formar la información sobre las propiedades de las barras
   string comm="";
//--- bloque del cambio del color de las barras
   int number=MathRand(); // obtenemos un número aleatorio
//--- el divisor del número es igual al tamaño del array colors[]
   int size=ArraySize(colors);
//--- obtenemos el índice para seleccionar nuevo color como el remanente de la división de números enteros
   int color_index=number%size;
//--- estableceremos el color como la propiedad PLOT_LINE_COLOR
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,colors[color_index]);
//--- apuntamos el color
   comm=comm+"\r\n"+(string)colors[color_index];
//--- apuntamos el nombre del símbolo
   comm="\r\n"+symbol+comm;
//--- mostraremos la información en el gráfico a través del comentario
   Comment(comm);
  }