
Стили рисования в MQL5
Введение
В 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
Что мы видим? В MQL5 было добавлено 12 новых стилей рисования, причем 8 новых стилей графического отображения имеют также цветовые буферы, понятие индекса линии MQL4 может запутать.
Таким образом, в MQL5 эквивалентом порядкового номера линии (line index) является индекс графического построения (plot index), который отображается в окне индикатора.
В MQL5 можно отображать не только линии, поэтому и наименование "индекс графического построения" является более точным.
Буферные паттерны
Введем понятие "буферный паттерн" (Buffer-Pattern). Эта характеристика включает в себя количество буферов, их тип и свойства. Можно представить это свойство при помощи строки, используя "D" для буфера данных, "C" для цветового буфера, слева направо, согласно количеству соответствующих буферов, используемых в указанном стиле рисования.
Таким образом, для стилей рисования в MQL5 эти характеристики выглядят следующим образом:
Таблица 2. Буферные паттерны для стилей рисования в MQL5
При наличии нескольких типов графических построений в ваших индикаторах, порядок индексов буферов при связывании индикаторных буферов с массивами при помощи функции SetIndexBuffer(), должен быть организован в порядке возрастания в соответствии с буферными паттернами.
При использовании дополнительных буферов для сохранения промежуточных данных, необходимых для вычислений, эти дополнительные буферы должны быть связаны при помощи функции SetIndexBuffer() после всех буферов, предназначенных для отображения.
В противном случае...
Для демонстрации паттернов буфферов я опубликовал индикатор DemoBufferPattern. Рассмотрите его самостоятельно.
Индикатор DemoDrawType
Рассмотрим индикатор DemoDrawType, иллюстрирующий типы графических отображений.
Входные параметры индикатора приведены на рис. 1-2.
Рисунок 1. Входные
параметры индикатора DemoDrawType
Рисунок 2. Входные
параметры индикатора DemoDrawType (продолжение)
Есть возможность выбора типа отображения (параметр inpDrawType) во вкладке "Входные параметры" индикатора и различных свойств рисования:
Рисунок 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. Классификация стилей рисования по категориям
Примеры отображения данных, содержащих пустые значения, приведены на рисунках 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





- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
круть с цветами очень понравилось =)