按国家/地区或货币获取事件记录

在日历中,针对给定的日期范围查询各种类型的特定事件,并按国家/地区或货币进行筛选。

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

CalendarValueHistory 函数用 fromto 之间时间范围内的日历条目填充通过引用传递的 values 数组。这两个参数都可以包含日期和时间。值 from 包含在区间内,但值 to 未包含在区间内。换句话说,该函数选择 time 特性满足以下复合条件的日历条目(MqlCalendarValue 结构体):from <= time < to

必须指定起始时间 from,而结束时间 to 是可选的:如果省略或等于 0,则所有未来的事件都将复制到数组中。

时间 to 应该大于 from,除非前者等于 0。查询所有可用事件(过去和未来)的特殊组合是 fromto 都为 0。

如果接收数组是动态的,将自动为其分配内存。如果数组是固定大小的,则复制的条目数量不会超过数组的大小。

countrycurrency 参数允许你按国家/地区或货币设置额外的记录筛选。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 字段的事件 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 方法中,我们通过其标识符获取事件的描述。然后,基于事件描述中的国家/地区标识符,我们得到一个包含国家/地区特性的结构体。之后,我们可以从接收到的 MqlCalendarEventMqlCalendarCountry 结构体中填充添加字段的前半部分。

   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);
   }
}

这里,通过为输入参数中设置的当前条件调用 CalendarValueHistory 来填充标准 MqlCalendarValue 结构体数组。接下来,所有元素都转移到 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