MetaTrader 5的经济日历与历史报价不同步
简而言之:MetaTrader 5内置的经济日历与历史报价并不完全同步。
每个报价都带有时间戳,这些时间戳是根据每个对应K线形成时服务器所在时区来标记的。
一旦K线形成,它们的时间戳将保持不变。但经济日历则提供与服务器当前时区相关的过去、现在和未来事件的信息。由于许多经纪商遵循特定的时区安排,包括夏令时的开启和关闭,因此历史事件的时间戳相对于相关的K线可能会在一年中的大约一半时间内出现1小时的偏差。
此外,经纪商有时更改时区的方式比简单的夏令时切换还要激进。历史报价可能因此在经济事件发生时的时间上出现数小时的偏移,而这些事件现在却在更新后的时区中被日历所报告。
考虑到新闻来自不同国家,各自的夏令时安排又不同,而你的服务器可能位于其他时区,新闻发布的时间在图表上可能会“跳跃”。这在春季和秋季的几周内尤为明显。
这些在在线交易中似乎不那么重要,但如果我们想测试基于新闻的策略呢?
是的,虽然可以说MetaTrader的测试器不支持经济日历,但许多交易者喜欢交易新闻,而其他人则应该密切关注新闻,以便在市场因新闻而剧烈波动前提前退场。因此,带有经济日历的回测非常重要。这就是为什么将日历导出到外部存储(文件或数据库),然后再导入到测试器中显得非常合理的原因。书中介绍了这样的日历归档工具:算法交易书籍。
在这里,我们遇到了历史报价与历史事件脱节的问题。为简单起见,书中没有解决这个问题。
现在,这个问题通过扩展版的CalendarCache.mqh和展示指示器CalendarMonitorCachedTZ.mq5得到了很好的解决。这是书中CalendarMonitorCached.mq5的一个略微修改的版本。
该指示器监控新闻事件,并动态更新图表上的表格,显示若干过去和即将发生的事件。
所有与时间纠正相关的工作都在幕后完成——在另一个公共库TimeServerDST.mqh中。为了更好地理解时间纠正的工作原理,可以使用脚本CalendarCSVForDates.mq5并并排比较带与不带纠正的CSV文件。
以下是该库是如何嵌入到两个程序的源代码中的——脚本和该指示器。
#include <TimeServerDST.mqh> // 在日历缓存之前包含,以启用时区修正支持 #include <MQL5Book/CalendarFilterCached.mqh> #include <MQL5Book/CalendarCache.mqh>
与原始指示器一样,这里有一个字符串输入CalendarCacheFile,您可以提供用于写入或读取的日历文件名。
当指示器附加到在线图表并且CalendarCacheFile为空时,它会直接使用内置日历。
当指示器使用CalendarCacheFile中的特定名称执行并且文件不存在时,指示器将日历记录导出到缓存文件(创建该文件)并退出。这是时间戳应该/可以进行纠正的阶段(见FixCachedTimesBySymbolHistory)。
当指示器使用CalendarCacheFile中现有缓存文件的名称执行时,它将加载缓存并像使用内置日历一样工作。这对于测试器尤其有用。

请记得,测试器需要指定附加文件,在我们的情况下——准备好的在线日历文件,在指令#property tester_file中,或者您应该将日历文件放入公共文件夹C:/Users/<User>/AppData/Roaming/MetaQuotes/Terminal/Common/。
当然,缓存也可以在回测和优化期间加载到EA中。
输入字符串FixCachedTimesBySymbolHistory的处理方式如下。
如果它为空,指示器将不进行时间纠正保存缓存。
要在导出时启用时间纠正,您需要指定一个符号,该符号将用于经验性检测服务器的历史时区。它基于H1报价的历史,最好是“XAUUSD”或“EURUSD”。
借助这个输入,指示器的新版本仅添加了几行代码:
if(StringLen(FixCachedTimesBySymbolHistory)) cache[].adjustTZonHistory(FixCachedTimesBySymbolHistory, true);
方法adjustTZonHistory是专门为时间戳调整而引入到CalendarCache类中的,其实现使用了TimeServerDST.mqh的内部。
该方法应仅在线调用(而不是在测试器中)。
通常,该方法应在从内置日历填充的缓存对象上调用,紧接着填充后进行调用。否则,如果缓存是从日历文件加载的,或者如果该方法之前已被调用,则缓存内容可能已经调整。然后,您将修正重复应用,导致错误的时间戳。
第二个参数(true)指示该方法将变更边界写入日志。类似如下:
时间修正开始于 2021.07.19 00:30:00 2021.07.19 00:30:00: 148786 -10800 diff=-3600 2021.11.08 01:50:00: 135918 -7200 OK 2022.03.14 04:30:00: 161085 -10800 diff=-3600 2022.11.07 04:00:00: 165962 -7200 OK 2023.03.13 01:50:00: 168500 -10800 diff=-3600 2023.11.06 01:50:00: 169270 -7200 OK 2024.03.11 01:50:00: 181258 -10800 diff=-3600 2024.11.04 02:30:00: 208469 -7200 OK
每一行都包含一个事件的时间和ID,其中发现了新的不一致,事件的服务器时间偏移,以及为消除服务器时间在日历缓存时的偏差而必须应用的所有后续时间戳的差异。
附带的mqh文件(CalendarFilter.mqh,CalendarCache.mqh,QuickSortStructT(Ref).mqh)包含了与书中原始版本相比的bug修复和改进。
更新日志
2024年11月11日 - CalendarFilter.mqh, CalendarCache.mqh的小bug修复和更新;
2024年11月22日 - CalendarCache.mqh的小bug修复和改进。