DRAW_COLOR_CANDLES

Стиль DRAW_COLOR_CANDLES как и DRAW_CANDLES рисует японские свечи по значениям четырех индикаторных буферов, в которых содержатся цены Open, High, Low и Close. Но кроме этого он позволяет задавать цвет для каждой свечи из заданного набора. Для этого в стиль добавлен специальный цветовой буфер, который хранит индексы цветов для каждого бара. Предназначен для создания собственных индикаторов в виде свечей, в том числе в отдельном подокне графика и по другим финансовым инструментам.

Количество цветов для раскраски свечей можно задавать директивами компилятора или динамически с помощью функции PlotIndexSetInteger(). Динамическое изменение свойств графического построения позволяет "оживить" индикаторы, чтобы они меняли свой вид в зависимости от  текущей ситуации.

Индикатор рисуется только для тех баров, для которых заданы непустые значения четырех индикаторных буферов для хранения цен. Чтобы указать, какое значение следует считать "пустым", установите это значение в свойстве PLOT_EMPTY_VALUE:

//--- значение 0 (пустое значение) не будет участвовать в отрисовке
   PlotIndexSetDouble(индекс_построения_DRAW_COLOR_CANDLES,PLOT_EMPTY_VALUE,0);

Всегда явно заполняйте значениями индикаторные буферы, на пропускаемых барах указывайте в буфере пустое значение.

Количество требуемых буферов для построения DRAW_COLOR_CANDLES — 5:

  • четыре буфера для хранения значений Open, High, Low и Close;
  • один буфер для хранения индекса цвета, которым рисуется свеча (имеет смысл задавать только отрисовываемых свечей).

Все буферы для построения должны идти последовательно один за другим в заданном порядке: Open, High, Low, Close и буфер цвета. Ни один из ценовых буферов не может содержать только пустые значения, так как в этом случае отрисовка не происходит.

Пример индикатора, рисующего в отдельном окне японские свечи по указанному финансовому инструменту. Цвет свечей меняется случайным образом каждые N тиков. Параметр N вынесен во внешние параметры индикатора для возможности ручной установки (закладка "Параметры" в окне свойств индикатора).

Пример стиля DRAW_COLOR_CANDLES

Обратите внимание, первоначально для графического построения plot1 цвет задается с помощью директивы компилятора #property, а затем в функции OnCalculate() выбирается новый цвет случайным образом из заранее подготовленного списка.

//+------------------------------------------------------------------+
//|                                           DRAW_COLOR_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 "Индикатор для демонстрации DRAW_COLOR_CANDLES."
#property description "Рисует в отдельном окне разным цветом свечи по случайно выбранному из MarketWatch символу."
#property description " "
#property description "Цвет и толщина свечей, а также символ, меняются"
#property description "случайным образом через каждые N тиков."
 
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots   1
//--- plot ColorCandles
#property indicator_label1  "ColorCandles"
#property indicator_type1   DRAW_COLOR_CANDLES
//--- зададим 8 цветов для раскраски свечей (они хранятся в специальном массиве)
#property indicator_color1  clrRed,clrBlue,clrGreen,clrYellow,clrMagenta,clrCyan,clrLime,clrOrange
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
 
//--- input параметры
input int      N=5;              // количество тиков для смены вида
input int      bars=500;         // сколько свечей показывать
input bool     messages=false;   // вывод сообщений в лог "Эксперты"
//--- индикаторные буферы
double         ColorCandlesBuffer1[];
double         ColorCandlesBuffer2[];
double         ColorCandlesBuffer3[];
double         ColorCandlesBuffer4[];
double         ColorCandlesColors[];
int            candles_colors;
//--- имя символа
string symbol;
//--- массив для хранения цветов содержит 14 элементов
color colors[]=
  {
   clrRed,clrBlue,clrGreen,clrChocolate,clrMagenta,clrDodgerBlue,clrGoldenrod,
   clrIndigo,clrLightBlue,clrAliceBlue,clrMoccasin,clrMagenta,clrCyan,clrMediumPurple
  };
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- если bars слишком мало - досрочно завершаем работу
   if(bars<50)
     {
      Comment("Укажите большее количество баров! Работа индикатора прекращена");
      return(INIT_PARAMETERS_INCORRECT);
     }
//--- indicator buffers mapping
   SetIndexBuffer(0,ColorCandlesBuffer1,INDICATOR_DATA);
   SetIndexBuffer(1,ColorCandlesBuffer2,INDICATOR_DATA);
   SetIndexBuffer(2,ColorCandlesBuffer3,INDICATOR_DATA);
   SetIndexBuffer(3,ColorCandlesBuffer4,INDICATOR_DATA);
   SetIndexBuffer(4,ColorCandlesColors,INDICATOR_COLOR_INDEX);
//--- пустое значение
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
//--- имя символа, по которому рисуются бары
   symbol=_Symbol;
//--- установим отображение символа 
   PlotIndexSetString(0,PLOT_LABEL,symbol+" Open;"+symbol+" High;"+symbol+" Low;"+symbol+" Close");
   IndicatorSetString(INDICATOR_SHORTNAME,"DRAW_COLOR_CANDLES("+symbol+")");
//---- количество цветов для раскраски свечей
   candles_colors=8;     //  см. комментарий к свойству #property indicator_color1
//--- 
   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;
//--- считаем тики для изменения стиля и цвета
   ticks++;
//--- если накопилось достаточное число тиков
   if(ticks>=N)
     {
      //--- выберем новый символ из окна "Обзор рынка"
      symbol=GetRandomSymbolName();
      //--- сменим вид
      ChangeLineAppearance();
      //--- меняем цвета, которыми рисуются бары
      ChangeColors(colors,candles_colors);
 
      int tries=0;
      //--- сделаем 5 попыток заполнить буферы plot1 ценами из symbol
      while(!CopyFromSymbolToBuffers(symbol,rates_total,0,
            ColorCandlesBuffer1,ColorCandlesBuffer2,ColorCandlesBuffer3,
            ColorCandlesBuffer4,ColorCandlesColors,candles_colors)
            && tries<5)
        {
         //--- счетчик вызовов функции CopyFromSymbolToBuffers()
         tries++;
        }
      //--- сбрасываем счетчик тиков в ноль
      ticks=0;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Заполняет указанную свечу                                        |
//+------------------------------------------------------------------+
bool CopyFromSymbolToBuffers(string name,
                             int total,
                             int plot_index,
                             double &buff1[],
                             double &buff2[],
                             double &buff3[],
                             double &buff4[],
                             double &col_buffer[],
                             int    cndl_colors
                             )
  {
//--- в массив rates[] будем копировать цены Open, High, Low и Close
   MqlRates rates[];
//--- счетчик попыток
   int attempts=0;
//--- сколько скопировано
   int copied=0;
//--- делаем 25 попыток получить таймсерию по нужному символу
   while(attempts<25 && (copied=CopyRates(name,_Period,0,bars,rates))<0)
     {
      Sleep(100);
      attempts++;
      if(messagesPrintFormat("%s CopyRates(%s) attempts=%d",__FUNCTION__,name,attempts);
     }
//--- если не удалось скопировать достаточное количество баров
   if(copied!=bars)
     {
      //--- сформируем строку сообщения
      string comm=StringFormat("Для символа %s удалось получить только %d баров из %d затребованных",
                               name,
                               copied,
                               bars
                               );
      //--- выведем сообщение в комментарий на главное окно графика
      Comment(comm);
      //--- выводим сообщения
      if(messages) Print(comm);
      return(false);
     }
   else
     {
      //--- установим отображение символа 
      PlotIndexSetString(plot_index,PLOT_LABEL,name+" Open;"+name+" High;"+name+" Low;"+name+" Close");
      IndicatorSetString(INDICATOR_SHORTNAME,"DRAW_COLOR_CANDLES("+symbol+")");
     }
//--- инициализируем буферы пустыми значениями
   ArrayInitialize(buff1,0.0);
   ArrayInitialize(buff2,0.0);
   ArrayInitialize(buff3,0.0);
   ArrayInitialize(buff4,0.0);
//--- на каждом тике копируем цены в буферы
   for(int i=0;i<copied;i++)
     {
      //--- вычислим соответствующий индекс для буферов
      int buffer_index=total-copied+i;
      //--- записываем цены в буферы
      buff1[buffer_index]=rates[i].open;
      buff2[buffer_index]=rates[i].high;
      buff3[buffer_index]=rates[i].low;
      buff4[buffer_index]=rates[i].close;
      //--- зададим цвет свечи
      int color_index=i%cndl_colors;
      col_buffer[buffer_index]=color_index;
     }
   return(true);
  }
//+------------------------------------------------------------------+
//| Возвращает случайным образом символ из Market Watch              |
//+------------------------------------------------------------------+
string GetRandomSymbolName()
  {
//--- количество символов, показываемых в окне "Обзор рынка"
   int symbols=SymbolsTotal(true);
//--- позиция символа в списке - случайное число от 0 до symbols
   int number=MathRand()%symbols;
//--- вернем имя символа по указанной позиции
   return SymbolName(number,true);
  }
//+------------------------------------------------------------------+
//| Изменяет цвет отрезков свечей                                    |
//+------------------------------------------------------------------+
void  ChangeColors(color  &cols[],int plot_colors)
  {
//--- количество цветов 
   int size=ArraySize(cols);
//--- 
   string comm=ChartGetString(0,CHART_COMMENT)+"\r\n\r\n";
 
//--- для каждого цветового индекса зададим новый цвет случайным образом
   for(int plot_color_ind=0;plot_color_ind<plot_colors;plot_color_ind++)
     {
      //--- получим случайное число
      int number=MathRand();
      //--- получим индекс в массиве col[] как остаток от целочисленного деления
      int i=number%size;
      //--- установим цвет для каждого индекса как свойство PLOT_LINE_COLOR
      PlotIndexSetInteger(0,                    //  номер графического стиля
                          PLOT_LINE_COLOR,      //  идентификатор свойства
                          plot_color_ind,       //  индекс цвета, куда запишем цвет
                          cols[i]);             //  новый цвет
      //--- запишем цвета
      comm=comm+StringFormat("CandleColorIndex[%d]=%s \r\n",plot_color_ind,ColorToString(cols[i],true));
      ChartSetString(0,CHART_COMMENT,comm);
     }
//---
  }
//+------------------------------------------------------------------+
//| Изменяет внешний вид свечей                                      |
//+------------------------------------------------------------------+
void ChangeLineAppearance()
  {
//--- строка для формирования информации о свойствах свечей
   string comm="";
//--- запишем имя символа
   comm="\r\n"+symbol+comm;
//--- выведем информацию на график через комментарий
   Comment(comm);
  }