Русский

Учебник по MQL4  Переменные  Массивы

Массивы


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

Понятие массив


Массив - это сгруппированный по месту распределения набор значений однотипных переменных, имеющих общее название. Различают одномерный и многомерный массивы. Максимально допустимое количество измерений в массиве - четыре. Допускаются массивы любых типов данных.

Элемент массива - это составная часть массива; индексированная переменная с одноимённым названием, имеющая некоторое значение.



Рис. 59. Графическое представление массивов целого типа: а) одномерный; b) двумерный; с) трёхмерный.

Индексирование


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

Допускается также способ указания индексов, при котором каждый из индексов обрамляется квадратными скобками:

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

Объявление массива и доступ к элементам массива


Перед тем, как массив будет использоваться в программе, его необходимо объявить. Массив может быть объявлен так же, как и переменная, - на глобальном и локальном уровне. Соответственно, значения элементов глобального массива доступны всей программе, а локального массива - только той функции, в которой этот массив объявлен. Массив не может быть объявлен на уровне клиентского терминала, поэтому глобальные переменные клиентского терминала не могут быть объединены в массив. Тип значений элементов массива может быть любым. Значения всех элементов массива имеют одинаковый тип, а именно тот, который указан при объявлении массива. При объявлении массива указывается тип данных, название массива и количество элементов в каждом измерении массива:

Доступ к значениям элементов массива осуществляется поэлементно, т.е. одновременно можно получить доступ только к одному из элементов. Тип значения элемента массива в программе не указывается. Получение или изменение значения элемента массива может осуществляться с помощью операторов присваивания:

Значения элементов массивов, показанных на Рис. 59, следующие:

- для одномерного массива значением элемента Mas[4] является целое число 34;

- для двумерного массива значением элемента Mas[3,7] является целое число 28;

- для трёхмерного массива значением элемента Mas[5,4,1] является целое число 77.

Обратите внимание, минимальное значение индекса элемента массива - 0 (ноль), а максимальное значение - на единицу меньше, чем количество элементов в соответствующем измерении, указанное при объявлении массива.

Например, для массива Mas[10][15] элементом с минимальными значениями индексов является элемент Mas[0,0], а с максимальными значениями индексов - элемент Mas[9,14] .

Осуществлять операции с массивами можно также с помощью стандартных функций. Для получения подробной информации о работе этих функций обратитесь к справочной документации на сайте производителя (https://docs.mql4.com/ru) или к разделу "Справка" в редакторе MetaEditor. Некоторые из этих функций рассматриваются в дальнейшем изложении.

Инициализация массива


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

int Mas_i[3][4] = { 0, 1, 2, 3,   10, 11, 12, 13,   20, 21, 22, 23 };

double Mas_d[2][3] = { 0.1, 0.2, -0.3, -10.2, 1.5, 7.0 };

bool Mas_b[5] = { false, true, false, true, true }

В инициализирующей последовательности допускается пропуск одной или нескольких констант. В этом случае соответствующие элементы массивов числовых типов инициализируются нолём, а элементы массивов типа string инициализируются строковым значением "" (открывающая и закрывающая двойная кавычка без промежутка), т.е. пустой строкой (не путать с пробелом). Следующая программа выводит на экран значений массивов, инициализированных последовательностью с пропусками некоторых значений (скрипт arrayalert.mq4):

//--------------------------------------------------------------------
// arrayalert.mq4
// Предназначен для использования в качестве примера в учебнике MQL4.
//--------------------------------------------------------------------
int start() // Спец. функция start
{
string Mas_s[4] = {"a","b", ,"d"}; // Строковый массив
int Mas_i[6] = { 0,1,2, ,4,5 }; // Массив целого типа
Alert(Mas_s[0],Mas_s[1],Mas_s[2],Mas_s[3]); // Вывод на экран
Alert(Mas_i[0],Mas_i[1],Mas_i[2],Mas_i[3],Mas_i[4],Mas_i[5]);
return; // Выход из start()
}
//--------------------------------------------------------------------

Если размер одномерного инициализируемого массива не указан, то он определяется компилятором, исходя из размера инициализирующей последовательности. Инициализация массива может быть выполнена также с помощью стандартной функции ArrayInitialize(). Все массивы являются статическими, т.е. имеют вид static, даже если при инициализации это явно не указано. Это значит, что все элементы массива сохраняют свои значения в промежутке между вызовами на исполнение функции, в которой объявлен массив (см. Виды переменных).


Все используемые в MQL4 массивы можно разделить на две группы: пользовательские массивы (создаваемые по инициативе программиста) и массивы - таймсерии (массивы с предопределёнными именами и типами данных). Определение размеров пользовательских массивов и значений их элементов зависит от того, как составлена программа и, в конечном счёте, от воли программиста. Значения элементов пользовательских массивов сохраняется в программе в течение всего времени исполнения программы и может быть изменено в результате вычислений. В то же время изменение значений элементов в массивах-таймсериях не допускается, а их размеры могут увеличиваться при подкачке истории.

Пользовательские массивы


В разделе Оператор switch рассматривалась Задача 18. Несколько усложним условие (увеличим количество выводимых словами пунктов до 100) и решим эту задачу, используя массивы.

Задача 25. Составить программу, в которой реализуются следующие условия: если курс поднялся выше заданного уровня, то выдать сообщение, в котором словами обозначено превышение над уровнем (до 100 пунктов); в остальных случаях сообщить, что курс не превышает заданный уровень.

Решение Задачи 25 с использованием строкового массива может быть таким (эксперт stringarray.mq4):

//--------------------------------------------------------------------
// stringarray.mq4
// Предназначен для использования в качестве примера в учебнике MQL4.
//--------------------------------------------------------------------
extern double Level=1.3200;                     // Заданный уровень
string Text[101];                               // Объявление массива
//--------------------------------------------------------------------
int init()                                      // Спец. ф-ия init()
  {                                             // Присвоение значений
   Text[1]="один ";            Text[15]="пятнадцать ";
  
Text[2]="два ";             Text[16]="шестнадцать ";
  
Text[3]="три ";             Text[17]="семнадцать ";
  
Text[4]="четыре ";          Text[18]="восемнадцать ";
  
Text[5]="пять ";            Text[19]="девятнадцать ";
  
Text[6]="шесть ";           Text[20]="двадцать ";
  
Text[7]="семь ";            Text[30]="тридцать ";
  
Text[8]="восемь ";          Text[40]="сорок ";
  
Text[9]="девять ";          Text[50]="пятьдесят ";
  
Text[10]="десять ";         Text[60]="шестьдесят";
  
Text[11]="одиннадцать ";    Text[70]="семьдесят ";
  
Text[12]="двенадцать ";     Text[80]="восемьдесят ";
  
Text[13]="тринадцать ";     Text[90]="девяносто";
  
Text[14]="четырнадцать ";   Text[100]= "сто";
  
// Вычисление значений
   for(int i=20; i<=90; i=i+10)                // Цикл по десяткам
     {
      for(int j=1; j<=9; j++)                  // Цикл по единицам
         Text[i+j]=Text[i] + Text[j];          // Вычисление значения  
     }
   return;                                     // Выход из init()
  }
//--------------------------------------------------------------------
int start()                                     // Спец. ф-ия start()
  {
   int Delta=NormalizeDouble((Bid-Level)/Point,0);// Превышение
//--------------------------------------------------------------------
   if (Delta>=0)                                // Цена не выше уровня
     {
      Alert("Цена ниже уровня");                // Сообщение
      return;                                   // Выход из start()
     }
//--------------------------------------------------------------------
   if (Delta<100)                               // Цена более 100
     {
      Alert("Более ста пунктов");               // Сообщение
      return;                                   // Выход из start()
     }
//--------------------------------------------------------------------
   Alert("Плюс ",Text[Delta],"pt.");            // Вывод на экран
   return;                                      // Выход из start()
  }
//--------------------------------------------------------------------

Для решения Задачи 25 используется строковый массив Text[]. Во время исполнения программы значения элементов этого массива не изменяются. Массив объявлен на глобальном уровне (за пределами специальных функций), а первоначальное заполнение массива осуществляется в специальной функции init(). Таким образом, в специальной функции start() выполняются только те вычисления, которые необходимо исполнить на каждом тике.

Некоторой части элементов массива Text[] присваиваются значения строковых констант. Другой части элементов массива присваиваются значения, вычисленные во вложенных циклах путём суммирования строк.

   for (int i = 20; i<=90; i=i+10)              // Цикл по десяткам
{
for (int j=1; j<=9; j++) // Цикл по единицам
Text[i+j] = Text[i] + Text[j]; // Вычисление значения
}

Смысл этих вычислений понять легко: для каждого элемента массива с индексом, начиная с 21 и заканчивая 99 (исключая значения индексов, кратных 10), вычисляются соответствующие строковые значения. Обратите внимание на значения индексов, указанные в строке:

         Text[i+j] = Text[i] + Text[j];         // Вычисление значения

В качестве значений индексов используются переменные (значения которых в цикле изменяются) и выражение. В зависимости значений переменных i и j программа будет обращаться к соответствующим элементам массива Text[], суммировать их значения и присваивать результат элементу массива с индексом, значение которого также вычисляется ( i+j ) Например, если на некотором этапе вычислений значение переменной i равно 30, а переменной j равно 7, то название элементов, значения которых суммируются, соответственно, Text[30] и Text[7], а элемента, которому присваивается результат, - Text[37]. В качестве значения индекса элемента массива может использоваться и любая другая переменная целого типа. В данном примере в функции start() используется название элемента того же массива с индексом Delta, а именно - Text[Delta].

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


Рис. 60. Вывод на экран искомых значений экспертом stringarray.mq4.

Обратите внимание на решение Задачи 18. Если бы и Задача 25 была решена тем же способом, то тело оператора switch содержало бы около 100 строк, - по одной строке для каждого варианта решения. Такой подход к составлению программ нельзя считать удовлетворительным. Тем более подобные способы решения оказываются непригодными, если приходится обрабатывать десятки, а иногда и сотни тысяч значений переменных. В таких случаях использование массивов оправдано и очень удобно.

Массивы-таймсерии


Массив-таймсерия - это массив с предопределённым названием (Open, Close, High, Low, Volume или Time), элементы которого содержат значения соответствующих характеристик исторических баров.

Данные, содержащиеся в массивах-таймсериях, несут очень важную информацию и широко используются в практике программирования на MQL4. Каждый массив-таймсерия является одномерным массивом и содержит исторические сведения о какой-то одной характеристике бара. Каждый бар характеризуется ценой открытия Open[], ценой закрытия Close[], максимальной ценой High[], минимальной ценой Low[], объёмом Volume[] и временем открытия Time[]. Например, массив-таймсерия Open[] несёт информацию о цене открытия всех баров, имеющихся в окне финансового инструмента: значением элемента массива Open[1] является цена открытия первого бара, Open[2] - цена открытия второго бара и т.д. То же справедливо и для всех других таймсерий.

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

Отсчёт баров (и поставленных им в соответствие индексов массивов-таймсерий) начинается с нулевого бара. Значениями элементов всех массивов-таймсерий, имеющих индекс [0], являются значения, характеризующие нулевой бар. Например, значением элемента Open[0] является цена открытия нулевого бара. На Рис. 61 показан порядок нумерации баров и характеристики бара (отражаемые в окне финансового инструмента при наведении на изображение бара курсора мыши).



Рис. 61. Каждый бар характеризуется набором значений, содержащихся в массивах-таймсериях.
Отсчёт баров начинается с нулевого бара.

Нулевой бар на Рис. 61 имеет следующие характеристики:

Индекс Open[] Close[] High[], Low[], Time[]
[0] 1.2755 1.2752 1.2755 1.2752 2006.11.01 14:34

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


Рис. 62. Бары смещаются с течением времени, но нумерация баров не смещается.

Теперь значения элементов массивов-таймсерий станут следующими:

Индекс Open[] Close[] High[], Low[], Time[]
[0] 1.2751 1.2748 1.2752 1.2748 2006.11.01 14:35
[1] 1.2755 1.2752 1.2755 1.2752 2006.11.01 14:34

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

Таким образом, важнейшая особенность, касающаяся массивов-таймсерий, состоит в следующем:

Значения элементов массивов-таймсерий являются собственными характеристиками бара и никогда не изменяются (за исключением следующих характеристик нулевого бара: Close[0], High[0], Low[0], Volume [0]), а индекс бара отражает его углубление в историю на текущий момент и меняется с течением времени.

Отдельно нужно заметить, что время открытия бара исчисляется кратно календарным минутам, секунды при этом не учитываются. Иными словами, если в период между 14:34 и 14:35 первый тик пришёл в 14 час. 34 мин. 07 сек, то в минутном таймфрейме образуется новый бар со временем открытия 14:34. Соответственно, время открытия бара в 15-минутном таймфрейме кратно 15 минутам, при этом первый бар в течение часового интервала открывается в n час.00 мин, второй в n:15, третий в n:30 и четвёртый - в n:45.

Чтобы правильно понять роль индексов в массивах-таймсериях, решим следующую простую задачу:

Задача 26.Найти минимальное и максимальное значения цены среди последних n баров.

Обратите внимание, решение подобных задач невозможно без обращения к значениям массивов-таймсерий. Эксперт, определяющий минимальную и максимальную цену среди заданного количества последних баров, может иметь следующее решение (extremumprice.mq4):

//--------------------------------------------------------------------
// extremumprice.mq4
// Предназначен для использования в качестве примера в учебнике MQL4.
//--------------------------------------------------------------------
extern int Quant_Bars=30; // Количество баров
//--------------------------------------------------------------------
int start() // Спец. функция start
{
int i; // Номер бара
double Minimum=Bid, // Минимальная цена
Maximum=Bid; // Максимальная цена

for(i=0;i<=Quant_Bars-1;i++) // От нуля (!) до..
{ // ..Quant_Bars-1 (!)
if (Low[i]< Minimum) // Если < известного
Minimum=Low[i]; // то оно и будет мин
if (High[i]> Maximum) // Если > известного
Maximum=High[i]; // то оно и будет макс
}
Alert("За последние ",Quant_Bars, // Вывод на экран
" баров Min= ",Minimum," Max= ",Maximum);
return; // Выход из start()
}
//--------------------------------------------------------------------

В программе extremumprice.mq4 используется простой алгоритм. Количество баров, предназначенных для анализа, задано во внешней переменной Quant_Bars. В начале программы искомым значениям Minimum и Maximum присваиваются значения текущей цены. Поиск минимального и максимального значений выполняется в операторе цикла:

   for(i=0;i<=Quant_Bars-1;i++)                 // От нуля (!) до..
{ // ..Quant_Bars-1 (!)
if (Low[i]< Minimum) // Если < известного
Minimum = Low[i]; // то оно и будет мин
if (High[i]> Maximum) // Если > известного
Maximum = High[i]; // то оно и будет макс
}

Здесь показательным является интервал значений индексов (целая переменная i) обрабатываемых элементов массивов-таймсерий Low[i] и High[i]. Обратите внимание на Выражение_1 и Условие в заголовке оператора цикла:

   for(i=0;i<=Quant_Bars-1;i++)                 // От нуля (!) до..

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

Последним индексом элементов таймсерий, обрабатываемых в цикле, является индекс, на 1 меньший, чем количество обрабатываемых баров. В нашем примере указано количество баров, равное 30. Это значит, что максимальное значение индекса должно быть равно 29. Таким образом, в цикле будут обработаны значения элементов таймсерий с индексами от 0 до 29, т.е. всего для 30 баров.

Легко понять и смысл вычислений в теле оператора цикла:

      if (Low[i]< Minimum)                      // Если < известного
Minimum = Low[i]; // то оно и будет мин
if (High[i]> Maximum) // Если > известного
Maximum = High[i]; // то оно и будет макс

Если текущее значение Low[i] (т.е. в период текущей итерации с текущим значением индекса) оказывается меньше известного минимального значения, то оно и становится минимальным значением. Аналогично вычисляется и максимальное значение. К моменту окончания цикла переменные Minimum и Maximum получат искомые значения. В последующих строках эти значения выводятся на экран.

Запустив эту программу на выполнение можно получить результат, аналогичный следующему:


Рис. 63. Результаты работы эксперта extremumprice.mq4.

Обратите внимание, эксперт может работать бесконечно долго, показывая правильный результат, причём в программе всё время используются одни и те же значения индексов (в данном случае от 0 до 29). При этом значения элементов массивов-таймсерий с ненулевыми индексами будут изменяться в момент появления нового бара, а значения элементов массивов-таймсерий, характеризующих нулевой бар, могут поменяться на любом следующем тике (за исключением значений Open[0] и Time[0], которые на нулевом баре не изменяются).

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

Задача 27.В начале каждого бара 1 раз вывести на экран минимальное и максимальное значения цены среди последних сформировавшихся n баров.

Чтобы решить задачу, прежде всего необходимо определить факт начала нового бара, т.е. выявить первый тик на нулевом баре. Для этой цели существует очень простой и надёжный способ - анализировать время открытия нулевого бара. Время открытия нулевого бара - это такая характеристика бара, которая не изменяется в течение времени его формирования. Новые тики, поступающие в процессе развития нулевого бара, могут изменить его максимальную цену High[0], минимальную цену Low[0], цену закрытия Close[0] и объём Volume0]. Но такие характеристики нулевого бара, как цена открытия Open[0] и время открытия Time[0], не изменяются.

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

//--------------------------------------------------------------------
// newbar.mq4
// Предназначен для использования в качестве примера в учебнике MQL4.
//--------------------------------------------------------------------
extern int Quant_Bars=15; // Количество баров
bool New_Bar=false; // Флаг нового бара
//--------------------------------------------------------------------
int start() // Спец. функция start
{
double Minimum, // Минимальная цена
Maximum; // Максимальная цена
//--------------------------------------------------------------------
Fun_New_Bar(); // Обращение к ф-ии
if (New_Bar==false) // Если бар не новый..
return; // ..то уходим
//--------------------------------------------------------------------
int Ind_max =ArrayMaximum(High,Quant_Bars,1);// Индекс бара макс.ц.
int Ind_min =ArrayMinimum(Low, Quant_Bars,1);// Индекс бара мин. ц.
Maximum=High[Ind_max]; // Искомая макс цена
Minimum=Low[Ind_min]; // Искомая мин. цена
Alert("За последние ",Quant_Bars, // Вывод на экран
" баров Min= ",Minimum," Max= ",Maximum);
return; // Выход из start()
}
//--------------------------------------------------------------------
void Fun_New_Bar() // Ф-ия обнаружения ..
{ // .. нового бара
static datetime New_Time=0; // Время текущего бара
New_Bar=false; // Нового бара нет
if(New_Time!=Time[0]) // Сравниваем время
{
New_Time=Time[0]; // Теперь время такое
New_Bar=true; // Поймался новый бар
}
}
//--------------------------------------------------------------------

В программе используется глобальная переменная New_Bar. Полагается, что если её значение равно true, то это означает, что последний известный тик - это первый тик нового бара. Если же значение New_Bar равно false, то последний известный тик появился в период развития текущего нулевого бара.

Флаг - это переменная, значение которой ставится в соответствие каким-либо событиям или фактам.

Использование флагов в программе очень удобно. Значение флага может быть определено в одном месте, а использоваться в разных местах. Иногда в программе используется алгоритм, в котором принимается решение в зависимости от сочетания значений различных флагов. В эксперте newbar.mq4 в качестве флага используется переменная New_Bar, значение которой находится в прямой зависимости от факта образования нового бара.

Вычисления, касающиеся выявления факта образования нового бара, сосредоточены в пользовательской функции Fun_New_Bar(). В первых строках этой функции определена статическая переменная New_Time (напомним, что статические переменные не теряют своё значение после окончания исполнения функции). При каждом обращении к функции значение глобальной переменной New_Bar устанавливается равным false. Собственно обнаружение нового бара осуществляется в операторе if:

   if(New_Time != Time[0])                      // Сравниваем время
{
New_Time = Time[0]; // Теперь время такое
New_Bar = true; // Поймался новый бар
}

Если значение переменной New_Time (вычисленное в предыдущей истории), не равно времени открытия нулевого бара Time[0], то это означает факт образования нового бара. В этом случае управление передаётся в тело оператора if, где запоминается новое значение времени открытия нового нулевого бара и переменной New_Bar присваивается значение true (условно можно сказать, что флаг устанавливается в положение вверх).

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

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

   if (New_Bar == false)                        // Если бар не новый..
return; // ..то уходим

Если последний тик, запустивший на исполнение специальную функцию start(), не образовал новый бар, то управление передаётся оператору, завершающему исполнение функции start(). И только в том случае, если новый бар образовался, управление передаётся в последующие строки для вычисления искомых значений (что и требуется по условию задачи).

Вычисление максимального и минимального значений осуществляется с помощью стандартных функций ArrayMaximum() и ArrayMinimum(). Каждая из этих функций возвращает индекс элемента массива (соответственно максимального и минимального значения) для заданного интервала индексов. По условию задачи необходимо исследовать только полностью сформировавшиеся бары, поэтому в качестве граничных значений индексов выбраны значения 1 и Quant_Bars - заданное количество баров (нулевой бар не сформировался, т.е. в решении данной задачи не учитывается). Для получения подробной информации о работе этих и других функций доступа к таймсериям обратитесь к справочной документации на сайте производителя (https://docs.mql4.com/ru) или к разделу "Справка" в редакторе MetaEditor.

На Рис. 64 можно проследить, как менялись минимальное и максимальное значения цены на заданном интервале в период исполнения программы:


Рис. 64. Результаты работы эксперта newbar.mq4.