English 中文 Español Deutsch 日本語 Português 한국어 Français Italiano Türkçe
Стили рисования в MQL5

Стили рисования в MQL5

MetaTrader 5Индикаторы | 1 апреля 2010, 12:55
7 919 1
Loong
Loong

Введение

В MQL4 есть 6 типов графического отображения индикаторов, а MQL5 доступно уже 18 стилей рисования. Поэтому, возможно, стоит написать статью о стилях рисования в MQL5.

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

Стили рисования

В отличие от MQL5, в языке MQL4 нет свойств Plot, первый параметр функции SetIndexStyle() задает порядковый номер линии, эквивалентом которого в MQL5 является индекс графического построения, задаваемого параметром plot_index.

void SetIndexStyle( int index, int type, int style=EMPTY, int width=EMPTY, color clr=CLR_NONE)
// Параметр index - порядковый номер линии.

В MQL4 есть только 6 стилей отображения, для отображения стиля DRAW_ZIGZAG требуется 2 буфера, для остальных 5 стилей требуется только один буфер.

В MQL4 первый параметр в функции SetIndexStyle() легко идентифицируется как индекс буфера. Это не проблема, если не используется стиль DRAW_ZIGZAG. Кстати, вы когда-нибудь видели индикатор в MQL4, использующий стиль DRAW_ZIGZAG? Я не видел. (В индикаторе ZigZag.mq4, входящем в стандартную поставку MetaTrader 4,  использован стиль DRAW_SECTION).

Сравним стили рисования в MQL4 и MQL5:

Таблица 1. Список стилей рисования в MQL4 и MQL5

Таблица 1. Список стилей рисования в MQL4 и MQL5

Что мы видим? В MQL5 было добавлено 12 новых стилей рисования, причем 8 новых стилей графического отображения имеют также цветовые буферы, понятие индекса линии MQL4 может запутать.

Таким образом, в MQL5 эквивалентом порядкового номера линии (line index) является индекс графического построения (plot index), который отображается в окне индикатора.

В MQL5 можно отображать не только линии, поэтому и наименование "индекс графического построения" является более точным.

Буферные паттерны

Введем понятие "буферный паттерн" (Buffer-Pattern). Эта характеристика включает в себя количество буферов, их тип и свойства. Можно представить это свойство при помощи строки, используя "D" для буфера данных, "C" для цветового буфера, слева направо, согласно количеству соответствующих буферов, используемых в указанном стиле рисования.

Таким образом, для стилей рисования в MQL5 эти характеристики выглядят следующим образом:

Таблица 2. Буферные паттерны для стилей рисования в MQL5

Таблица 2. Буферные паттерны для стилей рисования в MQL5

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

При использовании дополнительных буферов для сохранения промежуточных данных, необходимых для вычислений, эти дополнительные буферы должны быть связаны при помощи функции SetIndexBuffer() после всех буферов, предназначенных для отображения.

В противном случае...

Для демонстрации паттернов буфферов я опубликовал индикатор DemoBufferPattern. Рассмотрите его самостоятельно.

Индикатор DemoDrawType

Рассмотрим индикатор DemoDrawType, иллюстрирующий типы графических отображений.

Входные параметры индикатора приведены на рис. 1-2.

Рисунок 3. Входные параметры индикатора

Рисунок 1. Входные параметры индикатора DemoDrawType

Рисунок 4. Входные параметры индикатора (продолжение)

Рисунок 2. Входные параметры индикатора DemoDrawType (продолжение)

Есть возможность выбора типа отображения (параметр inpDrawType) во вкладке "Входные параметры" индикатора и различных свойств рисования:

Рис. 5 Список стилей рисования
Рисунок 3. Список типов отображения индикатора (стилей рисования)

Таким образом, нам нужно определить входные переменные для каждого атрибута и реализовать функцию проверки корректности этих переменных.

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

//--- input parameters
input ENUM_DRAW_TYPE InpDrawType    = DRAW_LINE;
input ENUM_LINE_STYLE InpLineStyle  = STYLE_SOLID;
input bool InpShowData        = true;
input uchar InpArrow          = 159;
input int InpArrowShift       = -10;
input int InpDrawBegin        = 10;
input int InpShift            = 10;
input int InpLineWidth        = 1;
input int InpColorNum         = 60;
input color InpPlotColor      = RoyalBlue;
input double InpEmptyValue    = 0.0;
input string InpLabel         = "Value";
input bool InpTestEmptyValue  = false;

//Примечание: 
//Переменные, объявленные на глобальном уровне не следует путать 
//с глобальными переменными клиентского терминала, работа с которыми осуществляется 
//посредством функций GlobalVariable...() 

//--- поскольку мы не можем изменять значения входных параметров в коде программы,
//--- нам понадобятся глобальные переменные
ENUM_DRAW_TYPE iDrawType      = DRAW_LINE;
ENUM_LINE_STYLE iLineStyle    = STYLE_SOLID;
bool bShowData       = true;
uchar uArrow         = 181;
int iArrowShift      = -10;
int iDrawBegin       = 10;
int iShift           = 10;
int iLineWidth       = 1;
int iColorNum        = 60;
color iPlotColor     = RoyalBlue;
string sLabel        = "";
bool bTestEmptyValue = false;
double dEmptyValue   = EMPTY_VALUE;

//+------------------------------------------------------------------+
//| Проверка корректности входных параметров                         |
//+------------------------------------------------------------------+
bool checkInput()
  {
   if(InpDrawType<DRAW_NONE || InpDrawType>DRAW_COLOR_CANDLES) return(false);
   else iDrawType = InpDrawType;
   if(InpLineStyle<STYLE_SOLID || InpLineStyle>STYLE_DASHDOTDOT) return(false);
   else iLineStyle = InpLineStyle;
   bShowData   = InpShowData;
   uArrow      = InpArrow;    //if uArrow>255, MQL5 will set Arrow as uArrow%256
   iArrowShift = InpArrowShift;
   iDrawBegin  = InpDrawBegin;
   iShift      = InpShift;
   iLineWidth  = InpLineWidth;
   iColorNum   = InpColorNum;
   iPlotColor  = InpPlotColor;
   //if(InpEmptyValue<=0.0) dEmptyValue=0.0;
   //else dEmptyValue=EMPTY_VALUE;
   dEmptyValue = InpEmptyValue;  // It may be not 0.0 or EMPTY_VALUE
   sLabel      = InpLabel;
   bTestEmptyValue = InpTestEmptyValue;
   return(true);
  }
Примеры всех 18 стилей рисования представлены на рисунках 4-21:

Рисунок 4. Пример стиля рисования DRAW_NONE

Рисунок 5. Пример стиля рисования DRAW_LINE

Рисунок 6. Пример стиля рисования DRAW_HISTOGRAM

Рисунок 7. Пример стиля рисования DRAW_ARROW

Рисунок 8. Пример стиля рисования DRAW_SECTION

Рисунок 9. Пример стиля рисования DRAW_HISTOGRAM2

Рисунок 10. Пример стиля рисования DRAW_FILLING

Рисунок 11. Пример стиля рисования DRAW_ZIGZAG

Рисунок 12. Пример стиля рисования DRAW_BARS

Рисунок 13. Пример стиля рисования DRAW_CANDLES

Рисунок 14. Пример стиля рисования DRAW_COLOR_LINE

Рисунок 15. Пример стиля рисования DRAW_COLOR_HISTOGRAM

Рисунок 16. Пример стиля рисования DRAW_COLOR_ARROW

Рисунок 17. Пример стиля рисования DRAW_COLOR_SECTION

Рисунок 18. Пример стиля рисования DRAW_COLOR_HISTOGRAM2

Рисунок 19. Пример стиля рисования DRAW_COLOR_ZIGZAG

Рисунок 20. Пример стиля рисования DRAW_COLOR_BARS

Рисунок 21. Пример стиля рисования DRAW_COLOR_CANDLES


Отображение пустых значений в данных

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

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

Поскольку индикатор разработан для иллюстрации стилей рисования, пришло время рассмотреть вопрос отображения нулевых значений. По способу отображения пустых значений стили рисования могут быть разбиты на три категории, представленные в таблице 3:

Таблица 3. Классификация стилей рисования по категориям

Таблица 3. Классификация стилей рисования по категориям

Примеры отображения данных, содержащих пустые значения, приведены на рисунках 22-29.

Рисунок 22. Пример стиля рисования DRAW_LINE (с пустыми значениями)

Рисунок 23. Пример стиля рисования DRAW_SECTION (с пустыми значениями)

Рисунок 24. Пример стиля рисования DRAW_HISTOGRAM2 (с пустыми значениями)

Рисунок 25. Пример стиля рисования DRAW_BARS (с пустыми значениями)

Рисунок 26. Пример стиля рисования DRAW_FILLING (с пустыми значениями)

Рисунок 27. Пример стиля рисования DRAW_ZIGZAG (с пустыми значениями)

Рисунок 28. Пример стиля рисования DRAW_COLOR_ARROW (с пустыми значениями)

Рисунок 29. Пример стиля рисования DRAW_COLOR_CANDLES (с пустыми значениями)

Полный исходный код индикатора:

//+------------------------------------------------------------------+
//|                                                 DemoDrawType.mq5 |
//|                             Copyright 2010, Loong@forum.mql4.com |
//|                             http://login.mql5.com/en/users/Loong |
//+------------------------------------------------------------------+
#property copyright "2010, Loong@forum.mql4.com"
#property link      "http://login.mql5.com/en/users/Loong"
#property version   "1.00"

//#property indicator_chart_window
#property indicator_separate_window //для более наглядной иллюстрации
#property indicator_plots   1       //должно быть установлено, может быть указано большее значение, чем необходимо
                               //но не больше чем значение свойства indicator_buffers 
#property indicator_buffers 5       //должно быть установлено, может быть указано большее значение, чем необходимо
//+------------------------------------------------------------------+
//| Структура DrawType,                                              |
//| Cодержит информацию о типе отображения и буферном паттерне       |
//+------------------------------------------------------------------+
struct SLoongDrawType                       // Структура Draw Type
  {
   ENUM_DRAW_TYPE    eDrawType;              // тип рисования
   int               iDrawType;             // численное значение типа рисования, используется только для просмотра
   int               iNumBufferData;        // кол-во буферов данных
   int               iNumBufferColor;       // кол-во цветовых буферов
   string            sDrawType;             // строка с наименованием типа отображения
   string            sDrawTypeDescription;  // описание типа отображения (как в документации)
  };
//+------------------------------------------------------------------+
//| Массив структур DrawType, содержащий все стили отображения       |
//+------------------------------------------------------------------+
const SLoongDrawType caDrawType[]=
  {
     { DRAW_NONE,              0,    1,    0,    "DRAW_NONE",             "Not drawn" },
     { DRAW_LINE,              1,    1,    0,    "DRAW_LINE",             "Line" },
     { DRAW_HISTOGRAM,         2,    1,    0,    "DRAW_HISTOGRAM",        "Histogram from the zero line" },
     { DRAW_ARROW,             3,    1,    0,    "DRAW_ARROW",            "Drawing arrows" },
     { DRAW_SECTION,           4,    1,    0,    "DRAW_SECTION",          "Section" },
     { DRAW_HISTOGRAM2,        5,    2,    0,    "DRAW_HISTOGRAM2",       "Histogram of the two indicator buffers" },
     { DRAW_ZIGZAG,            6,    2,    0,    "DRAW_ZIGZAG",           "Style Zigzag allows vertical section on the bar" },
     { DRAW_FILLING,           7,    2,    0,    "DRAW_FILLING",          "Color fill between the two levels" },
     { DRAW_BARS,              8,    4,    0,    "DRAW_BARS",             "Display as a sequence of bars" },
     { DRAW_CANDLES,           9,    4,    0,    "DRAW_CANDLES",          "Display as a sequence of candlesticks" },
     { DRAW_COLOR_LINE,       10,    1,    1,    "DRAW_COLOR_LINE",       "Multicolored line" },
     { DRAW_COLOR_HISTOGRAM,  11,    1,    1,    "DRAW_COLOR_HISTOGRAM",  "Multicolored histogram from the zero line" },
     { DRAW_COLOR_ARROW,      12,    1,    1,    "DRAW_COLOR_ARROW",      "Drawing multicolored arrows" },
     { DRAW_COLOR_SECTION,    13,    1,    1,    "DRAW_COLOR_SECTION",    "Multicolored section" },
     { DRAW_COLOR_HISTOGRAM2, 14,    2,    1,    "DRAW_COLOR_HISTOGRAM2", "Multicolored histogram of the two indicator buffers" },
     { DRAW_COLOR_ZIGZAG,     15,    2,    1,    "DRAW_COLOR_ZIGZAG",     "Multicolored ZigZag" },
     { DRAW_COLOR_BARS,       16,    4,    1,    "DRAW_COLOR_BARS",       "Multicolored bars" },
     { DRAW_COLOR_CANDLES,    17,    4,    1,    "DRAW_COLOR_CANDLES",    "Multicolored candlesticks" }
  };

//--- input parameters
input ENUM_DRAW_TYPE InpDrawType    = DRAW_LINE;
input ENUM_LINE_STYLE InpLineStyle  = STYLE_SOLID;
input bool InpShowData        = true;
input uchar InpArrow          = 159;
input int InpArrowShift       = -10;
input int InpDrawBegin        = 10;
input int InpShift            = 10;
input int InpLineWidth        = 1;
input int InpColorNum         = 60;
input color InpPlotColor      = RoyalBlue;
input double InpEmptyValue    = 0.0;
input string InpLabel         = "Value";
input bool InpTestEmptyValue  = false;

//Примечание: 
//Переменные, объявленные на глобальном уровне не следует путать 
//с глобальными переменными клиентского терминала, работа с которыми осуществляется 
//посредством функций GlobalVariable...() 
ENUM_DRAW_TYPE iDrawType      = DRAW_LINE;
ENUM_LINE_STYLE iLineStyle    = STYLE_SOLID;
bool bShowData       = true;
uchar uArrow         = 181;
int iArrowShift      = -10;
int iDrawBegin       = 10;
int iShift           = 10;
int iLineWidth       = 1;
int iColorNum        = 60;
color iPlotColor     = RoyalBlue;
string sLabel        = "";
bool bTestEmptyValue = false;
double dEmptyValue   = EMPTY_VALUE;

//--- индикаторные буферы
double DC[];   // цветовой буфер
double D1[];   // буферы данных
double D2[];
double D3[];
double D4[];
//+------------------------------------------------------------------+
//| Проверка входных параметров                                      |
//+------------------------------------------------------------------+
bool checkInput()
  {
   if(InpDrawType<DRAW_NONE || InpDrawType>DRAW_COLOR_CANDLES) return(false);
   else iDrawType=InpDrawType;
   if(InpLineStyle<STYLE_SOLID || InpLineStyle>STYLE_DASHDOTDOT) return(false);
   else iLineStyle=InpLineStyle;
   bShowData   =InpShowData;
   uArrow=InpArrow;    //если uArrow>255, MQL5 установит Arrow как uArrow%256
   iArrowShift = InpArrowShift;
   iDrawBegin  = InpDrawBegin;
   iShift      = InpShift;
   iLineWidth  = InpLineWidth;
   iColorNum   = InpColorNum;
   iPlotColor  = InpPlotColor;
//if(InpEmptyValue<=0.0) dEmptyValue=0.0;
//else dEmptyValue=EMPTY_VALUE;
   dEmptyValue=InpEmptyValue;  // Не может быть равно 0.0 или EMPTY_VALUE
   sLabel=InpLabel;
   bTestEmptyValue=InpTestEmptyValue;
   return(true);
  }
//+------------------------------------------------------------------+
//| Функция для красивого цветового распределения                    |
//+------------------------------------------------------------------+
int ColorInc6section(int i,int iBase=63,int iI=0xFF)
  {
   int id  = (int)MathFloor((double)iBase/6.0);
   int ip  = (int)MathFloor((double)iI/id);
   int MA_Rinc=0;
   int MA_Ginc=0;
   int MA_Binc=0;
   color iColor=0;
   if(i<=0)        {iColor =       iI; MA_Rinc=0; MA_Ginc=0; MA_Binc=0;}
   else if(i<1*id) {iColor =       iI; MA_Rinc=  0; MA_Ginc= ip; MA_Binc=  0;}
   else if(i<2*id) {iColor =   257*iI; MA_Rinc=-ip; MA_Ginc=  0; MA_Binc=  0;}
   else if(i<3*id) {iColor =   256*iI; MA_Rinc=  0; MA_Ginc=  0; MA_Binc= ip;}
   else if(i<4*id) {iColor = 65792*iI; MA_Rinc=  0; MA_Ginc=-ip; MA_Binc=  0;}
   else if(i<5*id) {iColor = 65536*iI; MA_Rinc= ip; MA_Ginc=  0; MA_Binc=  0;}
   else if(i<6*id) {iColor = 65537*iI; MA_Rinc=  0; MA_Ginc=  0; MA_Binc=-ip;}
   else            {iColor =       iI; MA_Rinc=  0; MA_Ginc=  0; MA_Binc=  0;}
   int iColorInc=(MA_Rinc+256*MA_Ginc+65536*MA_Binc);
   return iColor+iColorInc*(i%id);
  }
//+------------------------------------------------------------------+
//| Установка цветов графического отображения plot_index             |
//+------------------------------------------------------------------+
void SetPlotColorIndexes(int plot_index)
  {
   int iIllumination=0xFF;
//color cBack=(color)ChartGetInteger(0,CHART_COLOR_BACKGROUND);
//Print("BACKGROUND is ",cBack);
//if(White==cBack) iIllumination=0x9F; //для лучшего визуального эффекта
   PlotIndexSetInteger(plot_index,PLOT_COLOR_INDEXES,iColorNum);
   for(int i=0;i<iColorNum;i++)
      PlotIndexSetInteger(plot_index,PLOT_LINE_COLOR,i,ColorInc6section(i,iColorNum,iIllumination));
  }
//+------------------------------------------------------------------+
//| Установка типов рисования и других свойств                       |
//+------------------------------------------------------------------+
bool SetPlotProperties()
  {
//Print("iDrawType="+iDrawType);
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,iDrawType);
   PlotIndexSetInteger(0,PLOT_LINE_STYLE,iLineStyle);
   PlotIndexSetInteger(0,PLOT_SHIFT,iShift);

//--- нужно ли показывать значения индикатора в окне DataWindow
   PlotIndexSetInteger(0,PLOT_SHOW_DATA,bShowData);

   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,iDrawBegin);
   PlotIndexSetInteger(0,PLOT_LINE_WIDTH,iLineWidth);
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,dEmptyValue);
   PlotIndexSetString(0,PLOT_LABEL,sLabel);
   switch(iDrawType) //  кол-во буферов данных, цвета
     {
      case DRAW_COLOR_ARROW:       //1,    1,
         SetIndexBuffer(0,D1,INDICATOR_DATA);
         SetIndexBuffer(1,DC,INDICATOR_COLOR_INDEX);
         PlotIndexSetInteger(0,PLOT_ARROW,uArrow);
         PlotIndexSetInteger(0,PLOT_ARROW_SHIFT,iArrowShift);
         SetPlotColorIndexes(0);
         break;

      case DRAW_ARROW:             //1,    0,
         SetIndexBuffer(0,D1,INDICATOR_DATA);
         PlotIndexSetInteger(0,PLOT_ARROW,uArrow);
         PlotIndexSetInteger(0,PLOT_ARROW_SHIFT,iArrowShift);
         PlotIndexSetInteger(0,PLOT_LINE_COLOR,iPlotColor);
         break;

      case DRAW_COLOR_LINE:        //1,    1,
      case DRAW_COLOR_HISTOGRAM:   //1,    1,
      case DRAW_COLOR_SECTION:     //1,    1,
         SetIndexBuffer(0,D1,INDICATOR_DATA);
         SetIndexBuffer(1,DC,INDICATOR_COLOR_INDEX);
         SetPlotColorIndexes(0);
         break;

      case DRAW_NONE:              //1,    0,
      case DRAW_LINE:              //1,    0,
      case DRAW_HISTOGRAM:         //1,    0,
      case DRAW_SECTION:           //1,    0,
         SetIndexBuffer(0,D1,INDICATOR_DATA);
         PlotIndexSetInteger(0,PLOT_LINE_COLOR,iPlotColor);
         break;

      case DRAW_COLOR_HISTOGRAM2:  //2,    1,
      case DRAW_COLOR_ZIGZAG:      //2,    1,
         SetIndexBuffer(0,D1,INDICATOR_DATA);
         SetIndexBuffer(1,D2,INDICATOR_DATA);
         SetIndexBuffer(2,DC,INDICATOR_COLOR_INDEX);
         SetPlotColorIndexes(0);
         break;

      case DRAW_HISTOGRAM2:        //2,    0,
      case DRAW_ZIGZAG:            //2,    0,
         SetIndexBuffer(0,D1,INDICATOR_DATA);
         SetIndexBuffer(1,D2,INDICATOR_DATA);
         PlotIndexSetInteger(0,PLOT_LINE_COLOR,iPlotColor);
         break;

      case DRAW_FILLING:           //2,    0,
         SetIndexBuffer(0,D1,INDICATOR_DATA);
         SetIndexBuffer(1,D2,INDICATOR_DATA);
         PlotIndexSetInteger(0,PLOT_LINE_COLOR,iPlotColor);
         break;

      case DRAW_COLOR_BARS:        //4,    1,
      case DRAW_COLOR_CANDLES:     //4,    1,
         SetIndexBuffer(0,D1,INDICATOR_DATA);
         SetIndexBuffer(1,D2,INDICATOR_DATA);
         SetIndexBuffer(2,D3,INDICATOR_DATA);
         SetIndexBuffer(3,D4,INDICATOR_DATA);
         SetIndexBuffer(4,DC,INDICATOR_COLOR_INDEX);
         SetPlotColorIndexes(0);
         break;
      case DRAW_BARS:              //4,    0,
      case DRAW_CANDLES:           //4,    0,
         SetIndexBuffer(0,D1,INDICATOR_DATA);
         SetIndexBuffer(1,D2,INDICATOR_DATA);
         SetIndexBuffer(2,D3,INDICATOR_DATA);
         SetIndexBuffer(3,D4,INDICATOR_DATA);
         PlotIndexSetInteger(0,PLOT_LINE_COLOR,iPlotColor);
         break;
     }
   return(true);
  }
//+------------------------------------------------------------------+
//| Функция инициализации пользовательского индикатора               |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- ArrayInit
   bool bInitBuffer=true;
   if(bInitBuffer)
     {
      ArrayInitialize(D1,dEmptyValue);
      ArrayInitialize(D2,dEmptyValue);
      ArrayInitialize(D3,dEmptyValue);
      ArrayInitialize(D4,dEmptyValue);
      ArrayInitialize(DC,dEmptyValue);
     }
   checkInput();
   SetPlotProperties();
//--- установка точности отображения
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
   IndicatorSetString(INDICATOR_SHORTNAME,"DemoDrawType : "+caDrawType[iDrawType].sDrawType);
   return(0);
  }
//+------------------------------------------------------------------+
//| Функция расчета пользовательского индикатора                     |
//+------------------------------------------------------------------+
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[])
  {
//--- дополнительные переменные
   int i=0;
//--- установим начальную позицию
   if(i<prev_calculated) i=prev_calculated-1;
//--- расчет
   while(i<rates_total)
     {
      switch(iDrawType) // Буферов данных, цвета, что рисуется если буфер содежит dEmptyValue
        {
         case DRAW_COLOR_LINE:        //1, 1, ничего не рисуется
            DC[i]=(double)(i%iColorNum);
         case DRAW_LINE:              //1, 0, ничего не рисуется
         case DRAW_NONE:              //1, 0, ничего не рисуется
            if(bTestEmptyValue)
              {
               if(i%5==1)D1[i]=high[i];
               else D1[i]=dEmptyValue;
              }
            else
               D1[i]=close[i];
            break;

         case DRAW_COLOR_SECTION:     //1, 1, связываются не dEmptyValue
            DC[i]=(double)(i%iColorNum);
         case DRAW_SECTION:           //1, 0, соединяются смежные не dEmptyValue
            if(bTestEmptyValue)
              {
               if(i%5==1)D1[i]=close[i];
               else D1[i]=dEmptyValue;
              }
            else
               D1[i]=close[i];
            break;

         case DRAW_FILLING:           //2, 0,
            //DC[i]=(double)(i%iColorNum);
            if(bTestEmptyValue)
              {
               if(i%5==1)
                 {
                  D1[i]=high[i];
                  D2[i]=low[i];
                 }
               else
                 {
                  D1[i]=dEmptyValue;
                  D2[i]=dEmptyValue;
                 }
              }
            else
              {
               D1[i]=high[i];
               D2[i]=low[i];
              }
            break;

         case DRAW_COLOR_ZIGZAG:      //2, 1,
            DC[i]=(double)(i%iColorNum);
         case DRAW_ZIGZAG:            //2, 0,
            if(bTestEmptyValue)
              {
               if(i%5==1)D1[i]=high[i];
               else D1[i]=dEmptyValue;
               if(i%5==4)D2[i]=low[i];
               else D2[i]=dEmptyValue;
              }
            else
              {
               D1[i]=high[i];
               D2[i]=low[i];
              }
            break;

         case DRAW_COLOR_ARROW:       //1, 1, рисуется стрелка для не dEmptyValue
         case DRAW_COLOR_HISTOGRAM:   //1, 1, рисуется только для не dEmptyValue
            DC[i]=(double)(i%iColorNum);
         case DRAW_ARROW:             //1, 0, рисуется стрелка для не dEmptyValue
         case DRAW_HISTOGRAM:         //1, 0, рисуется только для не dEmptyValue
            if(bTestEmptyValue)
              {
               if(i%5==1)D1[i]=close[i];
               else D1[i]=dEmptyValue;
              }
            else
              {
               D1[i]=close[i];
              }
            break;

         case DRAW_COLOR_HISTOGRAM2:  //2, 1, рисуется только не dEmptyValue
            DC[i]=(double)(i%iColorNum);
         case DRAW_HISTOGRAM2:        //2, 0, рисуется только не dEmptyValue
            if(bTestEmptyValue)
              {
               if(i%5==1)
                 {
                  D1[i]=high[i];
                  D2[i]=low[i];
                 }
               else
                 {
                  D1[i]=dEmptyValue;
                  D2[i]=dEmptyValue;
                 }
              }
            else
              {
               D1[i]=high[i];
               D2[i]=low[i];
              }
            break;

         case DRAW_COLOR_BARS:        //4, 1, рисуется только не dEmptyValue
         case DRAW_COLOR_CANDLES:     //4, 1, рисуется только не dEmptyValue
            DC[i]=(double)(i%iColorNum);
         case DRAW_BARS:              //4, 0, рисуется только не dEmptyValue
         case DRAW_CANDLES:           //4, 0, рисуется только не dEmptyValue
            if(bTestEmptyValue)
              {
               if(i%5==1)
                 {
                  D1[i]=open[i];
                  D2[i]=high[i];
                  D3[i]=low[i];
                  D4[i]=close[i];
                 }
               else
                 {
                  D1[i]=dEmptyValue;
                  D2[i]=dEmptyValue;
                  D3[i]=dEmptyValue;
                  D4[i]=dEmptyValue;
                 }
              }
            else
              {
               D1[i]=open[i];
               D2[i]=high[i];
               D3[i]=low[i];
               D4[i]=close[i];
              }
            break;
        }
      //---
      i++;
     }
//--- возвращаем значение для переменной prev_calculated (при следующем вызове)
   return(rates_total);
  }
//+------------------------------------------------------------------+

Ответы на некоторые вопросы

Q: Индикатор ничего не рисует.
A: Цель индикатора - дать возможность протестировать все стили рисования без написания кода, если входные параметры заданы неверно, данные не будут отображаться.

Q: Массив caDrawType[] похоже бесполезный, он используется лишь для получения строкового наименования DrawType?
A: Согласен, этот массив взят из другого кода. В некоторых случаях массив структур caDrawType[] может быть очень полезным, но мы рассмотрим этот вопрос в следующей статье.

Выводы

Вы можете нарисовать все что захотите.

Да пребудет с вами Код (May the Code be with you).

Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/45

Прикрепленные файлы |
demodrawtype.mq5 (17.52 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (1)
Vasily
Vasily | 1 апр. 2010 в 14:06

круть с цветами очень понравилось =)

Создание тиковых индикаторов Создание тиковых индикаторов
В этой статье описывается создание двух индикаторов: строящего тиковый график цены и рисующего "тиковые свечи" - свечи, содержащие заданное число тиков. Каждый из рассмотренных индикаторов записывает поступающие значения цен в файл для построения индикаторов при повторном запуске терминала (эти данные также могут использоваться другими приложениями).
Создание индикатора с возможностями графического управления Создание индикатора с возможностями графического управления
Те, кто более-менее знаком с рыночными настроениями не понаслышке, знает индикатор MACD, или полное название Схождение Расхождение Скользящих Средних, и знает его как мощный инструмент анализа движения цены, которым пользуются трейдеры с первых моментов появления методов компьютерного анализа. В данной статье мы рассмотрим возможные модификации MACD и реализуем их в одном индикаторе с возможностью графического переключения между модификациями.
Пример написания игры "Змейка" на MQL5 Пример написания игры "Змейка" на MQL5
В статье рассматривается пример написания игры "Змейка". Создание игр в 5-ой версии языка MQL стало возможным, в первую очередь, благодаря обработке событий. Поддержка объектно-ориентированного программирования значительно упрощает данный процесс. Также вы узнаете особенности обработки событий, примеры работы со стандартной библиотекой MQL5 и способы периодического вызова функций.
Когда нужно использовать указатели в MQL5 Когда нужно использовать указатели в MQL5
Все объекты в MQL5 по умолчанию передаются по ссылке, но есть возможность использовать и указатели объектов. При этом есть опасность получить в качестве параметра функции указатель неинициализированного объекта. В этом случае работа программы будет завершена критически с последующей выгрузкой. Автоматически создаваемые объекты как правило такой ошибки не вызывают, и в этом отношении они достаточно безопасны. В этой статье мы попробуем разобраться в чем разница между ссылкой и указателей, когда оправдано использование указателей и как написать безопасный код с использованием указателей.