请观看如何免费下载自动交易
请在Telegram上找到我们!
加入我们粉丝页
有趣的脚本?
因此发布一个链接 -
让其他人评价
喜欢这个脚本? 在MetaTrader 5客户端尝试它
程序库

Local Timezones and Local Session Hours - MetaTrader 5程序库

显示:
206
等级:
(16)
已发布:
MQL5自由职业者 需要基于此代码的EA交易或指标吗?请在自由职业者服务中订购 进入自由职业者服务

交易者们,你们好。

该库拥有获取特定或所有外汇市场当前当地时间的所有功能。您可以在时区之间转换当地时间,或将其转换为您的经纪商服务器时间。您还可以通过分别设置每个时段的开始和结束时间,在特定时段进行交易。该库将处理经纪商和这些市场的不同时间偏移和夏令时变化。这就减轻了您每次为专家顾问或技术指标编程时都要重新发明轮子的负担,因为专家顾问或技术指标必须处理时区和当地时段的问题。


什么是时区?

时区被定义为标准时间,取决于该地的地理代表性。换句话说,时区是指基于地球自转的特定地区的当地时间。它以 UTC(协调世界时)定义,UTC 是协调世界各地区时间的标准。

例如 -- 纽约时间比格林威治时间晚 5 小时,根据日照以 UTC-5 或 UTC-4 表示。悉尼的时间比格林尼治早 10 小时,根据日照(夏季或冬季)的不同,用 UTC+10 或 UTC+11 表示。UTC和GMT这两个术语通常交替使用来表示偏移,因此UTC+2和GMT+2通常 具有相同的含义。

如果时区在格林尼治标准时间以东,则 UTC 偏移为正;如果时区在格林尼治标准时间以西,则 UTC 偏移为负。


时区标识符

//+------------------------------------------------------------------+
//| 时区标识符|
//+------------------------------------------------------------------+
enum ENUM_ZONE_ID
  {
   ZONE_ID_SYDNEY,     // 悉尼
   ZONE_ID_TOKYO,      // 东京
   ZONE_ID_FRANKFURT,  // 法兰克福
   ZONE_ID_LONDON,     // 伦敦
   ZONE_ID_NEWYORK,    // 纽约
   ZONE_ID_UTC,        // UTC
   ZONE_ID_LOCAL,      // 本地
   ZONE_ID_BROKER,     // 经纪人
   ZONE_ID_CUSTOM      //自定义
  };


类接口

//+------------------------------------------------------------------+
//| 类 CTimeZoneInfo。|
//| 用途:用于访问指定位置的当地时间的类。
//| 位置以及时区信息、时间
//| 当年的变化。|
//||
// | 程序库中使用的偏移符号:|
//| 请注意,图书馆表示的是正时间。
//| 按正偏移量划分时区,按负偏移量划分时区。
//| 负偏移。|
//| 相反,MQL5 内置的 TimeGMTOffset()
//| 函数表示正时区,如 GMT+3、||......
//| 负偏移量,如 -10800,反之亦然。
//+------------------------------------------------------------------+
class CTimeZoneInfo
  {
public:
                     CTimeZoneInfo( ENUM_ZONE_ID placeId, datetime pLocalTime = TIME_NOW );
                    ~CTimeZoneInfo( void );

   string            Name( void );                                                       // 返回时区名称
   string            ToString( bool secs = true, bool tzname = true );                   // 返回按 TZ/DST 偏移和 tzname 格式化的本地时间字符串
   bool              RefreshTime( void );                                                // 刷新当前当地时间并填充时区信息
   bool              SetLocalTime( datetime pLocalTime = TIME_NOW );                     // 将该位置的当地时间设置为指定时间

   datetime          TimeLocal( void );                                                  // 返回当地时区的时间
   datetime          TimeUTC( void );                                                    // 返回 UTC 时间(在所有时区都一样)
   int               TimeGMTOffset( void );                                              // 正时区为正值(如 GMT+3),否则为负值。(包括夏令时)
   int               TimeDaylightSavings( void );                                        // 返回所设置的当地时间的时区 DST 校正(以秒为单位)。

   datetime          ConvertLocalTime( ENUM_ZONE_ID destinationId );                     // 将该时区的当地时间转换为其他时区的时间
   bool              GetDaylightSwitchTimes( datetime &dst_start, datetime &dst_end );   // 获取当年夏令时的起止时间
   datetime          GetDaylightNextSwitch( void );                                      // 获取下一个夏令时切换的当地时间
   void              PrintObject( void );

   //--- 静态方法不需要创建对象。
   static datetime   GetCurrentTimeForPlace ( ENUM_ZONE_ID placeId );                    // 获取指定时区的当前当地时间
   static string     FormatTimeForPlace     ( datetime time, ENUM_ZONE_ID placeId, bool secs = true, bool tzname = true );
   static datetime   ConvertTimeForPlace    ( datetime time, ENUM_ZONE_ID placeId, ENUM_ZONE_ID destinationId );
   static int        TimeGMTOffset          ( ENUM_ZONE_ID placeId, datetime time = TIME_NOW );   // Returns total tz offset (UTC+DST) from GMT, for a timezone at given local time.
   static int        TimeDaylightSavings    ( ENUM_ZONE_ID placeId, datetime time = TIME_NOW );   // 返回给定当地时间时区的 dst 校正(以秒为单位)。
   static bool       IsDaylightSavingTime   ( ENUM_ZONE_ID placeId, datetime time = TIME_NOW );   // 检查指定时间是否属于夏令时
   static bool       GetDaylightSwitchTimes ( ENUM_ZONE_ID placeId, int iYear, datetime &dst_start, datetime &dst_end );
   static bool       GetDaylightSwitchDeltas( ENUM_ZONE_ID placeId, int iYear, int &delta_start, int &delta_end );

   static bool       SetCustomTimeZone( string name, int baseGMTOffset = 0,              // 定义库中没有的时区。
                                        ENUM_ZONE_ID dstSchedule = ZONE_ID_UTC );
   static void       SetUsingGoldSymbol( bool enabled = true );                          // 设置使用黄金符号估算服务器 TZ/DST 的选项
  };


类接口

//+------------------------------------------------------------------+
//| Class CSessionHours.|
//| 用途:用于访问本地交易时段时间的类。
//| 指定位置。|
//| 从类 CTimeZoneInfo 派生。|
//| 注意:默认会议时间设置为上午 8:00 - 下午 5:00 | |
//| 新 CSessionHours 对象的当地时间。
//+------------------------------------------------------------------+
class CSessionHours : public CTimeZoneInfo
  {
public:
                     CSessionHours( ENUM_ZONE_ID placeId );
                    ~CSessionHours( void );

   //--- 访问本地会话时间的方法
   bool              RefreshTime( void );                            // 刷新当前当地时间和当天的会议时间
   bool              SetLocalTime( datetime pLocalTime );

   //--- 覆盖默认本地会话时间的方法
   bool              BeginLocalTime( int pHour, int pMinute );       // 使用开始时针和分针设置本地会话开始时间
   bool              EndLocalTime( int pHour, int pMinute );         // 使用结束时和结束分设置本地会话结束时间

   //--- 访问本地会话时间的方法
   datetime          BeginLocalTime( void );
   datetime          EndLocalTime( void );
   bool              CheckLocalSession( void );                      // 检查本地交易时段当前是否处于活动状态。
   int               SecRemainingSession( void );                    // 本地会话关闭前的剩余时间(以秒为单位)。

   //--- 静态方法不需要创建对象。
   static datetime   ForexCloseTime( void );                         // 本周外汇市场关闭时的经纪人时间。
   static int        SecRemainingForex( void );                      // 距离本周外汇市场收盘的剩余时间(以秒为单位)。
  };


库中使用的偏移符号

请注意,该库用 偏移表示 正时区 ,用负偏移表示负时区。

这与 MQL5 内置的 TimeGMTOffset() 函数相反,后者用负偏移量(如 -10800)表示正时区(如 GMT+3),反之亦然。


选择用于估算服务器 TZ/DST 的符号

默认情况下,程序库将搜索并加载 XAUUSD 符号,用于估算服务器的时区偏移。在美国夏令时和欧盟夏令时不同步的几周(三月和十月下旬),XAUUSD 可以提供更可靠的结果(特别是对于遵循欧盟夏令时时间表的经纪商)。如果您的经纪商遵循美国夏令时时间表,或根本不遵循时间表,也可以使用图表符号。使用 "false "调用 CTimeZoneInfo::SetUsingGoldSymbol(),以使用当前图表的符号,而不是 XAUUSD。

要确定经纪商的夏令时(DST)时间表,可以使用以下脚本 https://www.mql5.com/zh/code/48650

//+------------------------------------------------------------------+
//| 设置是否使用 XAUUSD(黄金)符号来估算"|"。
//| 服务器的 TZ/DST 由 H1 引用历史分析得出。
//| TRUE:搜索并加载 Gold 符号(默认行为)。
//| FALSE :使用当前图表的符号。
//+------------------------------------------------------------------+
void CTimeZoneInfo::SetUsingGoldSymbol(const bool enabled = true);

注意

XAUUSD 比 Forex 晚开始一小时,因此夏令时切换会晚一小时(仅在策略测试器中,在正常模式下不会)。


关于与策略测试器兼容性的说明

在策略测试器中测试时,TimeGM T () 始终等于TimeTradeServer() 模拟 服务器时间。

TimeZoneInfo 库通过分析 H1 报价历史记录,根据 "真实 "格林尼治标准时间估算各时区的正确时间,而不是根据调用内置 TimeGMT 函数返回的时间。

如果 XAUUSD 符号用于估算服务器的 TZ/DST 时区,那么策略测试器中的 dst 切换将晚一小时进行。



I.使用本地时区

如何获取当前时间?

RefreshTime() 方法 将更新当前时区的本地时间 我们看一个示例来说明如何获取当前时间。

   Print("\n========== Get the current time in a timezone ==========");

   CTimeZoneInfo tz(ZONE_ID_TOKYO);
   tz.RefreshTime(); // 填充当前时区信息

   Print("Name()      : ", tz.Name());
   Print("TimeLocal() : ", tz.TimeLocal());
   Print("ToString()  : ", tz.ToString());

输出

   // ========== 获取时区的当前时间 ==========
   // Name() :东京
   // TimeLocal() : 2024.02.28 19:58:50
   // ToString() :周三, 2024.02.28 19:58:50 GMT+9 [东京]


您需要更多信息吗?

   Print("\n========== More information about a timezone ==========");

   CTimeZoneInfo tz(ZONE_ID_NEWYORK);
   tz.RefreshTime();

   Print("Name()                  : ", tz.Name());
   Print("TimeUTC()               : ", tz.TimeUTC());
   Print("TimeLocal()             : ", tz.TimeLocal());
   Print("TimeGMTOffset()         : ", tz.TimeGMTOffset());
   Print("TimeDaylightSavings()   : ", tz.TimeDaylightSavings());
   Print("ToString()              : ", tz.ToString());
   datetime dst_start, dst_end;
   tz.GetDaylightSwitchTimes(dst_start, dst_end);
   Print("dst_start               : ", dst_start);
   Print("dst_end                 : ", dst_end);
   Print("GetDaylightNextSwitch() : ", tz.GetDaylightNextSwitch());

输出:

   // ========== 有关时区的更多信息 ==========
   // Name() :纽约
   // TimeUTC() : 2024.03.17 16:50:38
   // TimeLocal() : 2024.03.17 12:50:38
   // TimeGMTOffset() : -14400
   // TimeDaylightSavings() : 3600
   // ToString() :Sun, 2024.03.17 12:50:38 GMT-4 [New York] (DST)
   // dst_start : 2024.03.10 02:00:00
   // dst_end : 2024.11.03 02:00:00
   // GetDaylightNextSwitch() : 2024.11.03 02:00:00

备注:

- TimeUTC() 方法返回 UTC 时间,相当于 GMT 时间。

- TimeLocal() 方法返回该时区的本地时间(可能因调用RefreshTimeSetLocalTime 方法而改变)。

- TimeGMTOffset() 方法返回该时区的本地时间与格林尼治标准时间之间的当前差值(以秒为单位),同时考虑到冬令时或夏令时的切换。返回的偏移量包括当前时区的 DST 调整。如果该时区位于格林尼治标准时间以东(领先于格林尼治标准时间),则格林尼治标准时间偏移量为正;如果该时区位于格林尼治标准时间以西(落后于格林尼治标准时间),则格林尼治标准时间偏移量为负。

-TimeDaylightSavings() 方法返回夏令时(DST)调整值(以秒为单位),前提是在实行 DST 的时区已切换到夏令时。如果已切换到冬令(标准)时间(或时区不支持 DST),则返回 0。


如何配置内置自定义时区以供日后使用?

CTimeZoneInfo 类包含一个SetCustomTimeZone 方法,您可以使用该方法配置内置的自定义时区。让我们来看一个示例,说明如何将内置自定义时区配置为指定名称、格林威治标准时间(GMT)偏移量和日光时间表标识符。

   Print("\n========== Configure the built-in custom timezone ==========");

   string        name  = "Custom+3";               // 自定义时区名称
   int           baseGMTOffset  = 10800;           // 自定义时区的基准格林尼治标准时间偏移(以秒为单位)
   ENUM_ZONE_ID  daylightRuleId = ZONE_ID_LONDON;  // 自定义时区的夏令时时间表

   bool success = CTimeZoneInfo::SetCustomTimeZone(name, baseGMTOffset, daylightRuleId);

   Print("Parameter 'name'            : ", name);
   Print("Parameter 'baseGMTOffset'   : ", baseGMTOffset);
   Print("Parameter 'daylightRuleId'  : ", EnumToString(daylightRuleId));
   Print("SetCustomTimeZone() returns : ", success);

输出:

   // ========== 配置内置自定义时区 ==========
   // 参数 'name' :自定义+3
   // 参数 "baseGMTOffset":10800
   // 参数 'daylightRuleId' :ZONE_ID_LONDON
   // SetCustomTimeZone() 返回:true


获取所有时区的当前时间

让我们看一个示例,了解如何获取所有时区的当前本地时间。

   Print("\n========== Get Current Time in All Timezones ==========");

   for(ENUM_ZONE_ID id=0; id <= MAX_ZONE_ID; id++)
     {
      CTimeZoneInfo tz(id);
      tz.RefreshTime();

      PrintFormat("%-12s:  %s | %s", tz.Name(), TimeToString(tz.TimeLocal()), tz.ToString());
     }

输出:

   // ========== 获取所有时区的当前时间 ==========
   // 悉尼 : 2024.02.28 21:58 | Wed, 2024.02.28 21:58:50 GMT+11 [Sydney] (DST)
   // Tokyo : 2024.02.28 19:58 | Wed, 2024.02.28 19:58:50 GMT+9 [Tokyo] 东京
   // Frankfurt : 2024.02.28 11:58 | Wed, 2024.02.28 11:58:50 GMT+1 [Frankfurt] (法兰克福)
   // London : 2024.02.28 10:58 | Wed, 2024.02.28 10:58:50 GMT+0 [London] 伦敦
   // 纽约 : 2024.02.28 05:58 | Wed, 2024.02.28 05:58:50 GMT-5 [纽约]
   // UTC : 2024.02.28 10:58 | Wed, 2024.02.28 10:58:50 GMT+0 [UTC]
   // Home : 2024.02.28 12:58 | Wed, 2024.02.28 12:58:50 GMT+2 [Home] 首页
   // FXOpen-MT5 : 2024.02.28 12:58 | Wed, 2024.02.28 12:58:50 GMT+2 [FXOpen-MT5]


可以使用静态方法GetCurrentTimeForPlace() 以另一种方式获取。另外,请注意还有另一种静态方法FormatTimeForPlace() 可用来将纯 mql日期 变量格式化为字符串 类似于 TimeToString,但其中包含工作日、日期、时间、时区名称和偏移。调用这些静态方法无需创建对象。

   Print("\n========== GetCurrentTimeForPlace() ==========");

   for(ENUM_ZONE_ID id=0; id <= MAX_ZONE_ID; id++)
     {
      datetime time = CTimeZoneInfo::GetCurrentTimeForPlace(id);

      PrintFormat("Time        :  %s | %s", TimeToString(time), CTimeZoneInfo::FormatTimeForPlace(time, id));
     }

输出

   // ========== GetCurrentTimeForPlace() ==========
   // 时间 : 2024.02.28 21:58 | Wed, 2024.02.28 21:58:50 GMT+11 [Sydney] (DST)
   // 时间 : 2024.02.28 19:58 | Wed, 2024.02.28 19:58:50 GMT+9 [东京]
   // 时间 : 2024.02.28 11:58 | Wed, 2024.02.28 11:58:50 GMT+1 [Frankfurt] (法兰克福
   // 时间 : 2024.02.28 10:58 | Wed, 2024.02.28 10:58:50 GMT+0 [London] (伦敦
   // 时间 : 2024.02.28 05:58 | Wed, 2024.02.28 05:58:50 GMT-5 [New York] [纽约
   // 时间 : 2024.02.28 10:58 | Wed, 2024.02.28 10:58:50 GMT+0 [UTC]
   // 时间 : 2024.02.28 12:58 | Wed, 2024.02.28 12:58:50 GMT+2 [主页]
   // 时间 : 2024.02.28 12:58 | Wed, 2024.02.28 12:58:50 GMT+2 [FXOpen-MT5]


如何设置时区的本地时间?

SetLocalTime() 方法 将设置指定的本地时间 让我们看一个示例来说明如何设置时区的本地时间。

   Print("\n========== Set the local time for a timezone ==========");

   CTimeZoneInfo tz(ZONE_ID_NEWYORK);

   if(tz.SetLocalTime(D'2021.07.15 09:31'))
      PrintFormat("%-12s:  %s | %s", tz.Name(), TimeToString(tz.TimeLocal()), tz.ToString());

   if(tz.SetLocalTime(D'2022.01.23 17:04'))
      PrintFormat("%-12s:  %s | %s", tz.Name(), TimeToString(tz.TimeLocal()), tz.ToString());

   if(tz.SetLocalTime(D'2023.03.12 02:21'))
      PrintFormat("%-12s:  %s | %s", tz.Name(), TimeToString(tz.TimeLocal()), tz.ToString());

输出:

   // ========== 设置时区的当地时间 ==========
   // 纽约 : 2021.07.15 09:31 | Thu, 2021.07.15 09:31:00 GMT-4 [New York] (DST)
   // 纽约 : 2022.01.23 17:04 | Sun, 2022.01.23 17:04:00 GMT-5 [纽约]
   // >>错误:纽约时间 2023.03.12 02:21 不存在。这是因为夏令时跳过了一小时。

下一段将解释最后一条错误信息的原因。


夏令时(DST):

夏令时是一种季节性时间变化措施,在一年中的部分时间里,时钟会设置在标准时间之前。

参见https://www.timeanddate.com/time/dst/transition.html

(夏令时"、"冬令时")。

当 DST 在春季开始时,我们的时钟会提前一定的时间,通常是一小时。这意味着时钟跳过一小时。到了秋天(秋季),夏令时通常会结束,我们的时钟会再次调回标准时间。


DST 开始示例

(不存在的一小时)

在美国,DST 总是从当地时间 02:00 (凌晨 2 点)开始。当时间首次到达标准时间 1:59:59 时,时钟就会向前跳到夏令时 3:00:00。因此,从 2:00:00 到 2:59:59 这一个小时在切换的当晚是不存在的。



II.获取时区信息

1.UTC偏移和当前夏令时偏移

我们来看一个示例,说明如何获取时区名称、UTC 偏移量和当前 DST 偏移量(如果 DST 有效)。

   Print("\n========== UTC offset and current DST offset ==========");

   for(ENUM_ZONE_ID id=0; id <= MAX_ZONE_ID; id++)
     {
      CTimeZoneInfo tz(id);
      tz.RefreshTime(); // 填充当前时区信息

      PrintFormat("%-12s: GMT%+g | DST%+g", tz.Name(), tz.TimeGMTOffset()/3600., tz.TimeDaylightSavings()/3600.);
     }

输出:

   // ========== UTC 偏移和当前 DST 偏移 ==========
   // 悉尼 :GMT+11 | DST+1
   // 东京 : GMT+9 | DST+0
   // 法兰克福 : GMT+1 | DST+0
   // 伦敦 :GMT+0 | DST+0
   // 纽约 :GMT-4 | DST+1
   // UTC : GMT+0 | DST+0
   // Home :GMT+2 | DST+0
   // FXOpen-MT5 :GMT+2 | DST+0

注释:

- TimeGMTOffset() 方法返回该时区的本地时间与格林尼治标准时间之间的当前差值(以秒为单位),其中考虑了冬令时或夏令时的切换。返回的偏移量包括当前时区的 DST 调整。如果时区位于格林尼治标准时间以东(领先于格林尼治标准时间),则格林尼治标准时间偏移量为正;如果时区位于格林尼治标准时间以西(落后于格林尼治标准时间),则格林尼治标准时间偏移量为负。

-TimeDaylightSavings() 方法 返回夏令时(DST)调整值(以秒为单位),前提是在实行 DST 的时区已切换到夏令时。如果已切换到冬令(标准)时间(或时区不支持 DST),则返回 0。


2.当年的 DST 切换时间

让我们看一个示例来说明如何获取 DST 信息。

   Print("\n========== DST switch times for the current year ==========");

   datetime dst_start, dst_end;

   for(ENUM_ZONE_ID id=0; id <= MAX_ZONE_ID; id++)
     {
      CTimeZoneInfo tz(id);
      tz.RefreshTime(); // 填充当前时区信息

      //--- 仅适用于遵守夏令时的时区。
      if(tz.GetDaylightSwitchTimes(dst_start, dst_end))
        {
         PrintFormat("%-12s:  DST starts on %s |  DST ends on %s", tz.Name(), TimeToString(dst_start), TimeToString(dst_end));
        }
     }

输出:

   // ========== 当年的 DST 切换时间 ==========
   // 悉尼:夏令时于 2024.04.07 03:00 开始 | 夏令时于 2024.10.06 02:00 结束
   // 法兰克福:夏令时于 2024.03.31 02:00 开始 | 夏令时于 2024.10.27 03:00 结束
   // 伦敦:夏令时于 2024.03.31 01:00 开始 | 夏令时于 2024.10.27 02:00 结束
   // 纽约:夏令时于 2024.03.10 02:00 开始 | 夏令时于 2024.11.03 02:00 结束

3.下一次 DST 切换的时间

让我们看一个示例,了解如何获取下一个 DST 切换的时间。

   Print("\n========== Time of the next DST switch ==========");

   for(ENUM_ZONE_ID id=0; id <= MAX_ZONE_ID; id++)
     {
      CTimeZoneInfo tz(id);
      tz.RefreshTime();

      datetime nxswitch = tz.GetDaylightNextSwitch();

      //--- 仅适用于遵守夏令时的时区。
      if(nxswitch)
        {
         PrintFormat("%-12s:  Time: %s |  dstNextSwitch: %s", tz.Name(), TimeToString(tz.TimeLocal()), TimeToString(nxswitch));
        }
     }

输出: 4:

   // ========== 下一次 DST 切换的时间 ==========
   // Sydney : 时间: 2024.02.28 21:58 | dstNextSwitch: 2024.04.07 03:00
   // 法兰克福 : 时间: 2024.02.28 11:58 | dstNextSwitch: 2024.03.31 02:00
   // 伦敦 : 时间: 2024.02.28 10:58 | dstNextSwitch: 2024.03.31 01:00
   // New York : Time: 2024.02.28 05:58 | dstNextSwitch: 2024.03.10 02:00


4.DST 列表

让我们看一个示例,了解如何获取该库中所有时区在一定年份范围内的 DST 信息。

   Print("\n========== DST List ==========");

   datetime dst_start, dst_end;
   int delta_start, delta_end;  // 以秒为单位的时钟变化

   for(ENUM_ZONE_ID id=0; id <= MAX_ZONE_ID; id++)
     {
      CTimeZoneInfo timezone(id);

      PrintFormat("========= %s Summer Time (DST) =========", timezone.Name());
      for(int year=2008; year<=2030; year++)
        {
         //--- 仅适用于遵守夏令时的时区。
         if(CTimeZoneInfo::GetDaylightSwitchTimes(id, year, dst_start, dst_end))
           {
            CTimeZoneInfo::GetDaylightSwitchDeltas(id, year, delta_start, delta_end);

            PrintFormat("DST starts on %s (%+d) and ends on %s (%+d)",TimeToString(dst_start), delta_start/3600, TimeToString(dst_end), delta_end/3600);
           }
        }

     }

输出: 5:

   // ========== DST 列表 ==========
   // ========= 悉尼夏令时间(DST) =========
   // 夏令时从 2008.04.06 03:00 (-1) 开始,到 2008.10.05 02:00 (+1) 结束。
   // 夏令时从 2009.04.05 03:00 (-1) 开始,到 2009.10.04 02:00 (+1) 结束。
   // 夏令时从 2010.04.04 03:00 (-1) 开始,到 2010.10.03 02:00 (+1) 结束。
   // 夏令时从 2011.04.03 03:00 (-1) 开始,到 2011.10.02 02:00 (+1) 结束。
   // 夏令时从 2012.04.01 03:00 (-1) 开始,到 2012.10.07 02:00 (+1) 结束。
   // ...
   // ...
   // ...

5.服务器 GMT 偏移量(当前)

经纪商的 GMT 偏移量表示经纪商时间比 GMT 提前多少秒,经纪商偏移量 = TimeTradeServer() - TimeGMT()。正值表示服务器时间领先于格林尼治标准时间。 下面我们来看一个示例,说明如何获取当前的经纪商格林尼治标准时间偏移量。

   Print("\n========== Current GMT offset of the broker ========== ");

   CTimeZoneInfo broker(ZONE_ID_BROKER);
   broker.RefreshTime();

   Print("Name()          : ", broker.Name());
   Print("TimeLocal()     : ", broker.TimeLocal());  // 经纪人时间
   Print("ToString()      : ", broker.ToString());
   Print("TimeGMTOffset() : ", broker.TimeGMTOffset());

输出:

   // ========== 当前经纪人的格林尼治标准时间偏移量 ==========
   // Name() :ICMarketsSC-Demo
   // TimeLocal() : 2024.03.08 06:33:06
   // ToString() :Fri, 2024.03.08 06:33:06 GMT+2 [ICMarketsSC-Demo]
   // TimeGMTOffset() : 7200

注: TimeGMTOffset() 的一个重要说明 是,它 将返回包括 dst 修正(UTC+DST)在内的 UTC 偏移量。正值表示服务器时间比 GMT 超前(向东)


6.服务器格林尼治标准时间偏移量(历史)

服务器过去的格林尼治标准时间偏移量可以计算为服务器周在图表上出现的第一个条形图的时间与纽约时间 周日下午 5 点对应的 UTC 时间之差。 让我们看一个例子来说明如何获取经纪商过去的格林尼治标准时间偏移量。在此示例中,我们将使用图表蜡烛图的时间作为经纪商的过去时间。

   Print("\n========== Past GMT offsets of the broker (chart candles) ==========");

   datetime bartimes[];
   int copied = CopyTime(Symbol(), PERIOD_D1, D'2022.03.18', 9, bartimes);
   if(copied<=0)
      Print("CopyTime() failed.");

   for(int i =0; i < copied; i++)
     {
      datetime t = bartimes[i];

      CTimeZoneInfo broker(ZONE_ID_BROKER);
      broker.SetLocalTime(t);

      PrintFormat("bar #%i  Time: %s |  offset: %5d (GMT%+g) |  %s",
                  i+1,
                  TimeToString(broker.TimeLocal()),
                  broker.TimeGMTOffset(),
                  broker.TimeGMTOffset()/3600.0,
                  broker.ToString());
     }

输出:

   // ========== 经纪人过去的格林尼治标准时间偏移量(图表蜡烛) ==========
   // 酒吧 #1 时间: 2022.03.08 00:00 | 偏移量: 7200 (GMT+2) | 星期二, 2022.03.08 00:00:00 GMT+2 [ICMarketsSC-Demo]
   // bar #2 时间: 2022.03.09 00:00 | 偏移量: 7200 (GMT+2) | Wed, 2022.03.09 00:00:00 GMT+2 [ICMarketsSC-Demo] (ICM MarketsSC-Demo)
   // bar #3 时间: 2022.03.10 00:00 | 偏移量: 7200 (GMT+2) | 星期四, 2022.03.10 00:00:00 GMT+2 [ICMarketsSC-Demo] (中文)
   // bar #4 时间: 2022.03.11 00:00 | 偏移量: 7200 (GMT+2) | 星期五, 2022.03.11 00:00:00 GMT+2 [ICMarketsSC-Demo] (中文)
   // 酒吧 #5 时间: 2022.03.14 00:00 | 偏移量: 10800 (GMT+3) | Mon, 2022.03.14 00:00:00 GMT+3 [ICMarketsSC-Demo]
   // bar #6 时间: 2022.03.15 00:00 | 偏移量: 10800 (GMT+3) | 星期二, 2022.03.15 00:00:00 GMT+3 [ICMarketsSC-Demo]
   // bar #7 时间: 2022.03.16 00:00 | 偏移量: 10800 (GMT+3) | Wed, 2022.03.16 00:00:00 GMT+3 [ICMarketsSC-Demo] [ICMarketsSC-Demo
   // bar #8 时间: 2022.03.17 00:00 | 偏移量: 10800 (GMT+3) | Thu, 2022.03.17 00:00:00 GMT+3 [ICMarketsSC-Demo] (中文)
   // bar #9 时间: 2022.03.18 00:00 | 偏移量: 10800 (GMT+3) | 星期五, 2022.03.18 00:00:00 GMT+3 [ICMarketsSC-Demo] (中文)

第 5 条所示, 服务器已从 +2 冬令时切换到 +3 夏令时,切换时间遵循美国夏令时时间表(3 月的第 2 个星期日)。每周有 5 次 D1 蜡烛图,周六和周日没有蜡烛图。这些服务器上的时间全年始终比纽约时间早 7 小时,用 NY+7 表示。 请注意,纽约在冬季是 -5,夏季是 -4

这是代码库中第一个能够确定服务器过去格林尼治标准时间偏移量(历史格林尼治标准时间偏移量)的库。计算中采用的算法非常快速、准确,而且尽可能与不同的经纪商兼容(在大量具有不同格林尼治标准时间偏移或 DST 时间表的经纪商上进行了测试)。



III.时区转换

将当前本地时间转换为其他时区

使用ConvertLocalTime() 方法将此时区实例的设定本地时间转换为特定时区。该方法会返回给定时区的新时间。

下面我们来看一个示例,说明如何将"当前"本地时间转换为特定时区的时间。

   Print("\n========== Convert current local time in Sydney to New York ==========");

   CTimeZoneInfo sydney(ZONE_ID_SYDNEY);
   sydney.RefreshTime();

   datetime localtime = sydney.TimeLocal();
   datetime converted = sydney.ConvertLocalTime(ZONE_ID_NEWYORK);

   PrintFormat("%s | %s", TimeToString(localtime), sydney.ToString());
   PrintFormat("%s | %s", TimeToString(converted), CTimeZoneInfo::FormatTimeForPlace(converted, ZONE_ID_NEWYORK));

输出:

   // ========== 将悉尼当前当地时间转换为纽约时间 ==========
   // 2024.02.28 21:58 | Wed, 2024.02.28 21:58:50 GMT+11 [Sydney] (DST)
   // 2024.02.28 05:58 | Wed, 2024.02.28 05:58:50 GMT-5 [纽约]


将特定的本地时间转换为另一个时区

让我们看一个示例,了解如何将特定的本地时间转换为特定的时区。

   Print("\n========== Convert a specific local time in Sydney to New York ==========");

   CTimeZoneInfo sydney(ZONE_ID_SYDNEY);
   sydney.SetLocalTime(D'2016.05.21 14:47:08');

   datetime localtime = sydney.TimeLocal();
   datetime converted = sydney.ConvertLocalTime(ZONE_ID_NEWYORK);

   PrintFormat("%s | %s", TimeToString(localtime), sydney.ToString());
   PrintFormat("%s | %s", TimeToString(converted), CTimeZoneInfo::FormatTimeForPlace(converted, ZONE_ID_NEWYORK));

输出:

   // ========== 将悉尼的特定当地时间转换为纽约时间 ==========
   // 2016.05.21 14:47 | Sat, 2016.05.21 14:47:08 GMT+10 [Sydney]
   // 2016.05.21 00:47 | Sat, 2016.05.21 00:47:08 GMT-4 [New York] (DST)


将所有时区的当前本地时间转换为经纪人时间

让我们看一个示例,了解如何将所有时区的当前本地时间转换为代理时间。

   Print("\n========== Convert the current local time in all timezones to the broker time ==========");

   for(ENUM_ZONE_ID id=0; id <= MAX_ZONE_ID; id++)
     {
      datetime localtime = CTimeZoneInfo::GetCurrentTimeForPlace(id);
      datetime converted = CTimeZoneInfo::ConvertTimeForPlace(localtime, id, ZONE_ID_BROKER);

      PrintFormat("%-49s | %s", CTimeZoneInfo::FormatTimeForPlace(localtime, id), CTimeZoneInfo::FormatTimeForPlace(converted, ZONE_ID_BROKER));
     }

输出:

   // ========== 将所有时区的当前当地时间转换为经纪人时间 ==========
   // Wed, 2024.02.28 21:58:50 GMT+11 [Sydney] (DST) | Wed, 2024.02.28 12:58:50 GMT+2 [FXOpen-MT5] (DST)
   // Wed, 2024.02.28 19:58:50 GMT+9 [Tokyo] | Wed, 2024.02.28 12:58:50 GMT+2 [FXOpen-MT5]
   // 星期三, 2024.02.28 11:58:50 GMT+1 [Frankfurt] | 星期三, 2024.02.28 12:58:50 GMT+2 [FXOpen-MT5]
   // 周三, 2024.02.28 10:58:50 GMT+0 [London] | 周三, 2024.02.28 12:58:50 GMT+2 [FXOpen-MT5]
   // 周三, 2024.02.28 05:58:50 GMT-5 [New York] | 周三, 2024.02.28 12:58:50 GMT+2 [FXOpen-MT5]
   // 星期三, 2024.02.28 10:58:50 GMT+0 [UTC] | 星期三, 2024.02.28 12:58:50 GMT+2 [FXOpen-MT5]
   // 周三, 2024.02.28 12:58:50 GMT+2 [Home] | 周三, 2024.02.28 12:58:50 GMT+2 [FXOpen-MT5]
   //周三, 2024.02.28 12:58:50 GMT+2 [FXOpen-MT5] | 周三, 2024.02.28 12:58:50 GMT+2 [FXOpen-MT5]



IV.使用本地会话时间

A.CTimeZoneInfo 类

请注意,使用父CTimeZoneInfo 类而不是CSessionHours 类并不可取,因为它需要更多编码,因此容易出错。让我们看一个示例,说明如何获取所有时区的外汇交易时段时间,并将其转换为经纪商的时间。

   Print("\n======= Local Session Hours (CTimeZoneInfo Class) =======");

   const ENUM_ZONE_ID ids[] = {ZONE_ID_SYDNEY, ZONE_ID_TOKYO, ZONE_ID_FRANKFURT, ZONE_ID_LONDON, ZONE_ID_NEWYORK};

   for(int i = 0; i < ArraySize(ids); i++)
     {
      ENUM_ZONE_ID id = ids[i];

      CTimeZoneInfo tz(id);
      tz.RefreshTime();

      datetime localtime = tz.TimeLocal();

      //--- 将会议时间设置为当地时间上午 8:00 - 下午 5:00
      datetime beginlocal = StringToTime(TimeToString(localtime, TIME_DATE) + " " + "08:00");
      datetime endlocal   = StringToTime(TimeToString(localtime, TIME_DATE) + " " + "17:00");

      //--- 转换为经纪人时间
      tz.SetLocalTime(beginlocal);
      datetime beginbroker = tz.ConvertLocalTime(ZONE_ID_BROKER);

      tz.SetLocalTime(endlocal);
      datetime endbroker = tz.ConvertLocalTime(ZONE_ID_BROKER);

      //--- 当地时区的星期几
      MqlDateTime st;
      TimeToStruct(localtime, st);
      int dow = st.day_of_week;

      //string state_str = ((dow != SATURDAY && dow != SUNDAY) && (localtime >= beginlocal && localtime < endlocal)) ?"open" : "closed";
      string state_str = ((dow != SATURDAY && dow != SUNDAY) && (TimeTradeServer() >= beginbroker && TimeTradeServer() < endbroker)) ? "open" : "closed";

      PrintFormat("%-12s:  %s |  %s  [session %s]", tz.Name(), CTimeZoneInfo::FormatTimeForPlace(beginbroker, ZONE_ID_BROKER), CTimeZoneInfo::FormatTimeForPlace(endbroker, ZONE_ID_BROKER), state_str);
     }

   Print("-----------------------------------");
   Print("broker time :  ", TimeTradeServer());
   Print("broker time :  ", CTimeZoneInfo::FormatTimeForPlace(TimeTradeServer(), ZONE_ID_BROKER));

输出:

   // ======= 本地会话时间(CTimeZoneInfo 类) =======
   // Sydney : Wed, 2024.02.28 23:00:00 GMT+2 [FXOpen-MT5] | Thu, 2024.02.29 08:00:00 GMT+2 [FXOpen-MT5] [session closed] (关闭会议
   // 东京 : 星期三, 2024.02.28 01:00:00 GMT+2 [FXOpen-MT5] | 星期三, 2024.02.28 10:00:00 GMT+2 [FXOpen-MT5] [会议闭幕]
   // 法兰克福 : 星期三, 2024.02.28 09:00:00 GMT+2 [FXOpen-MT5] | 星期三, 2024.02.28 18:00:00 GMT+2 [FXOpen-MT5] [时段开放]
   // 伦敦 : 星期三, 2024.02.28 10:00:00 GMT+2 [FXOpen-MT5] | 星期三, 2024.02.28 19:00:00 GMT+2 [FXOpen-MT5] [时段开放]
   // 纽约 : 星期三, 2024.02.28 15:00:00 GMT+2 [FXOpen-MT5] | 星期四, 2024.02.29 00:00:00 GMT+2 [FXOpen-MT5] [session open] [时段开放
   // -----------------------------------
   // 经纪人时间 : 2024.02.28 15:32:30
   //经纪商时间 : Wed, 2024.02.28 15:32:30 GMT+2 [FXOpen-MT5]



B.CSessionHours 类

目的:用于访问指定地点的本地交易时段时间的类。

派生自CTimeZoneInfo 类。

:对于新的CSessionHours 对象,默认时段设置为当地时间上午 8:00 - 下午 5:00。可以根据需要覆盖这些默认值。


使用 CSessionHours 对象

让我们来看一个如何使用该对象的示例。

   Print("\n========== Working with CSessionHours Objects  ==========");

   CSessionHours tz(ZONE_ID_SYDNEY);
   tz.RefreshTime(); // 填充时区和会话信息

   //----来自父级
   Print("Name()                : ", tz.Name());
   Print("TimeUTC()             : ", tz.TimeUTC());
   Print("TimeLocal()           : ", tz.TimeLocal());
   Print("ToString()            : ", tz.ToString());
   //--- 来自班级
   Print("BeginLocalTime()      : ", tz.BeginLocalTime());
   Print("EndLocalTime()        : ", tz.EndLocalTime());
   Print("CheckLocalSession()   : ", tz.CheckLocalSession());
   Print("SecRemainingSession() : ", tz.SecRemainingSession());
   Print("SecondsToString()     : ", CSessionHours::SecondsToString(tz.SecRemainingSession()));

输出:

   // ========== 处理 CSessionHours 对象 ==========
   // Name() :悉尼
   // TimeUTC() : 2024.02.28 10:58:50
   // TimeLocal() : 2024.02.28 21:58:50
   // ToString() :Wed, 2024.02.28 21:58:50 GMT+11 [Sydney] (DST)
   // BeginLocalTime() : 2024.02.28 08:00:00
   // EndLocalTime() : 2024.02.28 17:00:00
   // CheckLocalSession() : false
   // SecRemainingSession() :0
   // SecondsToString() : 00:00:00


本地会话时间

CSessionHours 以更少的代码提供了更多的功能。我们来看一个示例,说明如何使用CSessionHours 类获取所有时区的外汇交易时段,并将其转换为经纪商时间。请注意,转换为经纪商时间是一个可选步骤, 在检查每个时段的开始和结束时间时 并不需要

   Print("\n======= Local Session Hours (CSessionHours Class) =======");

   const ENUM_ZONE_ID ids[] = {ZONE_ID_SYDNEY, ZONE_ID_TOKYO, ZONE_ID_FRANKFURT, ZONE_ID_LONDON, ZONE_ID_NEWYORK};

   for(int i = 0; i < ArraySize(ids); i++)
     {
      ENUM_ZONE_ID id = ids[i];

      CSessionHours tz(id);
      tz.RefreshTime();

      //--- 默认会话时间设置为当地时间上午 8:00 - 下午 5:00
      datetime beginlocal = tz.BeginLocalTime();
      datetime endlocal   = tz.EndLocalTime();

      //--- 转换为经纪人时间
      datetime beginbroker = CTimeZoneInfo::ConvertTimeForPlace(beginlocal, id, ZONE_ID_BROKER);
      datetime endbroker = CTimeZoneInfo::ConvertTimeForPlace(endlocal, id, ZONE_ID_BROKER);

      string state_str = tz.CheckLocalSession() ? "open, ends in " + CSessionHours::SecondsToString(tz.SecRemainingSession()) : "closed";

      PrintFormat("%-12s:  %s |  %s  [session %s]", tz.Name(), CTimeZoneInfo::FormatTimeForPlace(beginbroker, ZONE_ID_BROKER), CTimeZoneInfo::FormatTimeForPlace(endbroker, ZONE_ID_BROKER), state_str);
     }

   Print("-----------------------------------");
   Print("broker time :  ", TimeTradeServer());
   Print("broker time :  ", CTimeZoneInfo::FormatTimeForPlace(TimeTradeServer(), ZONE_ID_BROKER));
   Print("Fx close    :  ", CTimeZoneInfo::FormatTimeForPlace(CSessionHours::ForexCloseTime(), ZONE_ID_BROKER));
   int sec = CSessionHours::SecRemainingForex();
   Print("closes in   :  ", sec, " sec = ", CSessionHours::SecondsToString(sec));

输出:

   // ======= 本地会话时间(CSessionHours 类) =======
   // Sydney : Wed, 2024.02.28 23:00:00 GMT+2 [FXOpen-MT5] | Thu, 2024.02.29 08:00:00 GMT+2 [FXOpen-MT5] [session closed] (关闭会议
   // 东京 : 星期三, 2024.02.28 01:00:00 GMT+2 [FXOpen-MT5] | 星期三, 2024.02.28 10:00:00 GMT+2 [FXOpen-MT5] [会议闭幕]
   // 法兰克福 : 星期三, 2024.02.28 09:00:00 GMT+2 [FXOpen-MT5] | 星期三, 2024.02.28 18:00:00 GMT+2 [FXOpen-MT5] [时段开放,02:27:29结束]
   // 伦敦 : Wed, 2024.02.28 10:00:00 GMT+2 [FXOpen-MT5] | Wed, 2024.02.28 19:00:00 GMT+2 [FXOpen-MT5] [时段开放,03:27:29结束]
   // 纽约 : 星期三, 2024.02.28 15:00:00 GMT+2 [FXOpen-MT5] | 星期四, 2024.02.29 00:00:00 GMT+2 [FXOpen-MT5] [时段开放,08:27:29结束]
   // -----------------------------------
   // 经纪人时间 : 2024.02.28 15:32:30
   //经纪商时间 : Wed, 2024.02.28 15:32:30 GMT+2 [FXOpen-MT5]
   // Fx close : Sat, 2024.03.02 00:00:00 GMT+2 [FXOpen-MT5]
   // 关闭时间 : 203249 秒 = 2d 08:27:29


如何覆盖默认的本地会话时间?

让我们看一个示例,说明如何在CSessionHours 类中覆盖默认会话时间。

   Print("\n=========== Override the default session hours ===========");

   CSessionHours frankfurt(ZONE_ID_FRANKFURT);

   // 更改默认会话时间
   frankfurt.BeginLocalTime(9, 0);
   frankfurt.EndLocalTime(19, 0);

   frankfurt.RefreshTime(); // 填充新的会话时间

   datetime beginlocal = frankfurt.BeginLocalTime();
   datetime endlocal   = frankfurt.EndLocalTime();

   PrintFormat("new session hours  :  %s | %s", CTimeZoneInfo::FormatTimeForPlace(beginlocal, ZONE_ID_FRANKFURT), CTimeZoneInfo::FormatTimeForPlace(endlocal, ZONE_ID_FRANKFURT));
   PrintFormat("current local time :  %s", frankfurt.ToString());

输出:

   // =========== 覆盖默认会话时间 ===========
   // 新的会议时间:2024.02.28 星期三 09:00:00 GMT+1 [法兰克福] | 2024.02.28 星期三 19:00:00 GMT+1 [法兰克福]
   // 当前当地时间 : Wed, 2024.02.28 11:58:50 GMT+1 [Frankfurt] (法兰克福


如何在周末检查平仓?

SecRemainingForex() 静态方法将返回本周外汇市场收盘前的剩余时间(以秒为单位)。该方法应在OnTick() 事件处理程序中调用 如果周末前没有滴答声, 最好在 OnTimer() 事件处理程序中调用,以重复检查平仓条件。让我们看一个示例,说明如何检查周末的平仓情况。

   Print("\n======= Check For Closing Positions at Weekend =======");

   int InpHours   = 2;   // 周末前的几个小时
   int InpMinutes = 30;  // 周末前几分钟

   int sec = CSessionHours::SecRemainingForex();
   PrintFormat("Time remaining till the weekend : %s", CSessionHours::SecondsToString(sec));
   PrintFormat("Close all if remaining time becomes %s or less.", CSessionHours::SecondsToString(InpHours * 3600 + InpMinutes * 60));

   // 检查剩余时间是否已达到目标
   if(sec <= InpHours * 3600 + InpMinutes * 60)
     {
      // CloseAll();
     }

或者,也可以使用绝对时间检查前一个条件:

   // 检查经纪人的时间是否已达到目标
   if(TimeTradeServer() >= CSessionHours::ForexCloseTime() - (InpHours * 3600 + InpMinutes * 60))
     {
      // CloseAll();
     }

输出:

   // ======= 检查周末 ======= 的关闭职位
   // 距周末剩余时间 : 3d 03:32:27
   // 如果剩余时间变为 02:30:00 或更短,则关闭所有系统。




周末 - 经纪人的时区和 DST 时间表

外汇市场于纽约时间周日 17:00 开盘(冬季为 GMT-5,夏季为 GMT-4),周五同一时间收盘。 纽约时间的开盘时间对应冬季的周日 10:00(夏季为周日 09:00)。外汇交易的收盘时间为周五, 冬季为10:00 PM UTC(夏季为 09:00PM UTC)。黄金和白银现货市场通常在一小时后开始。链接

每个外汇经纪商都有自己的时区和服务器时间。因此,不同经纪商的交易周开始时间(H1蜡烛图)也不尽相同,旧金山经纪商服务器时间周日下午 02:00(GMT-8),悉尼经纪商服务器时间周一上午 09:00(GMT+11)。交易周的结束时间也各不相同,从服务器时间周五下午 02:00服务器时间周六上午 09:00。

各经纪商可自由选择夏令时间 (DST)。该时区的夏令时不一定相同。有时,他们会混合使用欧盟时区和美国夏令时,而不是欧盟夏令时。对于不遵循美国时间表的经纪商来说,同一经纪商的服务器时间在一周的开始(和结束)时间上全年会有+/- 1小时的差异。 ForexCloseTime() 方法通过将纽约市周五17:00的收盘时间转换为经纪商时间来处理这些经纪商之间和经纪商内部的差异,同时考虑 到时间偏移和DST,从而提供准确的结果。

因此,使用+2 时区(美国夏季+3 时区)意味着每周有五根 D1 蜡烛。全年的周六和周日都没有蜡烛。简单地说, 这些服务器上的时间总是比纽约早 7 小时,表示为 NY+7。 这是目前最常见的设置,但也有很多不常见的变化。



示例指标 TestIndi.mq5


iForexSessions - MetaTrader 5 的指标

突出显示外汇市场时段

在此获取https://www.mql5.com/zh/code/48842


链接

世界时钟: https://www.timeanddate.com/worldclock/

时区转换器: https://www.timeanddate.com/worldclock/converter-classic.html


更新

2024.03.01 - v.1.40 :删除 CTimeZoneInfo 类(测试时使用)中的冗余代码,为 CSessionHours 类添加更多方法,更新 TestIndi.mq5 以反映新变化。

2024.03.03 - v.1.45 :更新了 "处理本地会话时间 - CTimeZoneInfo 类 "的示例代码。

2024.03.08 - v.1.50 : 在 CTimeZoneInfo 类中添加了两个内部方法HistoryBrokerOffsetFirstBarOfWeek。处理过去的服务器时间(UTC 偏移、文本格式、转换等)。

2024.03.15 - v.1.56 : 添加脚本 "SydneySession_Script.mq5",以显示悉尼全年的交易时段是如何波动的。

2024.03.30 - v.1.65 : 修正经纪商 GMT 偏移量。目前,该库只扫描黄金图表上的 H1 条,因为在我测试过的所有经纪商中,黄金图表的开始时间最准确。

2024.04.01 - v.1.67 :修正了在交易周第一小时计算经纪商格林威治标准时间偏移的潜在问题。

2024.04.03 - v.1.70:将经纪商格林威治标准时间偏移量缓存到哈希图中,以便更快地检索(例如从指标中检索)。经纪商偏移缓存将包含每个交易周的一个条目。

2024.04.08 - v.1.72 : 库性能至少提高 2-3 倍。现在在GetNthSunday 方法 中使用 StructToTime 而不是 StringToTime。

2024.04.09 - v.1.75 : 修复了圣诞节期间格林威治标准时间+0经纪商在计算经纪商格林威治标准时间偏移量时可能出现的问题。

2024.04.11 - v.1.77 : 加速GetDaylightSwitchTimes 方法 。现在使用静态数组记忆当前年份的切换时间。

2024.04.12 - v.1.80 : 修正了在不提供黄金交易的经纪商上计算经纪商 GMT 偏移的问题。

2024.04.15 - v.1.82 : 在 CTimeZoneInfo 类中添加了SetCustomTimeZone 方法,您可以使用该方法以指定名称、GMT 偏移量和 DST 标识符配置内置的自定义时区。可通过 ZONE_ID_CUSTOM 访问自定义时区。

2024.04.16 - v.1.85 : 以更优化的 GetMonthTime 方法取代 GetNthSunday 内部方法。

2024.04.17 - v.1.87 :用更优化的GetYear 方法取代TimeYear 内部方法。

2024.04.18 - v.1.88 :添加CreateDateTime 内部方法,从日期组件(年、月、日)构建日期时间值。这比调用 StructToTime 函数快 100-120 倍。

2024.10.21 - v.1.90 : 改进了黄金符号的检测,可回退至欧元兑美元符号。

2024.10.22 - v.1.93 : 在周末实时交易中更快确定服务器的格林威治标准时间偏移。

2024.10.26 - v.1.95 :新增两个静态方法:TimeGMTOffset()TimeDaylightSavings ()。将HistoryBrokerOffset() 方法更名为TimeServerGMTOffset()。

2024.10.28 - v.1.97 :将所有处理时间的宏转换为函数,以避免在宏体中重复评估参数。在其他行中清理了更多代码。

2024.10.30 - v.1.98 :修正了某些经纪商从 XAUEUR 报价中错误估算 GMT 偏移量的问题。

2024.11.01 - v.1.99 :增加了一个选项,可关闭黄金符号的默认加载,以估算服务器的TZ/DST。使用 "false "调用CTimeZoneInfo:: SetUsingGoldSymbol() 可使用当前图表的符号。

2024.11.13 - v.2.00 : 改进了在线服务器 TZ/DST 的估算,以及在策略中的估算(不再需要 TimeGMT 库)。构造函数接受地点和时间参数。新增用于处理日期类型数据的公共方法。改进了错误处理和调试支持。

2024.11.14 - v.2.02 :修正了尝试通过服务器时区对象访问 XAUUSD,H1 历史报价时的错误 ERR_HISTORY_NOT_FOUND (4401)。

2024.11.17 - v.2.03 : 小错误修正。

2024.11.23 - v.2.04 : 小改进和错误修复。

2024.12.05 - v.2.05 :新增静态方法 DaylightSavingsSupported(placeId)。

2024.12.12 - v.2.10 : 改进 HistoryServerGMTOffset() 和 HistoryServerDaylightSavings() 函数的性能,以及其他代码小改动。

2024.12.14 - v.2.11 : 提高了 FindSymbol() 函数的性能。

2024.12.17 - v.2.12 :进一步优化 HistoryServerGMTOffset() 和 HistoryServerDaylightSavings() 函数。

2024.12.24 - v.2.13 : 修正 HistoryServerGMTOffset() 和 HistoryServerDaylightSavings() 函数中的潜在问题。

2025.01.12 - v.2.15 : 修正了 HistoryServerDaylightSavings() 在策略测试器中搜索报价历史早于加载历史的问题。

2025.10.13 - v.2.17 : 小改进和错误修复。


由MetaQuotes Ltd译自英文
原代码: https://www.mql5.com/en/code/48419

CVD (Cumulative Volume Delta) CVD (Cumulative Volume Delta)

MT5 的轻量级 CVD(累计成交量Δ) - 基于 M1,以蜡烛图显示买入/卖出压力,可选择重置。

错误描述 - 更新资料库 错误描述 - 更新资料库

该库是 MetaQuotes 发布的 ErrorDescription.mqh 库的更新版,其中包含一些功能。