Вывод массивов в журнал

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

Однако удобнее переложить всю рутину по перебору элементов и их аккуратному форматированию на среду MQL5, потому что среди функций API имеется специальная для такого случая — ArrayPrint.

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

void ArrayPrint(const void &array[], uint digits = _Digits, const string separator = NULL,
  ulong start = 0, ulong count = WHOLE_ARRAY,
  ulong flags = ARRAYPRINT_HEADER | ARRAYPRINT_INDEX | ARRAYPRINT_LIMIT | ARRAYPRINT_DATE | ARRAYPRINT_SECONDS)

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

Массив должен иметь размерность 1 или 2. При этом форматирование автоматически подстраивается под конфигурацию массива и по возможности отображает его в наглядном виде (см. пример далее). Несмотря на то, что MQL5 поддерживает массивы размерностью вплоть до 4-х включительно, функция не отображает массивы с 3-мя и более размерностями, потому что их сложно представить в "плоском" виде. Происходит это без выдачи ошибок на стадии компиляции или выполнения программы.

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

Параметр digits применяется для массивов вещественных чисел и для числовых полей структур: он задает количество выводимых знаков в дробной части чисел. Значением по умолчанию является одна из предопределенных переменных графиков, а именно _Digits — это количество знаков после запятой в ценах финансового инструмента текущего графика.

Разделительный символ separator используется для обозначения колонок при выводе полей в массиве структур. При значении по умолчанию (NULL) функция применяет пробел в качестве разделителя.

Параметры start и count позволяют задать, соответственно, номер начального элемента и количество элементов для печати. По умолчанию функция выводит весь массив, но на результат может дополнительно оказать действие наличие флага ARRAYPRINT_LIMIT (см. ниже).

Параметр flags принимает сочетание флагов, которые управляют различными нюансами отображения. Вот некоторые из них:

  • ARRAYPRINT_HEADER — вывод заголовка с названиями полей структуры перед массивом структур; не влияет на массивы не-структур;
  • ARRAYPRINT_INDEX — вывод индексов элементов по измерениям (для одномерных массивов индексы выводятся слева, для двумерных — слева и сверху);
  • ARRAYPRINT_LIMIT — для больших массивов вывод ограничен сотней первых и сотней последних записей (это ограничение включено по умолчанию);
  • ARRAYPRINT_DATE — для значений типа datetime отображается дата;
  • ARRAYPRINT_MINUTES — для значений типа datetime отображается время с точностью до минут;
  • ARRAYPRINT_SECONDS — для значений типа datetime отображается время с точностью до секунд.

Значения типа datetime выводятся по умолчанию в формате ARRAYPRINT_DATE | ARRAYPRINT_SECONDS.

Значения типа color выводятся в шестнадцатеричном формате.

Значения перечислений отображаются как целые числа.

Функция не выводит вложенные массивы, структуры и указатели на объекты. Вместо них отображается троеточие.

Для демонстрации возможностей функции создан скрипт ArrayPrint.mq5.

В функции OnStart определено несколько массивов (одно-, двух- и трехмерный), которые выводятся с помощью ArrayPrint (с настройками по умолчанию).

void OnStart()
{
   int array1D[] = {12345678910};
   double array2D[][5] = {{12345}, {678910}};
   double array3D[][3][5] =
   {
      {{ 1,  2,  3,  4,  5}, { 6,  7,  8,  910}, {1112131415}},
      {{1617181920}, {2122232425}, {2627282930}},
   };
   
   Print("array1D");
   ArrayPrint(array1D);
   Print("array2D");
   ArrayPrint(array2D);
   Print("array3D");
   ArrayPrint(array3D);
   ...
}

Мы получим в журнале следующие строки:

array1D
 1  2  3  4  5  6  7  8  9 10
array2D
         [,0]     [,1]     [,2]     [,3]     [,4]
[0,]  1.00000  2.00000  3.00000  4.00000  5.00000
[1,]  6.00000  7.00000  8.00000  9.00000 10.00000
array3D

Массив array1D недостаточно большой (умещается на одном ряду), поэтому для него не показаны индексы.

Массив array2D имеет несколько строк (индексов), и потому их индексы отображаются (ARRAYPRINT_INDEX включен по умолчанию).

Обратите внимание, что поскольку скрипт запускался на графике EURUSD с пятизнаковыми ценами, _Digits = 5, и это сказывается на форматировании величин типа double.

Массив array3D проигнорирован: для него не выведено ни одной строки.

Дополнительно в скрипте определены структуры Pair и SimpleStruct:

struct Pair
{
   int xy;
};
   
struct SimpleStruct
{
   double value;
   datetime time;
   int count;
   ENUM_APPLIED_PRICE price;
   color clr;
   string details;
   void *ptr;
   Pair pair;
};

SimpleStruct содержит поля встроенных типов, указатель на void, а также поле типа Pair.

В функции OnStart создается массив типа SimpleStruct и выводится с помощью ArrayPrint в двух режимах: с настройками по умолчанию и с пользовательскими (количество цифр после "запятой" — 3, разделитель — ";", формат для datetime — только дата).

void OnStart()
{
   ...
   SimpleStruct simple[] =
   {
      { 12.57839D'2021.07.23 11:15', 22345PRICE_MEDIANclrBlue"text message"},
      {135.82949D'2021.06.20 23:45', 8569PRICE_TYPICALclrAzure},
      { 1087.576D'2021.05.15 10:01:30', -3298PRICE_WEIGHTEDclrYellow"note"},
   };
   Print("SimpleStruct (default)");
   ArrayPrint(simple);
   
   Print("SimpleStruct (custom)");
   ArrayPrint(simple3";"0WHOLE_ARRAYARRAYPRINT_DATE);
}

Это производит следующий результат:

SimpleStruct (default)
       [value]              [time] [count] [type]    [clr]      [details] [ptr] [pair]
[0]   12.57839 2021.07.23 11:15:00   22345      5 00FF0000 "text message"   ...    ...
[1]  135.82949 2021.06.20 23:45:00    8569      6 00FFFFF0 null             ...    ...
[2] 1087.57600 2021.05.15 10:01:30   -3298      7 0000FFFF "note"           ...    ...
SimpleStruct (custom)
  12.578;2021.07.23;  22345;     5;00FF0000;"text message";  ...;   ...
 135.829;2021.06.20;   8569;     6;00FFFFF0;null          ;  ...;   ...
1087.576;2021.05.15;  -3298;     7;0000FFFF;"note"        ;  ...;   ...

Уточним, что журнал, который мы используем в данном случае и в предыдущих разделах, формируется в терминале и доступен пользователю на вкладке Эксперты окна Инструменты. Однако в дальнейшем мы познакомимся с тестером, который предоставляет для MQL-программ некоторых типов (индикаторов и экспертов) такую же среду исполнения, как и сам терминал. В случае их запуска в тестере функция ArrayPrint и другие родственные функции, о которых рассказано в разделе Взаимодействие с пользователем, будут выводить сообщения в журнал агентов тестирования.
 
До сих пор мы работали и некоторое время продолжим работать только со скриптами, а они могут выполняться только в терминале.