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

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

Всем привет!

В этом уроке мы рассмотрим, что такое массивы, зачем они вообще нужны, какие бывают и как правильно их использовать. Научимся работать со свечами, определять значения цены Open, High, Low, Close свечей на графике, попробуем определить цену последней свечи. Поехали.

Массивы

Массив это сгруппированный набор данных одного типа под общим названием. Проще говоря, это переменная определенного типа, будь то int, double, string и т.д, которая может содержать в себе от одного до 2147483647 значений. Они называются элементами массива. Объявляться массив может на локальном, либо глобальном уровне.

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

Массивы могут быть как одномерные, так и многомерные: двумерные, трехмерные или четырехмерные. Лично мне трехмерный и четырехмерный массив ни разу в работе не понадобились, поэтому их рассматривать сейчас не будем.

Посмотрим на изображение из справочника на сайте MQL:

Значением элемента Array[4] у одномерного массива является число 34 (рис. a), для двумерного массива значением элемента Array[3,7] число равно 28 (рис. b). А для трёхмерного массива значением элемента Array[5,4,1] является целое число 77.

Если у вам возник вопрос «Зачем мне эти массивы?», то тут все просто — в них вы будете хранить большое количество информации, которое просто неудобно держать в отдельно созданных переменных. Например, вам нужно для анализа хранить номера Тикетов всех закрытых ордеров на покупку. Это можно сделать через отдельные переменные типа int, но тогда у вас будет целый список с именами MyTicket1, MyTicket2, MyTicket3 и т.д. Это неудобно, особенно, когда у вас больше сотни ордеров, плюс количество ордеров в истории будет постоянно увеличиваться. Другой пример: Вам нужно сохранить данные индикатора Moving Average за последние 20 свечей для дальнейшего расчета, либо построения графических фигур. Согласитесь, опрометчиво создать 20 разных переменных, когда можно сделать всего один массив с уникальным именем, который содержит в себе эти 20 значений.

Продолжим. Созданный ранее массив MyArray не содержит данных, изменим это, сразу задав ему значения:

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

Повторюсь, размер массива задается целым числом, в нашем случае это [3], т.е. в нем содержится три элемента. Но! При работе со значениями этого массива отсчет начинается с нуля, значит три элемента будут иметь порядковые номера 0, 1 и 2. Это важно запомнить, чтобы не путаться в будущем.

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

Теперь, давайте рассмотрим двумерный массив. Он содержит в себе два индекса в квадратных скобках:

Объявлен двумерный массив типа string, первый индекс которого равен двум, второй — трем, значит в сумме у этого массива 6 значений. Зададим ему текст:

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

Двумерные массивы удобны для хранения информации об ордерах — первый индекс будет как внутренняя нумерация ордера, а второй уже хранить в себе цену открытия, закрытия, цели, прибыль и т.д. Также я использовал их при импорте новостных данных для нашего индикатора Truly News Indicator из интернета. Там все данные о новостях (наименование, время, важность, прогноз) хранятся в типе данных sting. Далее записанную информацию в массив я разбивал на отдельные графические объекты, которые и отображали всю информацию на графике.

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

Стоит заметить, что не обязательно при инициализации задавать значения всем константам, можно пропустить нужное количество. Пропуск идет у последних элементов:

Динамические массивы

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

Они имеют такой же вид, как и статические, с единственной разницей — у них нет индекса внутри квадратных скобок. Объявим массив типа int:

Прежде, чем его начать использовать, мы должны задать ему размер с помощью функции ArrayResize:

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

Если в дальнейшем вам будет нужно изменить размер массива — нужно еще раз вызывать эту функцию. Естественно, если размер будет уменьшен, то все данные прошлого массива с бОльшим количеством элементов будут удалены. Т.е. если размер массива был 5, стал 3, то в памяти останется только первые три значения, два же сотрутся. Динамический массив может быть только для первого измерения, значит второй и последующие индексы должны быть определены программистом.

Чтобы не создавать отдельную статью, рассмотрим сразу другие основные функции для работы с массивами обоих типов:

  • ArrayInitialize — функция инициализирует числовой массив заданным значением. Передача данных идет сразу для всех элементов.
Ее удобно использовать, если нужно обнулить значения всего массива, либо придать им пустое значение EMPTY_VALUE.

  • ArrayFill — выполняет по сути тоже, что и предыдущая функция — задает значения элементам массива с разницей в том, что можно указать с какого элемента начинать и сколько значений заполнить. Первый параметр это имя массива, второй — индекс с которого нужно начать заполнение (0 — обозначает самый первый). Третий параметр это количество элементов, которые нужно заполнить, четвертый — значение, которым нужно заполнить массив. На примере ниже мы заполним 0 и 1 элементы массива значением «1111», а 2 и 3 — «2222»:
  • ArraySize — функция считает количество элементов заданного массива. В основном нужна для динамических массивов, когда их размер периодически меняется и нужно знать актуальное его значение.
Нужно учесть, что расчет идет на все элементы массива, независимо от количества его измерений. Т.е. если есть двумерный массив d_array[2][3], то результат будет равен 6.

  • ArrayRange — возвращает количество элементов в заданном измерении массива. Нужен для работы с многомерными массивами:
  • ArraySort — сортировка массива по первому измерению. С помощью этой функции можно поменять порядок всех или части элементов задом наперед. Функция имеет четыре параметра: наименование массива, сколько элементов нужно сортировать (WHOLE_ARRAY — обозначает весь массив), с какого индекса начать сортировку (0 значит первый), направление сортировки: MODE_ASCEND — в порядке возрастания, MODE_DESCEND — в порядке убывания.
  • ArrayIsDynamic — функция проверяет, является ли данный массив динамическим:
  • ArrayMaximum, ArrayMinimum — поиск в числовом массиве максимального или минимального номера элемента. Данные функции имеют три настройки: наименование массива, количество элементов для анализа, номер начального индекса, с которого начинать подсчет. Возвращает номер элемента, а не само значение. Чтобы его узнать, полученный номер нужно указать в фигурных скобках массива.
Также массивы можно копировать один в другой, сравнивать друг с другом, задавать им значения котировок и т.д., если в будущем это понадобится — я расскажу об этих функциях подробнее.

С массивами, как и с обычными переменными можно совершать арифметические функции, а также присоединять текст одного элемента массива к другому.

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

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

  • Open — цена открытия бара.
  • Close — цена закрытия бара
  • High — максимальная цена бара
  • Low — минимальная цена бара
  • Time — время открытия бара
  • Volume — объем бара.

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

Нумерация идет справа налево и начинается с нулевого бара, т.е. текущего, который еще открыт (не сформировался). Соответственно первый бар это предыдущая (первая закрытая) свеча, второй — свеча слева от первой и т.д. При наведении мышью на любую свечу вы получите все ее характеристики. Также их можно посмотреть в ‘Окне Данных‘, открыв его в меню «Вид», либо нажав «Ctrl+D’

После закрытия свечи новый открытый бар принимает значение 0. Все остальные номера баров смещаются на одну единицу (тот, что был 1, становится равным 2 и т.д.). После закрытия свечи ее данные цены и времени больше не изменяются.

Узнаем значение цены первой закрывшейся свечи:

У нулевой свечи еще нет цены закрытия, поэтому при определении Close[0] результат будет равен текущей цене Бид до того момента, пока бар не закроется.

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

Далее узнаем самую низкую цену закрытия 1,2 и 3 свечи:

Теперь определим самый высокий High и самый низкий Low последних 20 свечей:

Значение Массивов-таймсерии также можно вычитать и прибавлять, допустим, чтобы узнать размер свечи от цены открытия до закрытия:

С помощью цикла в дальнейшем мы изучим как находить разнообразные свечные паттерны и делать более сложные расчеты.

Стоит заметить, что данный тип отображения предопределённых названий работает только на текущей инструменте и таймфрейме графика. Если вам нужно знать цену на другом символе, либо ином периоде, то нужно воспользоваться следующими функциями: iOpen, iClose, iHigh, iLow, iTime. Они имеют три параметра: первый это символ, который нужно использовать (если указать NULL, то будет учитываться текущий), второй timeframe — период графика (при 0 — текущий). Третий это сдвиг, т.е. то значение, которое указывается в квадратных скобках.

 

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

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

В приложенных mql4 файлах скрипта специально закомментированы Print’ы, чтобы при установке на график на вас не вылилась гора информации. При проверке кода нужно просто по очереди снять знак комментария // с нужного раздела.

Скачать пример

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Заполните поле
Заполните поле
Пожалуйста, введите корректный адрес email.
Вы должны согласиться с условиями для продолжения

Меню