Продвинутое использование торговой платформы MetaTrader 5. Создание индикаторов и торговых роботов на MQL5 и Python. Издание 3-е, исправленное и дополненное. Тимур Машнин
Чтение книги онлайн.
Читать онлайн книгу Продвинутое использование торговой платформы MetaTrader 5. Создание индикаторов и торговых роботов на MQL5 и Python. Издание 3-е, исправленное и дополненное - Тимур Машнин страница 5
array out of range
Это произошло потому, что мы перед заполнением данного массива значениями не указали его размера и не зарезервировали под него память.
Так что его размер был равен нулю, когда мы попытались в него что-то записать.
Статическим мы этот массив сделать тоже не можем, т.е. объявить его сразу с указанием размера, так как значения такого промежуточного массива рассчитываются в функции обратного вызова OnCalculate на основе загруженной в функцию OnCalculate истории цен, а именно массивов open[], high[], low[], и close[].
Но точный размер массивов open[], high[], low[], и close[] неизвестен, он обозначается лишь переменной rates_total.
Хорошо, но мы можем в функции OnCalculate применить функцию ArrayResize, чтобы установить размер массива:
ArrayResize(ExtTmpBuffer,rates_total);
Передав в функцию в качестве аргумента переменную rates_total – количество баров на графике, на котором запущен индикатор.
Теперь после компиляции индикатор заработает как надо.
Но дело в том, что в функции OnCalculate мы сначала рассчитываем индикатор для всей ценовой истории, т.е. для rates_total значений, а затем при поступлении нового тика по символу индикатора, и соответственно вызове функции OnCalculate, мы рассчитываем значение индикатора для этого нового тика по символу и записываем новое значение индикатора в его массив буфера.
Чтобы это реализовать с промежуточным массивом, нужно внимательно следить за его размером и записывать новое значение в конец массива.
Вместо всего этого, проще всего привязать промежуточный массив к буферу индикатора с помощью функции SetIndexBuffer и таким образом решить все эти проблемы.
Аналогичная ситуация возникает, когда значения таких промежуточных массивов заполняются с помощью функции CopyBuffer, когда мы строим пользовательский индикатор на основе других индикаторов.
Функция CopyBuffer распределяет размер принимающего массива под размер копируемых данных.
Если копируется вся ценовая история, то проблем нет и в этом случае использовать INDICATOR_CALCULATIONS необязательно.
Если же мы хотим скопировать только одно новое поступившее значение, функция CopyBuffer определит размер принимающего массива как 1, и нужно будет использовать этот принимающий массив как еще один массив-посредник, из которого уже записывать значение в промежуточный массив индикатора. И в этом случае просто функцией ArrayResize для принимающего массива проблему не решить.
Теперь что нам делать, если мы хотим раскрашивать наши диаграммы индикатора в разные цвета в зависимости от цены?
Во-первых, мы должны указать, что наша графическая форма нашего графического построения является цветной, например:
#property indicator_type1 DRAW_COLOR_LINE
В идентификатор геометрической формы добавляется слово COLOR.
Далее значение свойства #property indicator_buffers увеличивается на единицу и объявляется еще один массив для хранения цвета.
Функцией SetIndexBuffer объявленный дополнительный массив сопоставляется с буфером цвета индикатора, например:
SetIndexBuffer(1,ExtColorsBuffer,INDICATOR_COLOR_INDEX);