
处理时间(第一部分):基础
哪一个时间
准确的时序也许是交易中的一个关键因素。 在当前钟点,伦敦或纽约的证券交易所是否已经或尚未开市,外汇交易的交易时间何时开始和结束? 对于一名实况手工交易者来说,这不算是个大问题。 透过各种互联网工具,金融工具的规格、自身时间,您可以快速查看什么时间是您策略的正确时机。 对于哪些只关注价格走势的交易者来说,一旦价格走势给他发出一个信号,他就做多或做空,而时间并不重要。 而对于“夜间剥头皮”的交易者来说,其中大有区别,有些人在纽约(股票)市场收盘后和欧盟公开市场(股票)开盘前进行交易;亦或有些交易者专门针对特定状况交易,例如“伦敦突破”;或有些交易者在最高反转处进行交易;或所有那些交易股票或期货的交易者。 这些交易者不会遵循经纪商的时间,但必须遵照美国、日本、伦敦、欧盟或莫斯科各自交易所的开市或闭市的当地实际时间,或特定期货的特殊交易时间。
夏季时间、冬季时间、和经纪商时移
如前所述,坐在屏幕前进行买卖的交易员可以轻松处理不同的时间。 无论是通过互联网还是某些功能,PC 均能保持这些数值或时钟可用,且可随时调用 MQL 函数,譬如 TimeGMT(),TimeGMTOffset() 和其它函数获取这些数值。 若是有人想依据历史数据编写和测试与时间相关的交易程序,情况就有所不同了。 事实上,与实况交易类似,这个问题也同样容易回答。
从 UTC(世界协调时间)或格林尼治标准时间(GMT,https://greenwichmeantime.com/what-is-gmt/),简单地加上地理或金融工具相关的时移,就可以推算出时间所在。 但这并非如此简单。 冬季和夏季时间(DST 或夏令时)的转换是在时间基础上增加或减少若干小时。 然而,这并非一成不变,每个国家或地区(如欧洲)都会自行定义,有时多年不变(欧盟和美国),或者时不时地改变,比如在俄罗斯于 2014 年被废除。 在欧盟,2018 年发起过一次讨论,包括关于取消年度时间变更问题的调查(https://ec.europa.eu/germany/news/20180831-konsultation-sommerzeit_de),结果显示大多数人赞成废除,因此委员会提交了一份关于终结时间变更的立法提案(https://ec.europa.eu/germany/news/20180914-kommission-gesetzesvorschlag-ende-zeitumstellung_de),不过最后不了了之。
似乎这还不够混乱,现在经纪商正在加入混战,即如何各自定义服务器时间的方式。 在 2015,一家德国经纪商通知我:
- 在 2015 年 3 月 8 日之前,我们的 MT4 服务器时间设置到伦敦时间(= GMT)。
- 而在 2015 年 3 月 8 日,至 3 月 29 日间,设置到 CET(GMT + 1)
- 后从 3 月 29 日起,服务器设置回伦敦时间(= GMT + 1)
也就是说,德国经纪商使用 GMT + DST - USA,或者(主要)伦敦时间 + 美国的 DST,您必须首先遵守它,尽管原因可以理解,因为外汇交易在纽约时间 17:00 开始,故需取决于美国的时间变更。 结果就是,对于法兰克福的那些人来说,外汇交易有时在 21:00 开始,通常是 22:00,秋季的第一周或第两周则是 23:00
对于我们这些交易员和客户来说,这更像是在幼儿园。 每个人都能决定自己想做什么,以及怎么做。 故此,交易者或开发人员会面临许多不同的时间,所有这些时间都可能很重要,所有这些时间都必须根据 MQL 的“在案资源”判定 — 但不幸的是,如果策略测试器中正在运行指标、脚本或 EA,则不能做到。
我们要改变这一点。 不必咨询经纪商,我们将判断其各自的时间变更,如此就可以在任何时刻很简单地为策略测试器中任意时间戳确定 GMT,当然,更进一步就是任何所需的本地时间,像是纽约时间。 此外,因为它仅在这种背景下出现,而外汇市场在其余时间仍然开放,对于所有希望在周末前平仓的交易员来说,它是必要的。 不过,我们将在第二篇文章中讨论这些函数,因为现在我们只开发一些宏替换,这可令我们简化上述函数的计算和控制表述。
宏替代
所有一切都在(附件)包含文件 DealingWithTimePart1.mqh 里。 在这个文件的开头有各种宏替换。
首先,不同地区有一些时间偏移,如此您就不必一次再一次地推导或搜索它们:
//--- defines #define TokyoShift -32400 // always 9h #define NYShift 18000 // winter 17h=22h GMT: NYTime + NYshift = GMT #define LondonShift 0 // winter London offset #define SidneyShift -39600 // winter Sidney offset #define FfmShift -3600 // winter Frankfurt offset #define MoskwaShift -10800 // winter Moscow offset #define FxOPEN 61200 // = NY 17:00 = 17*3600 #define FxCLOSE 61200 // = NY 17:00 = 17*3600 #define WeekInSec 604800 // 60sec*60min*24h*7d = 604800 => 1 Week
为了更好地理解,我们同意 GMT 是一个不可变的时间锚点,而不同的本地时间,如纽约、伦敦或莫斯科,每一个都有不同的(可变)时移。 同样,我们也将夏季或冬季时间的变更作为变量。 原因很简单。 可变时移的符号定义如下:
可变时间 + 可变时移 = GMT
一些例子:
莫斯科 (16h) + 莫斯科时移 (-3h) = GMT (13h)
纽约时间 (16h) + 纽约时移 (+5h) = GMT (21h)
纽约时间 (16h) + (纽约时移 (+5h) + DST_US(-1h)) = GMT (20h)
法兰克福时间 (16h) + (法兰克福时移 (-1h) + DST_US(-1h)) = GMT (14h)
留心括号! 当根据 GMT 计算可变时间时,它们变得非常重要:
纽约时间 (16h) = GMT (20h) - (纽约时移 (+5h) + DST_US(-1h)) => 20 -(+5 + -1) = 20 - 5 +1 = 16h
法兰克福时间 (16h) = GMT (14h) - (法兰克福时移 (-1h) + DST_US(-1h)) => 14 -( -1 + -1) = 14 +1 +1 = 16h
相信我,这是标记错误和误解的永恒来源。
以这种形式中,MQL5 和 PC 也会处理时差,如 TimeGMTOffset(): TimeLocal() + TimeGMTOffset() = TimeGMT()) 或 TimeDaylightSavings(): TimeLocal() + TimeDaylightSavings() = 冬季或 PC 的标准本地时间。
作为本部分的最后一部分,诸如 FxOpen 和 FxClose 提供以秒为单位的整个星期的持续时间 WeekInSec,因为在为变量赋值时,这种设计比在代码中突兀加入数字(例如 604800)更容易理解。
后跟两个简化的变量输出。 TOSTR(A) 它打印变量的名称及其值 - 非常优美。 然后是内含工作日缩写的数组。 它在本项目的开发代码中多次被用到,其有助于节省代码行的空间,也有助于计算时间戳的朝向:
#define TOSTR(A) #A+":"+(string)(A)+" " // Print (TOSTR(hGMT)); => hGMT:22 (s.b.) string _WkDy[] = // week days { "Su.", "Mo.", "Tu.", "We.", "Th.", "Fr.", "Sa.", "Su." };
现在,遵循时间计算的备选方案,从而避免将时间分配给 MQ 结构 MqlDateTime 时读取标量值的迂回过程。 它们是直接进行计算的:
#define DoWi(t) ((int)(((t-259200)%604800)/86400)) // (int)Day of Week Su=0, Mo=1,... #define DoWs(t) (_WkDy[DoWi(t)]) // Day of Week as: Su., Mo., Tu., ....
DoWi(t) (周内星期化为整数)判断周内星期的整数值(星期日:0,星期一:1,…),而 DoWs(t) (周内星期的字符串形式)则返回调用 DoWi(t) 和数组 _WkDy[] 后组成的周内星期缩写文本。 由于本文的第二部分涉及周末的最后和第一个小时,因此将会更频繁地取用这些宏替换。
#define SoD(t) ((int)((t)%86400)) // Seconds of Day #define SoW(t) ((int)((t-259200)%604800)) // Seconds of Week
SoD(t) (一天中的秒数)返回自刚过去的 00:00 点以来的秒数。 因此,SoD(TimeCurrent()) 用这种简单的方法计算出一根蜡烛已经存在的持续时间(以秒为单位)。 类似地,SoW(t) 计算自上周日 00:00 点以来的秒数。 通过这种途径,很容易计算出已流逝时间(以秒为单位)的百分比,和当天的剩余时间。 如果将该值除以 864(=0.01*24*60*60),则得到当天已流逝时间的百分比:
(double)SoD(D’20210817 15:34‘) / 864. = 64.86% 86400 - SoD(D’20210817 15:34‘) = Print("D'20210817 15:34': ", DoubleToString((double)SoD(D'20210817 15:34')/864.0, 2),"% ", 86400 - SoD(D’20210817 15:34‘),“ sec left“ );
这些计算相应地起作用(无论需要它):
#define MoH(t) (int(((t)%3600)/60)) // Minute of Hour #define MoD(t) ((int)(((t)%86400)/60)) // Minute of Day 00:00=(int)0 .. 23:59=1439
函数 ToD(t) 把一天的秒数转换为数据类型 “datetime”,并返回。 这可以防止编译器在某种状况下发出警告消息:
#define ToD(t) ((t)%86400) // Time of Day in Sec (datetime) 86400=24*60*60
函数 HoW(t) 返回自星期日 00:00 点以来的小时数:
#define HoW(t) (DoW(t)*24+HoD(t)) // Hour of Week 0..7*24 = 0..168 0..5*24 = 0..120
一天中的小时数可以用一种简单的方法来计算,结果是一个整数,而不是一个日期:
#define HoD(t) ((int)(((t)%86400)/3600)) //Hour of Day: 2018.02.03 17:55 => 17
这与“商业”四舍五入相同:
#define rndHoD(t) ((int)((((t)%86400)+1800)/3600))%24 // rounded Hour of Day 17:55 => 18
并与 datetime 类型相同:
#define rndHoT(t) ((t+1800)-((t+1800)%3600)) // rounded Hour of Time: 2018.02.03 17:55:56 => (datetime) 2018.02.03 18:00:00
一天开始的时间化为 datetime,否则必须调用日线时间帧 D1 来额外判断:
#define BoD(t) ((t)-((t)%86400)) // Begin of day 17.5 12:54 => 17.5. 00:00:00
一周开始的时间化为 datetime,否则必须调周线时间帧来判断:
#define BoW(t) ((t)-((t-172800)%604800 - 86400)) // Begin of Week, Su, 00:00
以下片段利用 MQL 结构和函数,因为转换对我来说太复杂了,例如要考虑闰年,但它们遵循上面相同的格式原则;时间函数的名称主要是三个字母或首字母缩写,DoY、(=年内的天)、MoY(年内的月)和 YoY(年内的年):
MqlDateTime tΤ; // hidden auxiliary variable: the Τ is a Greek characker, so virtually no danger int DoY(const datetime t) {TimeToStruct(t,tΤ);return(tΤ.day_of_year); } int MoY(const datetime t) {TimeToStruct(t,tΤ);return(tΤ.mon); } int YoY(const datetime t) {TimeToStruct(t,tΤ);return(tΤ.year); }
以下仍然是根据美国定义来计算年内的周:
int WoY(datetime t) //Su=newWeek Week of Year = nWeek(t)-nWeeks(1.1.) CalOneWeek:604800, Su.22:00-Su.22:00 = 7*24*60*60 = 604800 { return(int((t-259200) / 604800) - int((t-172800 - DoY(t)*86400) / 604800) + 1); // calculation acc. to USA }
(有关每周计算的更多信息,请参见此处: https://zh.wikipedia.org/wiki/Week#Numbering)
季节性和地方性时差
在声明并解释了函数所需的简化,以及更多内容之后,我们现在准备进入更广泛领域,彻底了解本地和季节性时移的差别,以及经纪商和 MQL5 如何处理它们。 我们从编程语言 MQL5 开始。
MQL5 中的时间
第一个立即能想到的时间是经纪商提供的报价时间,反映在柱线的开盘时间中,并可用 TimeCurrent() 查询最后收到的报价。 在许多情况下 — 这也许会令人惊讶 — 这个时间相对来说并不重要,它只用在柱线、价格、以及交易活动的按时间排序。 故此,它仅在终端环境、实况交易环境、以及策略测试环境中具有相关性。
然后是 TimeTradeServer():返回交易服务器的当前计算时间。 不像 TimeCurrent() 函数,时间计算在客户端执行,并取决于用户计算机中的时间设置。但是:在策略测试器中进行测试时,TimeTradeServer() 是根据历史数据模拟的,且始终与 TimeCurrent() 相等。因此,对于那些需要在策略测试器中针对实况进行优化的程序,此功能没有多大帮助。
对于 TimeGMT() 和 TimeLocal():在策略测试器中进行测试期间,TimeGMT() 始终等于 TimeTradeServer() 模拟的服务器时间,这其实也等于 TimeCurrent()。
这也令 TimeGMTOffset() 在策略测试器中“无效”,因为 TimeGMTOffset() = TimeGMT() - TimeLocal(),故始终为零。 :(
剩下的最后一项是 TimeDaylightSaves():“如果转换到夏令时,返回夏令时的校正值(以秒为单位)。 取决于用户计算机中的设置。 ... 如果转换到冬季时间(标准时间),则返回 0。
以下是演示帐户实况的打印输出(从日期可以看出,MQ 在查询时是依据欧盟和美国当前的夏令时):
2021.08.26 09:25:45.321 MasteringTime (EURUSD,M1) TimeCurrent: 10:25
2021.08.26 09:25:45.321 MasteringTime (EURUSD,M1) TimeTradeServer: 10:25
2021.08.26 09:25:45.321 MasteringTime (EURUSD,M1) TimeLocal: 09:25
2021.08.26 09:25:45.321 MasteringTime (EURUSD,M1) TimeGMT: 07:25
2021.08.26 09:25:45.321 MasteringTime (EURUSD,M1) TimeDaylightSavings: -3600 h: -1
2021.08.26 09:25:45.321 MasteringTime (EURUSD,M1) TimeGMTOffset: -7200 h: -2
这里是策略测试器中相同帐户的打印输出(调试):
2021.08.26 10:15:43.407 2021.06.18 23:54:59 TimeCurrent: 23:54
2021.08.26 10:15:43.407 2021.06.18 23:54:59 TimeTradeServer: 23:54
2021.08.26 10:15:43.407 2021.06.18 23:54:59 TimeLocal: 23:54
2021.08.26 10:15:43.407 2021.06.18 23:54:59 TimeGMT: 23:54
2021.08.26 10:15:43.407 2021.06.18 23:54:59 TimeDaylightSavings: 0 h: 0
2021.08.26 10:15:43.407 2021.06.18 23:54:59 TimeGMTOffset: 0 h: 0
所有这些功能在策略测试器中都没有啥帮助,它们仅在实况下有用。 因此,我们仅有 TimeCurrent() 可以自己计算所有其它时间,而这一切都很混乱。 好吧,任何人都可以轻易做到 ;)
理论上您可以这样认为,您可以从经纪商那里得到一切,譬如他如何定义报价时间戳的时间变更。 例如,下面是来自 Alpari 的答案:
(GMT+2/GMT +3 DST) 并于周五服务器时间 23:55:00 结束。 夏日期间
交易在周日格林威治标准时间 21:05 开始,而在冬季则是
周日 22:05 GMT。
事实证明,只有部分是事实。 首先,未提及欧盟和美国在夏季或冬季的过渡时间并不相同;其次,未提及该过渡时间内的价格,例如 2021 年 3 月 26 日,并非在 23:55 结束,而是在 22:55 就结束了。 在 23 点 55 分之前和之后。
但在我们继续之前,先简单介绍一下不同时区及其首字母缩略词。 在我看来,这个网站对我的整个主题最有帮助: https://24timezones.com/time-zones。 那里的表格列出了 200 个不同的时区。 以下是与我们相关的:
缩略语 | 时区 | 网站 | UTC 时差 | GMT 时差 |
---|---|---|---|---|
CEST | 欧洲中部夏令时 | 法兰克福夏令时 | UTC+2 | GMT+2 |
中欧时间 | 欧洲中部时间 | 法兰克福正常时间 | UTC+1 | GMT+1 |
EDT | 东部夏令时 | 纽约正常时间 | UTC-4 | GMT-4 |
EEST | 欧洲东部夏令时 | 塞浦路斯,夏令时 | UTC+3 | GMT+3 |
东欧时间 | 欧洲东部时间 | 塞浦路斯正常时间 | UTC+2 | GMT+2 |
EST | 东部标准时间 | 纽约正常时间 | UTC-5 | GMT-5 |
ET | 东部时间 | 纽约 | UTC-5/UTC-4 | GMT-5/GMT-4 |
GMT | 格林威治标准时间 | 伦敦正常时间 | UTC+0 | GMT+0 |
UTC | 协调世界时间 | 伦敦正常时间 | UTC | GMT |
请注意,如果您纯粹看数字的话,纽约的正常时差为 -5 小时,夏季为 -4,因此“少了”一小时,而法兰克福自 MQ+2 时差为 +1,但夏季分别为 +2 和 +3,因此“多了”一小时。 请不要对此感到困惑,记住示例!
现在,我们来看看 MQ 演示帐户在一个周末前后的第一个和最后一个报价的时间戳是什么:在 “EURUSD” 的 M1 图表上,我们首先激活周期分隔,然后在图表上按 Enter 键,在每种情况下以 dd.mm.yyyy 格式输入星期一的日期。(不是 MQ 日期格式)。 然后用鼠标将图表向右移动一点。 现在,带垂直线的柱线图是新一周的第一根柱线图,其左侧的柱线图是上一周的最后一根柱线图。 此处是周五最后一根柱线和周末后第一根柱线的日期:
2020 年秋季时间转换前后的周末:
夏季-EU | 夏季-EU | 夏季-EU | 冬季-EU | 冬季-EU | 冬季-EU | 冬季-EU | 冬季-EU | 冬季-EU | 冬季-EU |
---|---|---|---|---|---|---|---|---|---|
夏季-US | 夏季-US | 夏季-US | 夏季-US | 夏季-US | 冬季-US | 冬季-US | 冬季-US | 冬季-US | 夏季-US |
周五 | 周一 | 周五 | 周一 | 周五 | 周一 | 周五 | 周一 | 周五 | 周一 |
2020.10.16 | 2020.10.19 | 2020.10.23 | 2020.10.26 | 2020.10.30 | 2020.11.02 | 2021.03.05 | 2021.03.08 | 2021.03.12 | 2021.03.15 |
23:54 | 00:05 | 23:54 | 00:05 | 22:54 | 00:02 | 23:54 | 00:03 | 23:54 | 00:00 |
1,1716 | 1,17195 | 1,18612 | 1,18551 | 1,16463 | 1,16468 | 1,19119 | 1,19166 | 1,19516 | 1,19473 |
1,17168 | 1,17208 | 1,18615 | 1,18554 | 1,16477 | 1,16472 | 1,19124 | 1,19171 | 1,19521 | 1,19493 |
1,1716 | 1,1718 | 1,18596 | 1,18529 | 1,16462 | 1,16468 | 1,19115 | 1,19166 | 1,19514 | 1,19473 |
1,1716 | 1,17188 | 1,18598 | 1,18534 | 1,16462 | 1,16472 | 1,1912 | 1,19171 | 1,19519 | 1,19491 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
29 | 22 | 35 | 48 | 30 | 3 | 33 | 2 | 23 | 25 |
4 | 11 | 2 | 6 | 2 | 61 | 1 | 38 | 1 | 29 |
这是 2021 年春季时间转换前后的周末:
冬季-EU | 冬季-EU | 冬季-EU | 冬季-EU | 冬季-EU | 冬季-EU | 冬季-EU | 夏季-EU | 夏季-EU | 夏季-EU |
---|---|---|---|---|---|---|---|---|---|
冬季-US | 冬季-US | 冬季-US | 夏季-US | 夏季-US | 夏季-US | 夏季-US | 夏季-US | 夏季-US | 夏季-US |
周五 | 周一 | 周五 | 周一 | 周五 | 周一 | 周五 | 周一 | 周五 | 周一 |
2021.03.05 | 2021.03.08 | 2021.03.12 | 2021.03.15 | 2021.03.19 | 2021.03.22 | 2021.03.26 | 2021.03.29 | 2021.04.02 | 2021.04.05 |
23:54 | 00:03 | 23:54 | 00:00 | 22:54 | 00:00 | 22:54 | 00:07 | 23:54 | 00:03 |
1,19119 | 1,19166 | 1,19516 | 1,19473 | 1,19039 | 1,18828 | 1,17924 | 1,17886 | 1,17607 | 1,17543 |
1,19124 | 1,19171 | 1,19521 | 1,19493 | 1,19055 | 1,18835 | 1,17936 | 1,17886 | 1,17608 | 1,17543 |
1,19115 | 1,19166 | 1,19514 | 1,19473 | 1,19038 | 1,18794 | 1,17922 | 1,17884 | 1,17607 | 1,17511 |
1,1912 | 1,19171 | 1,19519 | 1,19491 | 1,19044 | 1,18795 | 1,17933 | 1,17886 | 1,17608 | 1,17511 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
33 | 2 | 23 | 25 | 41 | 43 | 17 | 3 | 2 | 3 |
1 | 38 | 1 | 29 | 1 | 20 | 5 | 68 | 28 | 79 |
有趣的是,有时周末前的最后一次报价应该在 23:00(22:54)左右到达,但通常在 24:00(23:54)时才会到达,但第一次报价总能在 00:00 到达,这一点我还不太理解。 若纯粹按小时的角度来看,有时这会造成 1 小时的“价格漏洞”(23:00 闭市,00:00 开市),而外汇市场通常在周五 17:00(纽约时间)闭市,周日 17:00(纽约时间)开市。 我们来具体地看看周末行为,切换并计算与我们相关的其它时区的相应时间:
日期 |
| 最后的周五日期 |
|
|
| 日期 |
|
|
|
|
| 最后一根柱线 | 下一根 m1 柱线 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
美国切换 |
| 纽约时间 | 纽约-GMT | GMT | 欧洲切换 |
| 中欧时间-GMT | 中欧时间 | 东欧时间-GMT | 东欧时间 | MQ 内 | MQ 内 | |
| 夏季-US | Fr, 16. Oct 20 | 17:00 | GMT + 4 | 21 |
| 夏季-EU | GMT + 2 | 23 | GMT + 3 | 24 | 23:54 |
|
| 夏季-US | So, 18. Oct 20 | 17:00 | GMT + 4 | 21 |
| 夏季-EU | GMT + 2 | 23 | GMT + 3 | 24 |
| 00:05 |
| 夏季-US | Fr, 23. Oct 20 | 17:00 | GMT + 4 | 21 | 25.10.20 | 夏季-EU | GMT + 2 | 23 | GMT + 3 | 24 | 23:54 |
|
| 夏季-US | So, 25. Oct 20 | 17:00 | GMT + 4 | 21 |
| 冬季-EU | GMT + 1 | 22 | GMT + 2 | 23 |
| 00:05 |
01.11.20 | 夏季-US | Fr, 30. Oct 20 | 17:00 | GMT + 4 | 21 |
| 冬季-EU | GMT + 1 | 22 | GMT + 2 | 23 | 22:54 |
|
| 冬季-US | So, 1. Nov 20 | 17:00 | GMT + 5 | 22 |
| 冬季-EU | GMT + 1 | 23 | GMT + 2 | 24 |
| 00:02 |
| 冬季-US | Fr, 6. Nov 20 | 17:00 | GMT + 5 | 22 |
| 冬季-EU | GMT + 1 | 23 | GMT + 2 | 24 | 23:54 |
|
| 冬季-US | So, 8. Nov 20 | 17:00 | GMT + 5 | 22 |
| 冬季-EU | GMT + 1 | 23 | GMT + 2 | 24 |
| 00:03 |
14.03.21 | 冬季-US | Fr, 12. Mrz 21 | 17:00 | GMT + 5 | 22 |
| 冬季-EU | GMT + 1 | 23 | GMT + 2 | 24 | 23:54 |
|
| 夏季-US | So, 14. Mrz 21 | 17:00 | GMT + 4 | 21 |
| 冬季-EU | GMT + 1 | 22 | GMT + 2 | 23 |
| 00:00 |
| 夏季-US | Fr, 26. Mrz 21 | 17:00 | GMT + 4 | 21 | 28.03.21 | 冬季-EU | GMT + 1 | 22 | GMT + 2 | 23 | 22:54 |
|
| 夏季-US | So, 28. Mrz 21 | 17:00 | GMT + 4 | 21 |
| 夏季-EU | GMT + 2 | 23 | GMT + 3 | 24 |
| 00:07 |
| 夏季-US | Fr, 2. Apr 21 | 17:00 | GMT + 4 | 21 |
| 夏季-EU | GMT + 2 | 23 | GMT + 3 | 24 | 23:54 |
|
| 夏季-US | So, 4. Apr 21 | 17:00 | GMT + 4 | 21 |
| 夏季-EU | GMT + 2 | 23 | GMT + 3 | 24 |
| 00:03 |
在一周当中,欧盟和美国的时钟不会分别显示当地的夏时制或标准时间,纽约外汇市场周日开市时间为 EET 23:00,周五闭市时间为 EET 23:00。 然而,各种经纪商以及 MQ 的演示帐户始终在周日 24:00(或周一 00:00)才会提供第一次报价。 现在人们可能会想,报价的时间戳总是与第二次变换匹配,而非第一次变换。 然而,在周五,外汇市场收盘前的最后一次报价必须有一个 24:00 之前的时间戳,因为只有这样才会有完整的 24*5=120 小时,但因此会缺失一个小时。 这样就提出了一个问题,这一小时是在周末前的周五还是周末后的周日?
鉴于每周的收盘价格比之周日第一个交易小时的开盘价更为重要,因此可以推断,如果周五的最后一次价格是 23:00 之前不久的价格,但下一个价格若是 24:00 或 00:00,那么外汇市场的每周第一个小时就不见了,周日 23:00-24:00 的价格,其实不是最后一次,而是周五 23:00-24:00 的那次。 然而,如果第一次报价的时间戳是在周日 23:00 后不久,那么您如果遵循谨慎的策略,在周末之前所有持仓平仓,那么不仅很容易辨别时间变更,而且很容易知道外汇市场何时再次闭市(周日开市后 5d*24h=120 小时)。 正如所说的,任何人都能简单地做到。
首先,我们考虑我们可以做出什么假设。 在策略测试器中,我们只有 TimeCurrent()。 依靠这个,我们能判断 GMT 或 UTC,这样我们就可以轻松地计算其它时区的所有时间。 根据可能的假期或其它影响美国外汇市场开市和闭市时间的原因,我们假设:
- 外汇市场于纽约时间周五 17:00 闭市。
- 外汇市场将于纽约时间周日 17:00 开市。
- 正常来讲,开市(5*24=)120 小时,闭市(2*24=)48 小时。
- 如果在两个周五之间缺少若干个小时。 17:00 和周日 17:00,那么直到周日第一次报价,所有报价缺失,而非周五收到的最后一次报价之后。
- 传入的报价(无论时间戳是什么)始终是最新的(例如,不会是 1 小时前的)。
- 经纪商并没有改变它的时间变更政策,因为它曾是之前历史报价的最后一次。
展望
现在,我们已经定义了函数,或者更准确地说是宏替换,稍后我们将使用这些函数,并在下一篇文章“处理时间(第二部分):函数”中阐明了要开发的条件。这些函数能依据给定的任何时间为我们计算 GMT。
附件是 DealingwithTimePart1.mqh,其中包含此篇讨论的代码部分。 在第二篇文章中,会扩展上述函数。
请在文章的评论部分写下建议、评论和提示。
本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/9926

