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

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

int CalendarValueHistory(MqlCalendarValue &values[], datetime from, datetime to = 0,
  const string country = NULL, const string currency = NULL)

Функция CalendarValueHistory заполняет передаваемый по ссылке массив values записями календаря во временном диапазоне от from до to. Оба параметра могут включать дату и время. Значение from входит в интервал, а значение to — нет. Иными словами, функция отбирает записи календаря (структуры MqlCalendarValue), в которых для свойства time выполняется составное условие: from <= time < to.

Начальное время from должно быть указано обязательно. Конечное время to является опциональным: если оно опущено или равно 0, в массив копируются все будущие события.

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

Если приемный массив динамический, для него будет автоматически выделена память. В случае массива с фиксированным размером, будет скопировано количество записей не больше размера массива.

Параметры country и currency позволяют задать дополнительную фильтрацию записей по стране или валюте. Параметр country принимает двухбуквенный код страны по стандарту ISO 3166-1 alpha-2 (например, "DE", "FR", "EU"), параметр currency — трехбуквенное обозначение валюты (например, "EUR", "CNY").

Значение по умолчанию NULL или пустая строка "" в любом из параметров равносильны отсутствию соответствующего фильтра.

Если указаны оба фильтра, выбираются значения только тех событий, для которых удовлетворяются одновременно оба условия — страна и валюта. Это может пригодиться, если в календаре окажутся страны с несколькими валютами, каждая из которых имеет хождение также в нескольких станах. В данный момент в календаре таких событий нет. Для получения событий стран зоны Евро достаточно указать код конкретной страны или EU, и валюта EUR будет подразумеваться.

Функция возвращает количество скопированных элементов и может установить код ошибки. В частности, если превышено время ожидания запроса с сервера, получим в _LastError ошибку 5401 (ERR_CALENDAR_TIMEOUT). Если же фиксированный массив не уместил всех записей, код будет равен 5400 (ERR_CALENDAR_MORE_DATA), однако массив будет заполнен. При выделении памяти под динамический массив потенциально возможна ошибка 4004 (ERR_NOT_ENOUGH_MEMORY).

Внимание! Порядок элементов в массиве может отличаться от хронологического. Сортируйте записи по времени самостоятельно.

С помощью функции CalendarValueHistory мы могли бы запросить грядущие события примерно так:

   MqlCalendarValue values[];
   if(CalendarValueHistory(valuesTimeCurrent()))
   {
      ArrayPrint(values);
   }

Однако с таким кодом мы получим недостаточно информативную таблицу, в которой суть событий — их названия, важность, коды валют — будут скрыты за идентификатором события в поле MqlCalendarValue::event_id и, опосредовано, за идентификатором страны в поле MqlCalendarEvent::country_id. Чтобы сделать вывод информации более дружественным следует по коду события запросить его описание, а из этого описания взять код страны и получить её атрибуты. Покажем это в примере скрипта CalendarForDates.mq5.

Во входных параметрах предусмотрим ввод кода страны и валюты для фильтрации. По умолчанию запрашиваются события по Евросоюзу.

input string CountryCode = "EU";
input string Currency = "";

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

#define DAY_LONG   60 * 60 * 24
#define WEEK_LONG  DAY_LONG * 7
#define MONTH_LONG DAY_LONG * 30
#define YEAR_LONG  MONTH_LONG * 12
   
enum ENUM_CALENDAR_SCOPE
{
   SCOPE_DAY = DAY_LONG,
   SCOPE_WEEK = WEEK_LONG,
   SCOPE_MONTH = MONTH_LONG,
   SCOPE_YEAR = YEAR_LONG,
};
   
input ENUM_CALENDAR_SCOPE Scope = SCOPE_DAY;

Определим свою структуру MqlCalendarRecord, производную от MqlCalendarValue, и добавим в неё поля для удобного представления атрибутов, которые будут заполняться по ссылкам (идентификаторам) из зависимых структур.

struct MqlCalendarRecordpublic MqlCalendarValue
{
   static const string importances[];
   
   string importance;
   string name;
   string currency;
   string code;
   double actualpreviousrevisedforecast;
   ...
};
   
static const string MqlCalendarRecord::importances[] = {"None""Low""Medium""High"};

Среди добавленных полей — строки с важностью (одно из значений статического массива importances), названием события, страны и валюты, а также четверка значений в формате double. Это фактически означает дублирование информации в угоду наглядному представлению при выводе на печать. Позднее мы подготовим более совершенную "обертку" для календаря.

Для заполнения объекта потребуется параметрический конструктор, принимающий исходную структуру MqlCalendarValue. После того как все унаследованные поля неявным образом скопированы в новый объект оператором '=', мы вызываем специально подготовленный метод extend.

   MqlCalendarRecord() { }
   
   MqlCalendarRecord(const MqlCalendarValue &value)
   {
      this = value;
      extend();
   }

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

   void extend()
   {
      MqlCalendarEvent event;
      CalendarEventById(event_idevent);
      
      MqlCalendarCountry country;
      CalendarCountryById(event.country_idcountry);
      
      importance = importances[event.importance];
      name = event.name;
      currency = country.currency;
      code = country.code;
      
      MqlCalendarValue value = this;
      
      actual = value.GetActualValue();
      previous = value.GetPreviousValue();
      revised = value.GetRevisedValue();
      forecast = value.GetForecastValue();
   }

Далее мы вызвали встроенные Get-методы для заполнения четверки полей типа double с финансовыми показателями.

Теперь мы можем использовать новую структуру в основном обработчике OnStart.

void OnStart()
{
   MqlCalendarValue values[];
   MqlCalendarRecord records[];
   datetime from = TimeCurrent() - Scope;
   datetime to = TimeCurrent() + Scope;
   if(PRTF(CalendarValueHistory(valuesfromtoCountryCodeCurrency)))
   {
      for(int i = 0i < ArraySize(values); ++i)
      {
         PUSH(recordsMqlCalendarRecord(values[i]));
      }
      Print("Near past and future calendar records (extended): ");
      ArrayPrint(records);
   }
}

Здесь делается заполнение массива стандартных структур MqlCalendarValue с помощью вызова CalendarValueHistory для текущих условий, выставленных во входных параметрах. Далее все элементы переносятся в массив MqlCalendarRecord, причем в процессе создания объектов они расширяются дополнительной информацией. Наконец, массив событий выводится в журнал.

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

CalendarValueHistory(values,from,to,CountryCode,Currency)=6 / ok

Near past and future calendar records (extended): 

      [id] [event_id]              [time]            [period] [revision] [actual_value]         [prev_value] [revised_prev_value]     [forecast_value] [impact_type]

[0] 162723  999020003 2022.06.23 03:00:00 1970.01.01 00:00:00    0 -9223372036854775808 -9223372036854775808 -9223372036854775808 -9223372036854775808             0

[1] 162724  999020003 2022.06.24 03:00:00 1970.01.01 00:00:00    0 -9223372036854775808 -9223372036854775808 -9223372036854775808 -9223372036854775808             0

[2] 168518  999010034 2022.06.24 11:00:00 1970.01.01 00:00:00    0 -9223372036854775808 -9223372036854775808 -9223372036854775808 -9223372036854775808             0

[3] 168515  999010031 2022.06.24 13:10:00 1970.01.01 00:00:00    0 -9223372036854775808 -9223372036854775808 -9223372036854775808 -9223372036854775808             0

[4] 168509  999010014 2022.06.24 14:30:00 1970.01.01 00:00:00    0 -9223372036854775808 -9223372036854775808 -9223372036854775808 -9223372036854775808             0

[5] 161014  999520001 2022.06.24 22:30:00 2022.06.21 00:00:00    0 -9223372036854775808             -6000000 -9223372036854775808 -9223372036854775808             0

 

А вот вторая половина с "расшифровкой" названий, важности и значений.

CalendarValueHistory(values,from,to,CountryCode,Currency)=6 / ok

Near past and future calendar records (extended):

     [importance]                                                [name] [currency] [code] [actual] [previous] [revised] [forecast]

[0]  "High"       "EU Leaders Summit"                                   "EUR"      "EU"        nan        nan       nan        nan

[1]  "High"       "EU Leaders Summit"                                   "EUR"      "EU"        nan        nan       nan        nan

[2]  "Medium"     "ECB Supervisory Board Member McCaul Speech"          "EUR"      "EU"        nan        nan       nan        nan

[3]  "Medium"     "ECB Supervisory Board Member Fernandez-Bollo Speech" "EUR"      "EU"        nan        nan       nan        nan

[4]  "Medium"     "ECB Vice President de Guindos Speech"                "EUR"      "EU"        nan        nan       nan        nan

[5]  "Low"        "CFTC EUR Non-Commercial Net Positions"               "EUR"      "EU"        nan   -6.00000       nan        nan