Скачать MetaTrader 5

Понравилась статья?
Поставьте ссылку на нее -
пусть другие почитают

Используй новые возможности MetaTrader 5

Пользовательские индикаторы в MQL5 для начинающих

3 марта 2010, 10:07
Nikolay Kositsin
4
11 437

Введение

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

Увы, ко всему, что связано с финансовыми и фондовыми рынками, большинство индивидов подходит в уже достаточно зрелом возрасте, и в такой ситуации самостоятельно начать эту, в общем-то, нелёгкую работу с нужного, простейшего уровня понимания оказывается весьма проблематично. В данном цикле статей я постараюсь помочь преодолеть этот первоначальный барьер в понимании языка MQL5 при написании пользовательских индикаторов для клиентского терминала MetaTrader 5.

Индикатор SMA, как пример для первого знакомства

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

Для примера можно взять самый знаменитый индикатор технического анализа - простую, скользящую среднюю - SMA, алгоритм вычисления которой имеет достаточно простой вид:

SMA = SUM (CLOSE (i), MAPeriod) / MAPeriod 

где:

  • SUM — сумма;
  • CLOSE (i) — цена закрытия текущего бара;
  • MAPeriod — число баров для усреднения. 

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

//+------------------------------------------------------------------+
//|                                                          SMA.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
  
input int MAPeriod = 13;
input int MAShift = 0; 
  
double ExtLineBuffer[]; 
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+  
void OnInit()
  {
   SetIndexBuffer(0, ExtLineBuffer, INDICATOR_DATA);
   PlotIndexSetInteger(0, PLOT_SHIFT, MAShift);
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MAPeriod - 1);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
  {
   if (rates_total < MAPeriod - 1)
    return(0);
    
   int first, bar, iii;
   double Sum, SMA;
   
   if (prev_calculated == 0)
    first = MAPeriod - 1 + begin;
   else first = prev_calculated - 1;

   for(bar = first; bar < rates_total; bar++)
    {
     Sum = 0.0;
     for(iii = 0; iii < MAPeriod; iii++)
      Sum += price[bar - iii];
     
     SMA = Sum / MAPeriod;
      
     ExtLineBuffer[bar] = SMA;
    }
     
   return(rates_total);
  }
//+------------------------------------------------------------------+

 А это результат работы этого кода на графике клиентского терминала MetaTrader 5:

Теперь первым делом мне следовало бы внимательно рассмотреть две вещи - это назначение каждой строки программного кода этого индикатора с одной стороны и с другой стороны - взаимодействие этого программного кода при его работе с клиентским терминалом. 

Использование комментариев 

При первом взгляде на код индикатора сразу бросаются в глаза объекты вот такого типа:

//+------------------------------------------------------------------+
//|                                                          SMA.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+  
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+

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

Вполне естественно, что в этих комментариях автор программного кода волен писать всё, что считает необходимым для лучшего понимания этого кода окружающими и самим собой, спустя определённое количество времени. В данном случае - первая шапка закомментированных строк представляет собой отображение названия индикатора и его авторство, вторая и третья шапки поменьше - отделяют описания функций OnInit() и OnCalculate(). Ну и последняя закомментированная строка просто является завершением всего программного кода.

Структура кода индикатора SMA

Таким образом, весь код этого индикатора можно разбить на три основные части:

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

3. Описание функции OnCalculate()

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

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

Помимо этих компонентов в минимальном наборе может присутствовать описание ещё одной функции MQL5 - OnDeinit():

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+  
void OnDeinit(const int reason)
  {

  }

Необходимости в которой в данном индикаторе нет, и потому она отсутствует.

Взаимодействие индикатора SMA с клиентским терминалом MetaTrader 5

Теперь следовало бы немного поподробнее остановиться на работе индикатора, скомпилированного в файл SMA.ex5 после того, как была нажата кнопка "Компилировать" панели инструментов редактора MetaEditor при открытом в его окне файле SMA.mq5. Сами файлы с расширением mq5 - это всего-навсего индикаторный код в текстовом формате, а непосредственно индикаторные файлы с расширением ex5 получаются после компиляции индикаторного кода с помощью этой кнопки или после перезагрузки терминала, если mq5-файлы находились в директории 'MetaTrader 5/MQL5/Indicators/'.

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

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

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

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

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

Программный код индикатора SMA

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

//---- отрисовка индикатора в основном окне
#property indicator_chart_window
//---- для расчёта и отрисовки индикатора использован один буфер
#property indicator_buffers 1
//---- использовано всего одно графическое построение
#property indicator_plots   1
//---- отрисовка индикатора в виде линии
#property indicator_type1   DRAW_LINE
//---- в качестве цвета линии индикатора использован красный цвет
#property indicator_color1  Red 

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

Наша простая скользящая средняя имеет всего два параметра, на которые может влиять пользователь терминала - это период усреднения и сдвиг по горизонтальной оси графика. Эти два параметра должны быть объявлены в качестве внешних переменных индикатора, что и было сделано в двух последующих строках кода:

//---- входные параметры индикатора
input int MAPeriod = 13; // период мувинга
input int MAShift = 0; // сдвиг мувинга по горизонтали

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

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

И последняя строка кода, присутствующая вне всяких скобок - это объявление динамического массива ExtLineBuffer[].

//---- объявление динамического массива, который будет 
//в дальнейшем использован в качестве индикаторного буфера
double ExtLineBuffer[];  

Объявлен он на глобальном уровне по нескольким причинам.

Во-первых, этот массив следует превратить в индикаторный буфер, а это делается в блоке функции OnInit().  Во-вторых, сам индикаторный буфер будет использоваться внутри функции OnCalculate(). И в-третьих, в этом массиве будут храниться и отображаться на ценовом графике в виде кривой индикаторные значения SMA, которые должны сохраняться в нём между тиками клиентского терминала, то есть всё время присутствия индикатора на графике. Таким образом, будучи объявленным на глобальном уровне этот массив оказывается доступным для всех блоков индикатора и хранит свои значения всё время, пока наш индикатор присутствует на графике. 

Содержимое функции OnInit() представлено всего тремя операторами, являющими встроенными функциями терминала MetaTrader. 

Вызов первой функции связывает нулевой индикаторный буфер с одномерным динамическим массивом ExtLineBuffer[]. Два вызова ещё одной функции с разными значениями входных параметров соответственно осуществляют возможность горизонтального сдвига индикатора вдоль ценовой оси и позволяют отрисовывать индикатор с бара за номером MAPeriod.

void OnInit()
  {
//----+
//---- превращение динамического массива ExtLineBuffer в индикаторный буфер
   SetIndexBuffer(0, ExtLineBuffer, INDICATOR_DATA);
//---- осуществление сдвига скользящей средней по горизонтали на MAShift
   PlotIndexSetInteger(0, PLOT_SHIFT, MAShift);
//---- осуществление сдвига начала отсчёта отрисовки индикатора на MAPeriod
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MAPeriod);
//----+
  }

Также самый последний вызов функции PlotIndexSetInteger() передаёт значение MAPeriod через параметр begin функции OnCalculate() другому индикатору, если этот индикатор будет вычисляться на основе значений индикатора SMA. Тут логика довольно простая, на этих первых барах в количестве MAPeriod - 1 усреднять с помощью данного индикатора пока ещё нечего, и потому нет смысла делать отрисовку индикатора на этих барах. А передать это значение в другой индикатор следует для осуществления сдвига на это значение начала отсчёта этого, другого индикатора.

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

И, наконец, последним в этом индикаторе идёт код функции OnCalculate().  Для функции OnCalculate(), как, впрочем, и для OnInit(), в коде индикатора присутствуют только описания функций, а пользовательские вызовы этих функций отсутствуют, по причине того, что вызовы этих функций делает сам клиентский терминал MetaTrader. По этой же причине в заглавии функции OnCalculate() присутствуют только константные объявления входных параметров функции,

int OnCalculate(
                const int rates_total,    // количество истории в барах на текущем тике
                const int prev_calculated,// количество истории в барах на предыдущем тике
                const int begin,          // номер начала достоверного отсчёта баров
                const double &price[]     // ценовой массив для расчёта индикатора
                )

влиять на которые по большому счёту пользователь не может, и значения которых в эту функцию передаёт сам терминал для их использования пользователем посредством программного кода этой функции. Про эти переменные уже более чем достаточно написано в самой справке. Функция OnCalculate() возвращает свои значения терминалу, а возврат этот делается через оператор return(rates_total); Клиентский терминал, приняв это значение на текущем тике по завершению вызова функции OnCalculate(), на следующем тике передаёт это значение этой же функции через константу prev_calculated.  Таким образом, всегда можно определить диапазон  изменения номера бара, в пределах которого можно производить расчёт только тех значений индикатора, которые появились после предыдущего тика.

Следует отметить, что по умолчанию нумерация баров в клиентском терминале MetaTrader производится слева направо, то есть самый старый, самый крайний бар, присутствующий слева на графике будет нулевым, следующим за ним - первым и т. д. Именно в таком порядке расположены элементы в индикаторном буфере ExtLineBuffer[].

Сама простейшая архитектура программного кода внутри функции OnCalculate() данного индикатора достаточно универсальна и типична для огромного количества индикаторов технического анализа. Так что на ней следовало бы остановиться немного поподробнее. Вот логика построения функции OnCalculate():

1. Проверка количества баров на достаточность для расчёта.
2. Объявления локальных переменных.
3. Получение стартового номера для цикла пересчёта баров.
4. Основной цикл расчёта индикатора.
5. Итоговый возврат клиентскому терминалу с помощью оператора return значения переменной rates_total.

Смысл проверки на достаточность для расчёта, я думаю, понятен. Ежели период мувинга MAPeriod, например, равен двум сотням, а терминал имеет в наличии всего одну сотню баров, то и производить расчёты никакой необходимости нет по причине того, что на такой период усреднения просто нет баров в терминале, а стало быть, следовало бы вернуть терминалу нулевой результат расчёта оператором return:

//---- проверка количества баров на достаточность для расчёта
   if(rates_total < MAPeriod - 1 + begin)
      return(0);

Ну а константа begin  учитывает, например, тот факт, что наш мувинг может быть рассчитан по значениям другого индикатора, у которого тоже может быть такая же область, где значения не рассчитываются. На эту тему уже имеется статья Индикатор от индикатора в MQL5, так что добавить тут, в общем-то, нечего.

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

//---- объявления локальных переменных 
   int first, bar, iii;
   double Sum, SMA;

При получении стартового номера для цикла пересчёта баров необходимо учитывать два момента. Во-первых, при старте индикатора необходимо произвести расчёт этого индикатора на всех барах. И, во-вторых, на всех, последующих тиках терминала делать расчёт только на вновь появившихся барах. Что и было сделано с помощью трёх строк программного кода для инициализации переменной first.

   //---- расчёт стартового номера first для цикла пересчёта баров
   if (prev_calculated == 0) // проверка на первый старт расчёта индикатора
    first = MAPeriod - 1 + begin; // стартовый номер для расчёта всех баров
   else first = prev_calculated - 1; // стартовый номер для расчёта новых баров 

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

//---- основной цикл расчёта индикатора
   for(bar = first; bar < rates_total; bar++)

К этому можно добавить, что в цикле организована обработка баров от меньшего значения индекса к большему (bar++), то есть слева-направо, как наиболее естественный, и исторически правильный подход. Хотя, например, в данном индикаторе этот цикл можно было бы произвести без особого ущерба и в обратном порядке. Но всё-таки лучше один раз условиться писать индикаторный код цикла именно в таком виде, как более универсальном. Изменяемую, целочисленную переменную для пересчёта баров в цикле я назвал "bar", хотя многие, начинающие изучать язык MQL5 захотят использовать вариант цикла с переменной "i". Но, по моим наблюдениям, название "bar" делает код более наглядным и удобочитаемым.

Сам код алгоритма усреднения, присутствующий внутри основного цикла довольно прост.

     {
      Sum = 0.0;
      //---- цикл суммирования значений цены для усреднения на текущем баре
      for(iii = 0; iii < MAPeriod; iii++)
         Sum += price[bar - iii]; // Sum = Sum + price[bar - iii]; // эквивалент строки

      //---- получение среднего значения
      SMA = Sum / MAPeriod;

      //---- Инициализация ячейки индикаторного буфера полученным значением SMA
      ExtLineBuffer[bar] = SMA;
     }

С помощью второго оператора цикла мы в переменной Sum накапливаем сумму цен с предыдущих баров за период, а затем делим полученное значение на этот период усреднения, получая в результате итоговое значение SMA.

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

Вот вариант кода того же самого индикатора с подробными комментариями к каждой строки кода:

//+------------------------------------------------------------------+
//|                                                         SMA_.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
//---- отрисовка индикатора в основном окне
#property indicator_chart_window
//---- для расчёта и отрисовки индикатора использован один буфер
#property indicator_buffers 1
//---- использовано всего одно графическое построение
#property indicator_plots   1
//---- отрисовка индикатора в виде линии
#property indicator_type1   DRAW_LINE
//---- в качестве цвета линии индикатора использован красный цвет
#property indicator_color1  Red

//---- входные параметры индикатора
input int MAPeriod = 13; // период мувинга
input int MAShift = 0; // сдвиг мувинга по горизонтали

//---- объявление динамического массива, который будет в 
                // дальнейшем использован в качестве индикаторного буфера
double ExtLineBuffer[]; 
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+  
void OnInit()
  {
//----+
   //---- превращение динамического массива ExtLineBuffer в индикаторный буфер
   SetIndexBuffer(0, ExtLineBuffer, INDICATOR_DATA);
   //---- осуществление сдвига скользящей средней по горизонтали на MAShift
   PlotIndexSetInteger(0, PLOT_SHIFT, MAShift);
   //---- осуществление сдвига начала отсчёта отрисовки индикатора MAPeriod
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MAPeriod - 1);
//----+
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(
                const int rates_total,    // количество истории в барах на текущем тике
                const int prev_calculated,// количество истории в барах на предыдущем тике
                const int begin,          // номер начала достоверного отсчёта баров
                const double &price[]     // ценовой массив для расчёта индикатора
                )

  {
//----+   
   //---- проверка количества баров на достаточность для расчёта
   if (rates_total < MAPeriod - 1 + begin)
    return(0);
   
   //---- объявления локальных переменных 
   int first, bar, iii;
   double Sum, SMA;
   
   //---- расчёт стартового номера first для цикла пересчёта баров
   if (prev_calculated == 0) // проверка на первый старт расчёта индикатора
    first = MAPeriod - 1 + begin; // стартовый номер для расчёта всех баров
   else first = prev_calculated - 1; // стартовый номер для расчёта новых баров

   //---- основной цикл расчёта индикатора
   for(bar = first; bar < rates_total; bar++)
    {
     Sum = 0.0;
     //---- цикл суммирования значений цены для усреднения на текущем баре
     for(iii = 0; iii < MAPeriod; iii++)
      Sum += price[bar - iii]; // Sum = Sum + price[bar - iii]; // эквивалент строки
     
     //---- получение среднего значения
     SMA = Sum / MAPeriod;
     
     //---- Инициализация ячейки индикаторного буфера полученным значением SMA
     ExtLineBuffer[bar] = SMA;
    }
//----+     
   return(rates_total);
  }
//+------------------------------------------------------------------+ 

В таком виде этот код оказывается более понятным и наглядным для восприятия. 

И ещё на одном моменте восприятия программного кода я хотел бы заострить внимание. Дело в том, что в MQL5 за место ничего не платят! Это я к тому, что лишние пробелы и пустые строки в коде ничего, кроме более лёгкого восприятия этого кода не меняют! Так что гораздо лучше и для себя и для окружающих делать необходимые отступы, пробелы и пустые строки в коде. Такая, казалось бы, мелочь, а производительность труда при работе с готовым кодом повышает основательно, особенно ежели этот код многократно использовать в своих дальнейших разработках.

Заключение 

Ну вот и всё, что касается взаимодействия программного кода пользовательского индикатора с клиентским терминалом MetaTrader. Вполне естественно, что тема эта довольно объёмная и едва ли уместимая в пределы одной статьи даже в масштабах общих пояснений этого дела. Так что данная статья отнюдь не заменяет самостоятельного изучения справки по MQL5 и призвана только помочь разобраться в этом, в общем-то, нелёгком деле.

Прикрепленные файлы |
sma__1.mq5 (1.85 KB)
sma___1.mq5 (3.47 KB)
Docker
Docker | 5 мар 2010 в 11:57
Написано и рассказано на пятёрку. Прочитав очень хочется сваять что-то своё. Переписывать код каждый раз мало интересное занятие и авторы MQL5, понимая это, создали большую библиотеку встроенных функций. Вот одна из них: 

int  iMA(
   string symbol,                                     // имя символа
   ENUM_TIMEFRAMES period,                 // период
   int ma_period,                                    // период усреднения
   int ma_shift,                                       // смещение индикатора по горизонтали
   ENUM_MA_METHOD ma_method,         // тип сглаживания
   ENUM_APPLIED_PRICE applied_price     // тип цены или handle
   );
используя которую, можно получить тот же результат. Но. Как получить applied_price при использовании короткой формы int OnCalculate(). Иными словами, как добраться до значений во вкладке "Параметры" при инициализации индикатора?

Спасибо. 


Николай Осипов
Николай Осипов | 15 янв 2013 в 23:59

Спасибо за статью! Очень полезно материал для новичка и
для того кто переходит с другого языка. 

 

serg7771959
serg7771959 | 31 июл 2014 в 21:42

Николай!

Не подскажешь мне почем у при попытке заполнить в цикле индикаторный массив по формуле  Mass[ i ]= Mass[ i+1]+А; где А переменная, компиляция проходит без ошибок а при присоединению к окну  выходит сообщение  array out of range (выход из размера массива)?


Artyom Trishkin
Artyom Trishkin | 31 июл 2014 в 21:50
serg7771959:

Николай!

Не подскажешь мне почем у при попытке заполнить в цикле индикаторный массив по формуле  Mass[ i ]= Mass[ i+1]+А; где А переменная, компиляция проходит без ошибок а при присоединению к окну  выходит сообщение  array out of range (выход из размера массива)?


Потому что цикл нужно делать с учётом того, в какую ячейку последнюю запись будет делаться. Если размер массива Mass[], допустим, равен 10, цикл от нуля до 9 (это индекс последней ячейки массива), то при i==9, вы пытаетесь писать в ячейку с индексом 9+1. А ячейки 10 у массива нет. Соответственно и получаете выход за пределы массива.
Порядок создания и уничтожения объектов в MQL5 Порядок создания и уничтожения объектов в MQL5

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

MQL5.community - Памятка пользователя MQL5.community - Памятка пользователя

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

MQL5 для "чайников": Получение значений технических индикаторов в своих экспертах MQL5 для "чайников": Получение значений технических индикаторов в своих экспертах

Для получения в торговом советнике значений встроенного или пользовательского индикатора, необходимо предварительно создать его хендл с помощью соответствующей функции. На примерах показано, как воспользоваться тем или иным техническим индикатором при разработке своих программ. Речь идёт о индикаторах, которые непосредственно встроены в язык MQL5. Статья предназначена для начинающих разработчиков торговых стратегий и предлагает простые и ясные способы работы с индикаторами с использованием приложенной библиотеки функций.

Способы вызова индикаторов в MQL5 Способы вызова индикаторов в MQL5

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