日历的基本概念

在处理经济日历时,我们将运用若干概念,MQL5 为这些概念的规范描述定义了特殊类型的结构体。

首先,日历事件与特定国家/地区相关联,使用 MqlCalendarCountry 结构体来描述每个国家/地区。

struct MqlCalendarCountry

   ulong  id;              //country identifier according to ISO 3166-1 
   string name;            // text name of the country (in the current terminal encoding) 
   string code;            // two-letter country designation according to ISO 3166-1 alpha-2 
   string currency;        // international country currency code 
   string currency_symbol// symbol/sign of the country's currency 
   string url_name;        // country name used in the URL on the mql5.com website 
};

我们将在下一节中了解如何以 MqlCalendarCountry 结构体数组的形式获取日历中可用的国家/地区列表及其特性。

目前,我们只需关注其 id 字段。该字段之所以重要,是因为它是确定日历事件是否属于特定国家/地区的关键。在每个国家/地区(或注册的国家/地区联盟,如欧盟),都存在一个国际公认的、会影响市场并因此被纳入日历的经济指标类型和信息事件类型列表。

每种事件类型均由 MqlCalendarEvent 结构体定义,其中 country_id 字段将事件唯一地关联到对应国家/地区。我们稍后会探讨所使用的枚举类型。

struct MqlCalendarEvent

   ulong                          id;         // event ID 
   ENUM_CALENDAR_EVENT_TYPE       type;       // event type 
   ENUM_CALENDAR_EVENT_SECTOR     sector;     // sector to which the event belongs 
   ENUM_CALENDAR_EVENT_FREQUENCY  frequency;  // frequency (periodicity) of the event 
   ENUM_CALENDAR_EVENT_TIMEMODE   time_mode;  // event time mode 
   ulong                          country_id// country identifier 
   ENUM_CALENDAR_EVENT_UNIT       unit;       // indicator unit 
   ENUM_CALENDAR_EVENT_IMPORTANCE importance// importance of the event 
   ENUM_CALENDAR_EVENT_MULTIPLIER multiplier// indicator multiplier 
   uint                           digits;     // number of decimal places
   string                         source_url// URL of the event publication source 
   string                         event_code// event code
   string                         name;       // text name of the event in the terminal language 
};

重要的是要理解,MqlCalendarEvent 结构体描述的正是事件的类型(例如,消费者价格指数 CPI 的发布),而不是可能每季度、每月或按其他时间表发生的某个具体事件。它包含了事件的通用特性,包括重要性、频率、与经济板块的关系、计量单位、名称以及信息来源。至于实际指标和预测指标,这些将在针对此类特定事件的日历条目中提供:这些条目以 MqlCalendarValue 结构体的形式存储,我们稍后会讨论。用于查询支持的事件类型的函数将在后续章节介绍。

type 字段中的事件类型被指定为 ENUM_CALENDAR_EVENT_TYPE 枚举值之一。

标识符

说明

CALENDAR_TYPE_EVENT

事件(会议、演讲等)

CALENDAR_TYPE_INDICATOR

经济指标

CALENDAR_TYPE_HOLIDAY

假日(周末)

事件所属的经济板块则从 ENUM_CALENDAR_EVENT_SECTOR 枚举中选择。

标识符

说明

CALENDAR_SECTOR_NONE

未设置部门

CALENDAR_SECTOR_MARKET

市场、交易所

CALENDAR_SECTOR_GDP

国内生产总值 (GDP)

CALENDAR_SECTOR_JOBS

劳动力市场

CALENDAR_SECTOR_PRICES

价格

CALENDAR_SECTOR_MONEY

资金

CALENDAR_SECTOR_TRADE

交易

CALENDAR_SECTOR_GOVERNMENT

政府

CALENDAR_SECTOR_BUSINESS

企业

CALENDAR_SECTOR_CONSUMER

消费

CALENDAR_SECTOR_HOUSING

住房

CALENDAR_SECTOR_TAXES

税收

CALENDAR_SECTOR_HOLIDAYS

假日

事件的频率通过 ENUM_CALENDAR_EVENT_FREQUENCY 枚举在 frequency 字段中显示。

标识符

说明

CALENDAR_FREQUENCY_NONE

未设置发布频率

CALENDAR_FREQUENCY_WEEK

每周

CALENDAR_FREQUENCY_MONTH

每月

CALENDAR_FREQUENCY_QUARTER

每季度

CALENDAR_FREQUENCY_YEAR

每年

CALENDAR_FREQUENCY_DAY

每日

事件持续时间 (time_mode) 可以用 ENUM_CALENDAR_EVENT_TIMEMODE 枚举中的一个元素来描述。

标识符

说明

CALENDAR_TIMEMODE_DATETIME

事件的具体时间是已知的

CALENDAR_TIMEMODE_DATE

事件持续一整天

CALENDAR_TIMEMODE_NOTIME

时间未发布

CALENDAR_TIMEMODE_TENTATIVE

只有日期是事先知道的,但事件的确切时间不知道(时间是事后指定的)。

事件的重要性通过 ENUM_CALENDAR_EVENT_IMPORTANCE 枚举在 importance 字段中指定。

标识符

说明

CALENDAR_IMPORTANCE_NONE

未设置

CALENDAR_IMPORTANCE_LOW

CALENDAR_IMPORTANCE_MODERATE

CALENDAR_IMPORTANCE_HIGH

作为 ENUM_CALENDAR_EVENT_UNIT 枚举的一个成员,事件值所使用的度量单位在 unit 字段中定义。

标识符

说明

CALENDAR_UNIT_NONE

未设置单位

CALENDAR_UNIT_PERCENT

利息 (%)

CALENDAR_UNIT_CURRENCY

本国货币

CALENDAR_UNIT_HOUR

小时数

CALENDAR_UNIT_JOB

工作场所数量

CALENDAR_UNIT_RIG

钻机

CALENDAR_UNIT_USD

美元

CALENDAR_UNIT_PEOPLE

人数

CALENDAR_UNIT_MORTGAGE

按揭贷款数量

CALENDAR_UNIT_VOTE

投票数

CALENDAR_UNIT_BARREL

桶数

CALENDAR_UNIT_CUBICFEET

体积(立方英尺)

CALENDAR_UNIT_POSITION

合约投机仓位净额

CALENDAR_UNIT_BUILDING

建筑物数量

在某些情况下,经济指标的数值需要根据 ENUM_CALENDAR_EVENT_MULTIPLIER 枚举中的某一元素使用 multiplier

标识符

说明

CALENDAR_MULTIPLIER_NONE

未设置乘数

CALENDAR_MULTIPLIER_THOUSANDS

千倍

CALENDAR_MULTIPLIER_MILLIONS

百万倍

CALENDAR_MULTIPLIER_BILLIONS

十亿倍

CALENDAR_MULTIPLIER_TRILLIONS

万亿倍

至此,我们已了解所有用于描述 MqlCalendarEvent 结构体中事件类型的特殊数据类型。

每个独立的日历条目则由 MqlCalendarValue 结构体表示。其详细描述如下,但首先请注意一个关键点:MqlCalendarValue 包含一个 event_id 字段,该字段指向事件类型的标识符,即 MqlCalendarEvent 结构体中某个 id 的值。

如前所述,MqlCalendarEvent 结构体又通过 country_id 字段与 MqlCalendarCountry 关联。因此,一旦特定国家/地区或事件类型的信息录入日历数据库,便可为其注册任意数量的同类事件。当然,数据库的填充工作由信息提供方负责,而非开发者。

简而言之,系统分别维护着三个内部数据表:

  • MqlCalendarCountry 结构体表:描述国家/地区信息
  • MqlCalendarEvent 结构体表:描述事件类型
  • MqlCalendarValue 结构体表:存储各类具体事件的指标

通过引用事件类型标识符,可以有效避免在具体事件记录中重复信息。例如,月度发布的 CPI 值都只引用同一个包含该事件类型通用特性的 MqlCalendarEvent 结构体。如果不是采用这种分表方式,那么就必须在每个 CPI 日历条目中重复相同的特性。这种使用标识符字段在数据表之间建立关系的方法被称为 relational,我们将在关于 SQLite的章节中再次讨论。所有这些都在下图中有所说明。

结构体间通过标识符字段链接的方案

结构体间通过标识符字段链接的示意图

所有这些表都存储在内部日历数据库中,该数据库在终端连接到服务器期间会持续保持最新状态。

日历条目(即具体事件)是 MqlCalendarValue 结构体。它们也通过其 id 字段中的唯一编号进行标识(这三个核心表各自都有自己的 id 字段)。

struct MqlCalendarValue 

   ulong      id;                 // entry ID 
   ulong      event_id;           // event type ID 
   datetime   time;               // time and date of the event 
   datetime   period;             // reporting period of the event 
   int        revision;           // revision of the published indicator in relation to the reporting period 
   long       actual_value;       // actual value in ppm or LONG_MIN 
   long       prev_value;         // previous value in ppm or LONG_MIN 
   long       revised_prev_value// revised previous value in ppm or LONG_MIN 
   long       forecast_value;     // forecast value in ppm or LONG_MIN 
   ENUM_CALENDAR_EVENT_IMPACT impact_type;  // potential impact on the exchange rate
    
 // functions for checking values
   bool HasActualValue(voidconst;     // true if the actual_value field is filled 
   bool HasPreviousValue(voidconst;   // true if the prev_value field is filled 
   bool HasRevisedValue(voidconst;    // true if the revised_prev_value field is filled 
   bool HasForecastValue(voidconst;   // true if the forecast_value field is filled
    
   // functions for getting values 
   double GetActualValue(voidconst;   // actual_value or nan if value is not set 
   double GetPreviousValue(voidconst// prev_value or nan if value is not set 
   double GetRevisedValue(voidconst;  // revised_prev_value or nan if value is not set 
   double GetForecastValue(voidconst// forecast_value or nan if value is not set 
};

对于每个事件,除了其发布时间 (time) 外,还存储了以下四个值:

  • 实际值 (actual_value),在新闻发布后即刻知晓
  • 前次值 (prev_value),在上次同类新闻发布时知晓
  • 前次指标的修正值 (revised_prev_value)(如果自上次发布后有所修改)
  • 预测值 (forecast_value)

显而易见,并非所有字段都必须填写。因此,对于未来的事件,当前值是缺失的(尚未知晓),而过去值的修正也并非一定发生。此外,这四个字段仅对量化指标有意义,而日历中还反映了监管机构的演讲、会议和假日。

空字段(无值)由常量 LONG_MIN (-9223372036854775808) 表示。如果字段中的值已指定(不等于 LONG_MIN),则它对应于指标真实值乘以一百万后的结果,也就是说,要获得常规(真实)形式的指标,需要将字段值除以 1,000,000。

为了方便程序员,该结构体定义了 4 个 Has 方法用于检查字段是否已填充,以及 4 个 Get 方法用于返回已转换为实数的相应字段值,如果字段未填充,则方法将返回 NaN (Not A Number,非数字)。

有时,为了获取绝对值(如果算法需要),额外分析 MqlCalendarEvent 结构体中的 multiplier 特性非常重要,因为某些值是根据 ENUM_CALENDAR_EVENT_MULTIPLIER 枚举以倍数单位指定的。此外,MqlCalendarEvent 拥有 digits 字段,它指定了接收值的有效小数位数,用于后续的正确格式化(例如,在调用 NormalizeDouble 时)。

报告期(即已发布指标的计算周期)在 period 字段中设置为该周期的第一天。例如,如果指标是按月计算的,那么日期 '2022.05.01 00:00:00' 表示五月份。报告期的时长(例如,月、季度、年)则在关联的 MqlCalendarEvent 结构体的 frequency 字段中定义:该字段的类型是前面与其他枚举一起描述过的特殊枚举 ENUM_CALENDAR_EVENT_FREQUENCY。

特别值得关注的是 impact_type 字段,在新闻发布后,该字段会通过比较当前值和预测值,自动设置相应货币对汇率的影响方向。这种影响可能是积极的(货币预期升值),也可能是消极的(货币预期贬值)。例如,销售额降幅大于预期将被标记为具有消极影响,而失业率降幅大于预期则为积极影响。但并非所有事件的这种特性都能被明确解读(某些经济指标被认为是矛盾的),此外,还应注意变化的相对数值。

事件对本国货币汇率的潜在影响使用 ENUM_CALENDAR_EVENT_IMPACT 枚举表示。

标识符

说明

CALENDAR_IMPACT_NA

未说明影响

CALENDAR_IMPACT_POSITIVE

积极影响

CALENDAR_IMPACT_NEGATIVE

消极影响

经济日历的另一个重要概念是其“变更”这一事实。遗憾的是,并没有一个专门的结构体来描述变更。变更唯一的特性是其独特的 ID,这是一个整数,在内部日历库每次发生更改时由系统分配。

我们知道,信息提供者会不断修改日历:新的即将发生的事件会被添加进来,而已发布的指标和预测也可能被修正。因此,跟踪任何编辑的发生至关重要,通过检测周期性递增的变更编号可以实现这一点。

具有特定标识符的编辑时间及其具体内容在 MQL5 中是不可获取的。如果需要,MQL 程序应自行实现定期的日历状态查询和记录分析。

一系列 MQL5 函数允许获取关于国家/地区、事件类型、具体日历条目及其变更的信息。我们将在后续章节中对此进行探讨。

注意!首次访问日历时(如果之前未在终端工具栏中打开过“日历”选项卡),内部日历数据库与服务器之间的同步可能需要几秒钟的时间。