SetIndexBuffer (1,ExtPDIBuffer);
SetIndexBuffer (2,ExtNDIBuffer);
SetIndexBuffer (3,ExtPDBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer (4,ExtNDBuffer, INDICATOR_CALCULATIONS);
// SetIndexBuffer (5,ExtTmpBuffer, INDICATOR_CALCULATIONS);
Теперь массив ExtTmpBuffer является просто динамическим массивом.
Откомпилируем код индикатора и присоединим индикатор к графику в терминале MetaTrader 5.
Терминал выдаст ошибку:
Это произошло потому, что мы перед заполнением данного массива значениями не указали его размера и не зарезервировали под него память.
Так что его размер был равен нулю, когда мы попытались в него что-то записать.
Статическим мы этот массив сделать тоже не можем, т.е. объявить его сразу с указанием размера, так как значения такого промежуточного массива рассчитываются в функции обратного вызова OnCalculate на основе загруженной в функцию OnCalculate истории цен, а именно массивов open [], high [], low [], close [].
Но точный размер массивов open [], high [], low [], close [] неизвестен, он обозначается лишь переменной rates_total.
Хорошо, но мы можем в функции OnCalculate применить функцию ArrayResize, чтобы установить размер массива:
ArrayResize (ExtTmpBuffer, rates_total);
Теперь после компиляции индикатор заработает как надо.
Но дело в том, что в функции OnCalculate мы сначала рассчитываем индикатор для всей ценовой истории, т.е. для rates_total значений, а затем при поступлении нового тика по символу индикатора, и соответственно вызове функции OnCalculate, мы рассчитываем значение индикатора для этого нового тика по символу и записываем новое значение индикатора в его массив буфера.
Чтобы это реализовать с промежуточным массивом, нужно внимательно следить за его размером и записывать новое значение в конец массива.
Вместо всего этого, проще всего привязать промежуточный массив к буферу индикатора с помощью функции SetIndexBuffer и таким образом решить все эти проблемы.
Аналогичная ситуация возникает когда значения таких промежуточных массивов заполняются с помощью функции CopyBuffer, которая распределяет размер принимающего массива под размер копируемых данных.
Если копируется вся ценовая история, то проблем нет и в этом случае использовать INDICATOR_CALCULATIONS необязательно.
Если же мы хотим скопировать только одно новое поступившее значение, функция CopyBuffer определит размер принимающего массива как 1, и нужно будет использовать этот принимающий массив как еще один массив-посредник, из которого уже записывать значение в промежуточный массив индикатора. И в этом случае просто функцией ArrayResize для принимающего массива проблему не решить.
Теперь что нам делать, если мы хотим раскрашивать наши диаграммы индикатора в разные цвета в зависимости от цены?
Во-первых, мы должны указать, что наша графическая форма нашего графического построения является цветной, например:
#property indicator_type1 DRAW_COLOR_LINE
В идентификатор геометрической формы добавляется слово COLOR.
Далее значение свойства #property indicator_buffers увеличивается на единицу и объявляется еще один массив для хранения цвета.
Функцией SetIndexBuffer объявленный дополнительный массив сопоставляется с буфером цвета индикатора, например:
SetIndexBuffer (4,ExtColorsBuffer, INDICATOR_COLOR_INDEX);
В свойстве #property indicator_color, раскрашиваемого графического построения, указывается несколько цветов, например:
#property indicator_color1 Green, Red
И, наконец, каждому элементу массива, представляющего буфер цвета индикатора, присваивается номер цвета, определенный в свойстве #property indicator_color.
В данном случае, это 0.0 и 1.0.
Теперь при отрисовке диаграммы индикатора, из буфера берется значение диаграммы, по позиции значения оно сопоставляется со значением буфера цвета, и элемент диаграммы становится цветным.
Вместо свойства #property indicator_color, цвета графического построения можно задать программным способом:
//Задаем количество индексов цветов для графического построения
PlotIndexSetInteger (0,PLOT_COLOR_INDEXES,2);
//Задаем цвет для каждого индекса
PlotIndexSetInteger (0,PLOT_LINE_COLOR,0,Blue); //Нулевой индекс цвета – синий цвет
PlotIndexSetInteger (0,PLOT_LINE_COLOR,1,Orange); //Первый индекс цвета – оранжевый цвет
Где первый параметр – индекс графического построения, соответственно первое графическое построение имеет индекс 0.
Это идентично объявлению:
#property indicator_color1 Blue, Orange
Двинемся дальше по свойствам индикатора.
Толщина линии диаграммы индикатора задается свойством indicator_widthN, где N – номер графического построения, например:
#property indicator_width1 1
Также можно задать стиль линии диаграммы индикатора – сплошная линия, прерывистая, пунктирная, штрих-пунктирная, штрих – с помощью свойства indicator_styleN, где N – номер графического построения, например:
#property indicator_style1 STYLE_SOLID
И, наконец, свойство indicator_labelN указывает метки диаграмм индикатора в DataWindow или Окно данных, например:
#property indicator_label1 «ADX»
#property indicator_label2 "+DI»
#property indicator_label3 "-DI»
Другие свойства можно посмотреть в справочнике.
Правда можно отметить еще одну группу свойств, которая позволяет нарисовать горизонтальный уровень индикатора в отдельном окне, например:
#property indicator_level1 0.0
#property indicator_levelcolor Red
#property indicator_levelstyle STYLE_SOLID
#property indicator_levelwidth 2
В редакторе MQL5, в окне Navigator (Навигатор), в разделе Indicators-> Examples откроем исходный код индикатора ADX.
Блок объявления свойств индикатора выглядит следующим образом:
#property copyright «2009, MetaQuotes Software Corp.»
#property link "http://www.mql5.com"
#property description «Average Directional Movement Index»
#property indicator_separate_window
#property indicator_buffers 6
#property indicator_plots 3
#property indicator_type1 DRAW_LINE
#property indicator_color1 LightSeaGreen
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
#property indicator_type2 DRAW_LINE
#property indicator_color2 YellowGreen
#property indicator_style2 STYLE_DOT
#property indicator_width2 1
#property indicator_type3 DRAW_LINE
#property indicator_color3 Wheat
#property indicator_style3 STYLE_DOT
#property indicator_width3 1
#property indicator_label1 «ADX»
#property indicator_label2 "+DI»
#property indicator_label3 "-DI»
Если мы в MetaTrader 5 попытаемся присоединить данный индикатор к графику, во-первых, откроется диалоговое окно индикатора, которое во вкладке Common отобразит значения свойств copyright, link и description:
а во вкладке Colors отобразит значения свойств indicator_label, indicator_color, indicator_width, indicator_style:
Само же название индикатора определяется именем файла индикатора.
К слову сказать, диалоговое окно индикатора можно открыть и после присоединения индикатора к графику, с помощью контекстного меню, щелкнув правой кнопкой мышки на индикаторе и выбрав свойства индикатора.
При наведении курсора на название индикатора в окне Navigator терминала всплывает подсказка, отображающая свойство copyright.
После присоединения индикатора свойство:
#property indicator_label1 «ADX»
работать не будет, так как в функции OnInit () с помощью вызова функции:
string short_name=«ADX (»+string (ExtADXPeriod) +»)»;
IndicatorSetString (INDICATOR_SHORTNAME, short_name);
изменена подпись индикатора:
А вызовом функции:
PlotIndexSetString (0,PLOT_LABEL, short_name);
изменена метка индикатора в окне Data Window:
Значения же свойств:
#property indicator_label2 "+DI»
#property indicator_label3 "-DI»
отображаются, как и было определено, во всплывающих подсказках к диаграммам индикатора и отображаются в окне Data Window.
В коде индикатора ADX объявленное количество буферов индикатора больше, чем количество графических построений:
#property indicator_buffers 6
#property indicator_plots 3
Сделано это для того, чтобы использовать три буфера индикатора для промежуточных расчетов:
SetIndexBuffer (0,ExtADXBuffer);
SetIndexBuffer (1,ExtPDIBuffer);
SetIndexBuffer (2,ExtNDIBuffer);
SetIndexBuffer (3,ExtPDBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer (4,ExtNDBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer (5,ExtTmpBuffer, INDICATOR_CALCULATIONS);
В функции OnCalculate индикатора, значения массивов ExtPDBuffer, ExtNDBuffer, ExtTmpBuffer рассчитываются на основе загруженной ценовой истории, а затем уже на их основе рассчитываются значения массивов ExtADXBuffer, ExtPDIBuffer, ExtNDIBuffer, которые используются для отрисовки диаграмм индикатора.
Как уже было сказано, буфера индикатора для промежуточных вычислений здесь объявляются, так как заранее неизвестен размер загружаемой ценовой истории.
В описании индикатора ADX сказано, что:
Сигнал на покупку формируется тогда, когда +DI поднимается выше – DI и при этом сам ADX растет.
В момент, когда +DI расположен выше – DI, но сам ADX начинает снижаться, индикатор подает сигнал о том, что рынок «перегрет» и пришло время фиксировать прибыль.
Сигнал на продажу формируется тогда, когда +DI опускается ниже – DI и при этом ADX растет.
В момент, когда +DI расположен ниже – DI, но сам ADX начинает снижаться, индикатор подает сигнал о том, что рынок «перегрет» и пришло время фиксировать прибыль.
Давайте, модифицируем код индикатора ADX таким образом, чтобы раскрасить диаграмму ADX в четыре цвета, которые соответствуют описанным выше четырем торговым сигналам.