DRAW_FILLING

Стиль DRAW_FILLING рисует цветную область между значениями двух индикаторных буферов. Фактически этот стиль рисует две линии и закрашивает пространство между ними одним из двух заданных цветов. Предназначен для создания индикаторов, рисующих каналы. Ни один из буферов не может содержать только пустые значения, так как в этом случае отрисовка не происходит.

Можно задавать два цвета заливки:

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

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

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

   #define INDICATOR_EMPTY_VALUE -1.0
   ...
//--- значение INDICATOR_EMPTY_VALUE (пустое значение) не будет участвовать в расчете
   PlotIndexSetDouble(индекс_построения_DRAW_FILLING,PLOT_EMPTY_VALUE,INDICATOR_EMPTY_VALUE);

Отрисовка на барах, которые не участвуют в расчете индикатора, будет зависеть от значений в индикаторных буферах:

  • Бары, для которых значения обоих индикаторных буферов равны 0, не участвуют в отрисовке индикатора. То есть область с нулевыми значениями не будет закрашиваться.

DRAW_FILLING_without_drawing

  • Бары, для которых значения индикаторных буферов равны "пустому значению", участвуют в отрисовке индикатора. Область с пустыми значениями будет закрашиваться таким образом, чтобы соединять области со значащими значениями.

DRAW_FILLING_with_drawing

При этом важно отметить, что если "пустое значение" равняется нулю, то бары, не участвующие в расчете индикатора, также будут закрашиваться.

Количество требуемых буферов для построения DRAW_FILLING — 2.

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

DRAW_FILLING

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

//+------------------------------------------------------------------+
//|                                                 DRAW_FILLING.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_FILLING"
#property description "Рисует в отдельном окне канал между двумя средними"
#property description "Цвет заливки канала меняется случайным образом"
#property description "через каждые N тиков"
 
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   1
//--- plot Intersection
#property indicator_label1  "Intersection"
#property indicator_type1   DRAW_FILLING
#property indicator_color1  clrRed,clrBlue
#property indicator_width1  1
//--- input параметры
input int      Fast=13;          // период быстрой скользящей средней
input int      Slow=21;          // период медленной скользящей средней
input int      shift=1;          // сдвиг средних в будущее (положительный)
input int      N=5;              // кол-во тиков для изменения 
//--- индикаторные буферы
double         IntersectionBuffer1[];
double         IntersectionBuffer2[];
int fast_handle;
int slow_handle;
//--- массив для хранения цветов
color colors[]={clrRed,clrBlue,clrGreen,clrAquamarine,clrBlanchedAlmond,clrBrown,clrCoral,clrDarkSlateGray};
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,IntersectionBuffer1,INDICATOR_DATA);
   SetIndexBuffer(1,IntersectionBuffer2,INDICATOR_DATA);
//---
   PlotIndexSetInteger(0,PLOT_SHIFT,shift);
//---
   fast_handle=iMA(_Symbol,_Period,Fast,0,MODE_SMA,PRICE_CLOSE);
   slow_handle=iMA(_Symbol,_Period,Slow,0,MODE_SMA,PRICE_CLOSE);
//---
   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=0;
//--- считаем тики для изменения стиля, цвета и толщины линии
   ticks++;
//--- если накопилось достаточное число тиков
   if(ticks>=N)
     {
      //--- меняем свойства линии
      ChangeLineAppearance();
      //--- сбрасываем счетчик тиков в ноль
      ticks=0;
     }
 
//--- делаем первый расчет индикатора или данные изменились и требуется полный перерасчет
   if(prev_calculated==0)
     {
      //--- копируем все значения индикаторов в соответствующие буферы
      int copied1=CopyBuffer(fast_handle,0,0,rates_total,IntersectionBuffer1);
      int copied2=CopyBuffer(slow_handle,0,0,rates_total,IntersectionBuffer2);
     }
   else // экономно заполняем только те данные, которые обновились
     {
      //--- получим разницу в барах между текущим и предыдущим запуском OnCalculate()
      int to_copy=rates_total-prev_calculated;
      //--- если разницы нет, то все равно будем копировать одно значение - на нулевом баре
      if(to_copy==0) to_copy=1;
      //--- копируем to_copy значений в самый конец индикаторных буферов
      int copied1=CopyBuffer(fast_handle,0,0,to_copy,IntersectionBuffer1);
      int copied2=CopyBuffer(slow_handle,0,0,to_copy,IntersectionBuffer2);
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Изменяет цвета заливки канала                                    |
//+------------------------------------------------------------------+
void ChangeLineAppearance()
  {
//--- строка для формирования информации о свойствах линии
   string comm="";
//--- блок изменения цвета линии
   int number=MathRand(); // получим случайное число
//--- делитель числа равен размеру массива colors[]
   int size=ArraySize(colors);
 
//--- получим индекс для выбора нового цвета как остаток от целочисленного деления
   int color_index1=number%size;
//--- установим первый цвет как свойство PLOT_LINE_COLOR
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,colors[color_index1]);
//--- запишем первый цвет
   comm=comm+"\r\nColor1 "+(string)colors[color_index1];
 
//--- получим индекс для выбора нового цвета как остаток от целочисленного деления
   number=MathRand(); // получим случайное число
   int color_index2=number%size;
//--- установим второй цвет как свойство PLOT_LINE_COLOR
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,colors[color_index2]);
//--- запишем второй цвет
   comm=comm+"\r\nColor2 "+(string)colors[color_index2];
//--- выведем информацию на график через комментарий
   Comment(comm);
  }