English Русский Español Deutsch 日本語 Português
preview
处理时间(第一部分):基础

处理时间(第一部分):基础

MetaTrader 5测试者 | 24 十二月 2021, 10:04
3 737 0
Carl Schreiber
Carl Schreiber

哪一个时间

准确的时序也许是交易中的一个关键因素。 在当前钟点,伦敦或纽约的证券交易所是否已经或尚未开市,外汇交易的交易时间何时开始和结束? 对于一名实况手工交易者来说,这不算是个大问题。 透过各种互联网工具,金融工具的规格、自身时间,您可以快速查看什么时间是您策略的正确时机。 对于哪些只关注价格走势的交易者来说,一旦价格走势给他发出一个信号,他就做多或做空,而时间并不重要。 而对于“夜间剥头皮”的交易者来说,其中大有区别,有些人在纽约(股票)市场收盘后和欧盟公开市场(股票)开盘前进行交易;亦或有些交易者专门针对特定状况交易,例如“伦敦突破”;或有些交易者在最高反转处进行交易;或所有那些交易股票或期货的交易者。 这些交易者不会遵循经纪商的时间,但必须遵照美国、日本、伦敦、欧盟或莫斯科各自交易所的开市或闭市的当地实际时间,或特定期货的特殊交易时间。


夏季时间、冬季时间、和经纪商时移

如前所述,坐在屏幕前进行买卖的交易员可以轻松处理不同的时间。 无论是通过互联网还是某些功能,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,一家德国经纪商通知我:

  1. 在 2015 年 3 月 8 日之前,我们的 MT4 服务器时间设置到伦敦时间(= GMT)。
  2. 而在 2015 年 3 月 8 日,至 3 月 29 日间,设置到 CET(GMT + 1)
  3. 后从 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 的标准本地时间。

作为本部分的最后一部分,诸如 FxOpenFxClose 提供以秒为单位的整个星期的持续时间 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)    Broker: MetaQuotes Software Corp.
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   Broker: MetaQuotes Software Corp.
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 的答案:

请注意,我们的交易会在周一服务器时间 00:05:00 开始
(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,这样我们就可以轻松地计算其它时区的所有时间。 根据可能的假期或其它影响美国外汇市场开市和闭市时间的原因,我们假设:

  1. 外汇市场于纽约时间周五 17:00 闭市。
  2. 外汇市场将于纽约时间周日 17:00 开市。
  3. 正常来讲,开市(5*24=)120 小时,闭市(2*24=)48 小时。
  4. 如果在两个周五之间缺少若干个小时。 17:00 和周日 17:00,那么直到周日第一次报价,所有报价缺失,而非周五收到的最后一次报价之后。
  5. 传入的报价(无论时间戳是什么)始终是最新的(例如,不会是 1 小时前的)。
  6. 经纪商并没有改变它的时间变更政策,因为它曾是之前历史报价的最后一次。

展望

现在,我们已经定义了函数,或者更准确地说是宏替换,稍后我们将使用这些函数,并在下一篇文章“处理时间(第二部分):函数”中阐明了要开发的条件。这些函数能依据给定的任何时间为我们计算 GMT。

附件是 DealingwithTimePart1.mqh,其中包含此篇讨论的代码部分。 在第二篇文章中,会扩展上述函数。

请在文章的评论部分写下建议、评论和提示。


本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/9926

附加的文件 |
开发 EA 构造函数的一次尝试 开发 EA 构造函数的一次尝试
在本文中,我把自己的一套交易函数以成品 EA 的形式提供给大家。 这种方法能够通过简单地添加指标和改变输入来获得多种交易策略。
DoEasy 函数库中的图形(第八十八部分):图形对象集合 — 存储对象动态变化属性的二维动态数组 DoEasy 函数库中的图形(第八十八部分):图形对象集合 — 存储对象动态变化属性的二维动态数组
在本文中,我将创建一个动态多维数组类,该类能够改变任意维度中的数据量。 基于所创建的类,我还将创建一个二维动态数组来存储一些会动态变动的图形对象属性。
MQL5 酷宝书 – 财经日历 MQL5 酷宝书 – 财经日历
本文着重于财经日历的编程特性,并研究创建一个类来简化访问日历属性和接收事件值。 运用 CFTC(商品期货交易委员会)的非商业净持仓规则来开发指标作为一个实际例子。
使用 MQL5.0 社区频道和群聊天 使用 MQL5.0 社区频道和群聊天
MQL5.com 网站汇集了来自世界各地的交易者。 用户发表文章、共享免费代码、在市场上销售产品、执行自由职业订单、以及跟单信号。 您可以在论坛、交易者聊天和元交易者频道中与他们交流。