本地时间和服务器时间
在 MetaTrader 5 平台上始终有两种类型的时间:本地(客户)时间和服务器(经纪人)时间。
本地时间对应于运行终端的计算机时间,该时间以与真实世界相同的速率持续增加。
服务器时间的流动方式则不同。服务器时间的依据按经纪人的计算机上的时间设定,然而,客户端仅与下次价格变动一同接收到关于服务器时间的信息,这种价格变动被包装进特殊结构,称为分时报价(参见关于 MqlTick的章节),并使用 事件将其传递给 MQL 程序。
因此,仅当市场上的至少一个金融工具(即“市场报价”窗口中选择的金融工具之一)的价格变动之后,终端才能知道更新的服务器时间。最后已知的服务器时间显示在该窗口的标题栏中。如果没有分时报价,则终端中的服务器时间保持静止。这在周末和节假日尤其明显,这时候所有交易所和外汇平台均关闭。
尤其是在星期日,服务器时间将很可能显示为星期五晚上。唯一的例外是 MetaTrader 5 实例,其提供持续交易金融工具(诸如加密数字货币)。然而,即使在这种情况下,在低波动期间,服务器时间也可能明显滞后于本机时间。
本节中所有函数以精确到秒( datetime 类型的时间表示精度)的精度处理时间。
为获取本地和服务器时间,MQL5 API 提供了三个函数:TimeLocal、TimeCurrent 以及 TimeTradeServer。三个函数均有两个原型版本:第一个版本以 datetime 类型的值返回时间,第二个版本还通过引用接受和填充带时间分量的 MqlDateTime 结构体。
datetime TimeLocal()
datetime TimeLocal(MqlDateTime &dt)
该函数以 datetime 格式返回本地计算机时间。
务必要注意的是,时间包括夏令时(如果启用)。即 TimeLocal 等于计算机的时区的标准时间,减去修正 TimeDaylightSavings。该公式可条件性地表示如下:
TimeLocal summer() = TimeLocal winter() - TimeDaylightSavings() |
其中 TimeDaylightSavings 通常等于 -3600,也就是将时钟前移 1 小时(损失 1 小时)。因此,相对于 UTC,TimeLocal 的夏季时间值大于冬季时间值(在天文时间相等的情况下)。例如,如果在冬季 TimeLocal 等于 UTC+2,则在夏季等于 UTC+3。UTC 可使用 TimeGMT 函数获得。
datetime TimeCurrent()
datetime TimeCurrent(MqlDateTime &dt)
该函数以 datetime 格式返回最后已知服务器时间。这是“市场报价”中所有金融工具列表的上次报价抵达时间。唯一例外是 EA 交易中的 OnTick 事件处理程序,其中该函数将返回已处理的分时报价的时间(即使时间更接近的分时报价已出现在“市场报价”中)。
另外,应注意,MetaTrader 5 中所有图表水平轴上的时间对应于服务器时间(历史习惯)。最后(当前,最右边)条柱包含 TimeCurrent。详情参见 图表 一节。
datetime TimeTradeServer()
datetime TimeTradeServer(MqlDateTime &dt)
该函数返回交易服务器的估计当前时间。不同于 TimeCurrent(如果没有新的报价,其结果可能不会改变),TimeTradeServer 允许你获取持续增加的服务器时间的估计值。计算是基于客户端时区与服务器时区之间的最后已知差值,该差值与当前本地时间相加。
在测试程序中,TimeTradeServer 值始终等于 TimeCurrent。
该函数用法示例在 TimeCheck.mq5 脚本中提供。
主函数具有持续不间断记录的所有类型时间的无限循环,直至用户停止该脚本。
void OnStart()
|
除了标准函数外,这里还应用了自定义函数 TimeTradeServerExact。
datetime TimeTradeServerExact()
|
该函数是必需的,因为内置 TimeTradeServer 函数的算法不一定适合所有情况。内置函数找到本地时间和服务器时间之间以小时表示的差值(即时区差值),然后获取服务器时间,以根据该差值对本地时间进行修正。因此,如果客户端和服务器上的分钟数和秒数不同步(这是极有可能的),则服务器时间的标准近似值将显示客户端的分钟数和秒数,而不是服务器的分钟数和秒数。
理想情况下,所有计算机的本地时钟应与全球时间同步,但在现实中会发生偏差。因此,即使二者之间只是出现很小偏差,TimeTradeServer 也无法再以最高精度重现服务器上的时间。
我们在 MQL5 中对同一函数的实现中,不将客户端与服务器时间之间的差值舍入至小时时区。相反,在计算中使用以秒数表示的准确差值。这就是为什么 TimeTradeServerExact 返回的时间其分钟数和秒数象服务器上一样显示。
下面是由该脚本生成的一个日志的示例。
TimeLocal()=2021.09.02 16:03:34 / ok
|
可以看到,客户端和服务器的时区相同,但有若干分钟的不同步(为了清晰展示)。在第一次调用中,TimeTradeServerExact 返回 0。此外,用于计算差值的数据将已到达,我们将会看到所有四个时间类型以几秒钟的间隔一致“走动”。
TimeLocal()=2021.09.02 16:03:35 / ok
|