Получение записей о событиях конкретного вида

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

int CalendarValueHistoryByEvent(ulong id, MqlCalendarValue &values[], datetime from, datetime to = 0)

Функция CalendarValueHistoryByEvent заполняет переданный по ссылке массив записями о событиях конкретного вида, заданного идентификатором id. Параметры from и to позволяют ограничить диапазон дат, в которых ищутся события.

Если необязательный параметр to не указан, в массив будут помещены все записи календаря, начиная с времени from и далее, в будущее. Чтобы запросить все прошлые события, установите from в 0. Если оба параметра from и to равны 0, будет возвращена вся имеющая история и планируемые события. Во всех остальных случаях, когда to не равно 0, оно должно быть больше from.

Массив values может быть динамическим (тогда функция автоматически расширит или уменьшит его под объем данных) или фиксированного размера (тогда в массив будет скопировано только то, что уместилось).

Функция возвращает количество скопированных элементов.

В качестве примера рассмотрим скрипт CalendarStatsByEvent.mq5, который подсчитывает статистику (частоту встречаемости) событий разных видов для заданной страны или валюты, в заданном временном диапазоне.

Условия анализа задаются во входных переменных.

input string CountryOrCurrency = "EU";
input ENUM_CALENDAR_SCOPE Scope = SCOPE_YEAR;

В зависимости от длины строки CountryOrCurrency, она интерпретируется как код страны (2 символа) или валюты (3 символа).

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

struct CalendarEventStats
{
   static const string importances[];
   ulong id;
   string name;
   string importance;
   int count;
};
   
static const string CalendarEventStats::importances[] = {"None""Low""Medium""High"};

В функции OnStart сначала запросим все виды событий с помощью функции CalendarEventByCountry или CalendarEventByCurrency на указанную глубину истории и в будущее, а затем в цикле по полученным описаниям событий в массиве events вызовем CalendarValueHistoryByEvent для каждого идентификатора события. В данном применении нас не интересуют содержащиеся в массиве values записи, достаточно лишь знать их количество.

void OnStart()
{
   MqlCalendarEvent events[];
   MqlCalendarValue values[];
   CalendarEventStats stats[];
   
   const datetime from = TimeCurrent() - Scope;
   const datetime to = TimeCurrent() + Scope;
   
   if(StringLen(CountryOrCurrency) == 2)
   {
      PRTF(CalendarEventByCountry(CountryOrCurrencyevents));
   }
   else
   {
      PRTF(CalendarEventByCurrency(CountryOrCurrencyevents));
   }
   
   for(int i = 0i < ArraySize(events); ++i)
   {
      if(CalendarValueHistoryByEvent(events[i].idvaluesfromto))
      {
         CalendarEventStats event = {events[i].idevents[i].name,
            CalendarEventStats::importances[events[i].importance], ArraySize(values)};
         PUSH(statsevent);
      }
   }
   
   SORT_STRUCT(CalendarEventStatsstatscount);
   ArrayReverse(stats);
   ArrayPrint(stats);
}

При успешном вызове функции заполняем структуру CalendarEventStats и добавляем её в массив структур stats. Далее мы сортируем структуру уже известным нам способом (макрос SORT_STRUCT был описан в разделе Сравнение, сортировка и поиск в массивах).

Запуск скрипта с настройками по умолчанию генерирует примерно такие записи в журнале (приведено с сокращениями).

CalendarEventByCountry(CountryOrCurrency,events)=82 / ok
          [id]                                                [name] [importance] [count]
[ 0] 999520001 "CFTC EUR Non-Commercial Net Positions"               "Low"             79
[ 1] 999010029 "ECB President Lagarde Speech"                        "High"            69
[ 2] 999010035 "ECB Executive Board Member Elderson Speech"          "Medium"          37
[ 3] 999030027 "Core CPI"                                            "Low"             36
[ 4] 999030026 "CPI"                                                 "Low"             36
[ 5] 999030025 "CPI excl. Energy and Unprocessed Food y/y"           "Low"             36
[ 6] 999030024 "CPI excl. Energy and Unprocessed Food m/m"           "Low"             36
[ 7] 999030010 "Core CPI m/m"                                        "Medium"          36
[ 8] 999030013 "CPI y/y"                                             "Low"             36
[ 9] 999030012 "Core CPI y/y"                                        "Low"             36
[10] 999040006 "Consumer Confidence Index"                           "Low"             36
[11] 999030011 "CPI m/m"                                             "Medium"          36
...
[65] 999010008 "ECB Economic Bulletin"                               "Medium"           8
[66] 999030023 "Wage Costs y/y"                                      "Medium"           6
[67] 999030009 "Labour Cost Index"                                   "Low"              6
[68] 999010025 "ECB Bank Lending Survey"                             "Low"              6
[69] 999010030 "ECB Supervisory Board Member af Jochnick Speech"     "Medium"           4
[70] 999010022 "ECB Supervisory Board Member Hakkarainen Speech"     "Medium"           3
[71] 999010028 "ECB Financial Stability Review"                      "Medium"           3
[72] 999010009 "ECB Targeted LTRO"                                   "Medium"           2
[73] 999010036 "ECB Supervisory Board Member Tuominen Speech"        "Medium"           1
 

Обратите внимание, что всего было получено 82 вида событий, однако в массиве статистики у нас оказалось только 74. Дело в том, что функция CalendarValueHistoryByEvent возвращает false (неуспех) и нулевой код ошибки в _LastError, если событий какого-либо вида не оказалось в заданном диапазоне дат. В приведенном тесте таких теоретически существующих, но ни разу за год не встретившихся событий набралось 8.