Forex trading, timezones and daylight savings

It is important to take daylight savings and time zones into account when Forex trading.

Local time differences can change as much as four times throughout the year between two countries.

Each country can have specific rules that control when daylight savings starts and ends.

Below are the current rules of daylight savings for the four major Forex trading exchanges: London, New York, Sydney and Tokyo.

As a proof of concept I translated these rules to an Expert Advisor that can be used for backtesting with MetaTrader 5.

 
Timezones, daylight saving rules and trading hours for major cities.


London
Time zone:
UTC +0
Daylight savings:
From 1 a.m. (ST) on the last Sunday in March till 2 a.m. (DT) on the last Sunday in October, UTC +1.
Local trading hours:
From 8 a.m. till 5 p.m.

New York
Time zone:
UTC -5
Daylight savings:
From 2 a.m. (ST) on the second Sunday in March till 2 a.m. (DT) on the first Sunday in November, UTC -4.
Local trading hours:
From 8 a.m. till 5 p.m.

Sydney
Time zone:
UTC +10
Daylight savings:
From 2 a.m. (ST) on the first Sunday in October till 3 a.m. (DT) on the first Sunday in April, UTC -11.
Local trading hours:
From 8 a.m. till 5 p.m.

Tokyo
Time zone:
UTC +9
Daylight savings:
none
Local trading hours:
From 8 a.m. till 5 p.m.

 
MetaTrader and Daylight Savings
Is there a way to make an Expert Advisor take local daylight savings into account?

The candlestick times and ticks in Metatrader 5 are that of the broker which supplies the prices. Sometimes you might like to focus on a specific time related to a session of a particular exchange. But due to daylight savings, this time, relative to your broker's time, will vary throughout the year.

Some solutions rely on using your local PC time to account for daylight savings, but this is not possible for back testing strategies.

Below is the code of an Expert Advisor I wrote as a solution to take daylight savings and time zones into account. It outputs the local time of London, New York, Sydney and Tokyo. It works no matter what the time, date or year is (as long as the broker's time isn't also using daylight savings).

It applies the rules above to each specific city and converts the broker time into a local time of the city, including the daylight savings changes.

It is just a Proof of Concept. It doesn't do anything except display the local times as a comment.

I'm just learning to use MetaTrader 5 and MQL5, so the code might not be written according to best practices.

Feel free to modify it for your personal needs.

 


//+------------------------------------------------------------------+
//|                                          PoC time converter.mq5  |
//|                                       Aard Jan van Musschenbroek |
//|                   https://globaltimekeeper.com/forex-trading.php |
//+------------------------------------------------------------------+


/*
Introduction:
This EA for Metatrader 5 is a Proof of Concept for converting the broker time to local times in London, New York, Sydney and Tokyo.
The local times take daylight savings into account.
The local times are also valid during back testing, and future dates.

The rules for daylight savings are those currently used in 2018.
They may have been different in the past, and they may change in the future.
So keep back testing restricted to the near past. And check the rules every year if they still apply.

This EA doesn't do anything except save the local times in variables and show them as a comment.

To use:  Fill in your broker timezone UTC offset (BrokerOffsetHours).


*/

#property copyright "Aard Jan van Musschenbroek"
#property link      "https://globaltimekeeper.com/forex-trading.php"
#property version   "1.00"

input int BrokerOffsetHours = 1;  // Fill in your broker timezone UTC offset (only standard time - no daylight savings time)

datetime LondonTime;
datetime NewYorkTime;
datetime SydneyTime;
datetime TokyoTime;
datetime TimeNow;

void OnTick()
  {
      ConvertTime();
      
      Comment("Broker time: "+TimeToString(TimeNow)
      +"\nLondonTime: "+TimeToString(LondonTime)
      +"\nNewYorkTime: "+TimeToString(NewYorkTime)
      +"\nSydneyTime: "+TimeToString(SydneyTime)
      +"\nTokyoTime: "+TimeToString(TokyoTime)
      
      );

  }


void ConvertTime()
{
     
      TimeNow = TimeCurrent();  //Broker time
      
      datetime TimeNowUTC = TimeNow - (BrokerOffsetHours * 60 * 60); // Broker time back to UTC
      
      
      MqlDateTime TimeNowStruct;
      TimeToStruct(TimeCurrent(),TimeNowStruct);
      
      string YearNow = IntegerToString(TimeNowStruct.year);
      
      int DaylightStartDayOfMonth;
      int DaylightEndDayOfMonth;
      
      
      //London, UTC +0
      //Daylight savings:	From 1 a.m. (ST) on the last Sunday in March till 1 a.m. (ST) on the last Sunday in October, UTC +1.
      
      int StandardOffsetLondon = 0;
      
      datetime LastDayInMarch=StringToTime(YearNow+".03.31 00:00:00");
      MqlDateTime LastDayInMarchStruct;
      TimeToStruct(LastDayInMarch,LastDayInMarchStruct);
      DaylightStartDayOfMonth = 31;
      if (LastDayInMarchStruct.day_of_week != 7)  DaylightStartDayOfMonth = 31 - LastDayInMarchStruct.day_of_week;
      datetime DaylightStartDateLondon = StringToTime(YearNow+".03."+IntegerToString(DaylightStartDayOfMonth,2,'0')+" 01:00:00");
      
      
      datetime LastDayInOctober=StringToTime(YearNow+".10.31 00:00:00");
      MqlDateTime LastDayInOctoberStruct;
      TimeToStruct(LastDayInOctober,LastDayInOctoberStruct);
      DaylightEndDayOfMonth = 31;
      if (LastDayInOctoberStruct.day_of_week != 7)  DaylightEndDayOfMonth = 31 - LastDayInOctoberStruct.day_of_week;
      datetime DaylightEndDateLondon = StringToTime(YearNow+".10."+IntegerToString(DaylightEndDayOfMonth,2,'0')+" 01:00:00");     
      
  
  
      //New York, UTC -5
      //Daylight savings:	From 2 a.m. (ST) on the second Sunday in March till 3 a.m. (ST) on the first Sunday in November, UTC -4.
  
      int StandardOffsetNewYork = -5;
      
      datetime FirstDayInMarch=StringToTime(YearNow+".03.01 00:00:00");
      MqlDateTime FirstDayInMarchStruct;
      TimeToStruct(FirstDayInMarch,FirstDayInMarchStruct);
      DaylightStartDayOfMonth = 8 + (7-FirstDayInMarchStruct.day_of_week);
      datetime DaylightStartDateNewYork = StringToTime(YearNow+".03."+IntegerToString(DaylightStartDayOfMonth,2,'0')+" 02:00:00");
  
      datetime FirstDayInNovember=StringToTime(YearNow+".11.01 00:00:00");
      MqlDateTime FirstDayInNovemberStruct;
      TimeToStruct(FirstDayInNovember,FirstDayInNovemberStruct);
      DaylightEndDayOfMonth = 1 + (7-FirstDayInNovemberStruct.day_of_week);
      datetime DaylightEndDateNewYork = StringToTime(YearNow+".11."+IntegerToString(DaylightEndDayOfMonth,2,'0')+" 03:00:00"); 
  
 
 
      //Sydney, UTC +10
      //Daylight savings:	From 2 a.m. (ST) on the first Sunday in October till 2 a.m. (ST) on the first Sunday in April, UTC -11.
      
      int StandardOffsetSydney = 10;
      
      datetime FirstDayInOctober=StringToTime(YearNow+".10.01 00:00:00");
      MqlDateTime FirstDayInOctoberStruct;
      TimeToStruct(FirstDayInOctober,FirstDayInOctoberStruct);
      DaylightStartDayOfMonth = 1 + (7-FirstDayInOctoberStruct.day_of_week);
      datetime DaylightStartDateSydney = StringToTime(YearNow+".10."+IntegerToString(DaylightStartDayOfMonth,2,'0')+" 02:00:00");
 
      datetime FirstDayInApril=StringToTime(YearNow+".04.01 00:00:00");
      MqlDateTime FirstDayInAprilStruct;
      TimeToStruct(FirstDayInApril,FirstDayInAprilStruct);
      DaylightEndDayOfMonth = 1 + (7-FirstDayInAprilStruct.day_of_week);
      datetime DaylightEndDateSydney = StringToTime(YearNow+".04."+IntegerToString(DaylightEndDayOfMonth,2,'0')+" 02:00:00"); 
      
      
  
      // Tokyo, UTC +9
      //Daylight savings:	None
      
      int StandardOffsetTokyo = 9;
      
      
      
  
      // LondonTime
      LondonTime = TimeNowUTC + (StandardOffsetLondon * 60 * 60);
      if(TimeNowUTC > DaylightStartDateLondon && TimeNowUTC < DaylightEndDateLondon) LondonTime = LondonTime + 3600; // add 1 hour for daylight savings
  

       // NewYorkTime
      NewYorkTime = TimeNowUTC + (StandardOffsetNewYork * 60 * 60);
      if(TimeNowUTC > DaylightStartDateNewYork && TimeNowUTC < DaylightEndDateNewYork) NewYorkTime = NewYorkTime + 3600; // add 1 hour for daylight savings
 
      // SydneyTime
      SydneyTime = TimeNowUTC + (StandardOffsetSydney * 60 * 60);
      if(TimeNowUTC > DaylightStartDateSydney || TimeNowUTC < DaylightEndDateSydney) SydneyTime = SydneyTime + 3600; // add 1 hour for daylight savings. Note Or instead of And for southern hemisphere
  
  
      // TokyoTime
      TokyoTime = TimeNowUTC + (StandardOffsetTokyo * 60 * 60);



// This comment is redundant because the comment in the OnTick function will be shown.
// This is only for troubleshooting.
// To see the comment, remove the one in the OnTick function
 
      Comment("Time broker(current): "+TimeToString(TimeNow ,TIME_MINUTES)
      +"\nDaylight startdate London: "+TimeToString(DaylightStartDateLondon)
      +"\nDaylight enddate London: "+TimeToString(DaylightEndDateLondon)
      +"\nDaylight startdate New York: "+TimeToString(DaylightStartDateNewYork)
      +"\nDaylight enddate New York: "+TimeToString(DaylightEndDateNewYork)
      +"\nDaylight startdate Sydney: "+TimeToString(DaylightStartDateSydney)
      +"\nDaylight enddate Sydney: "+TimeToString(DaylightEndDateSydney)
      +"\n"
      +"\nLondonTime: "+TimeToString(LondonTime)
      +"\nNewYorkTime: "+TimeToString(NewYorkTime)
      +"\nSydneyTime: "+TimeToString(SydneyTime)
      +"\nTokyoTime: "+TimeToString(TokyoTime)
      
      );

}