Timezone best practice?

 

Hi, what is the best way for managing timezones eg to consistently get iOpen(Symbol(),PERIOD_D1,0) for GMT.

I think this is a big design error in the MQL4 history/charting.. sending date information with variable timezones, and no way to query the timezone the broker is using?

Is this why people are creating offline charts?

 

iOpen( D1) is ALWAYS your broker's timezone.

Convert a GMT time to server timezone. Use iBarShift (H1 or smaller) to get the corresponding broker's bar.

My code can automatically calculate the broker's timezone.

 

Thanks WHRoeder, this uses the LocalTimeGMT function to get local GMT time and then calculates the offset from that right?

What do we do during backtesting ? hardcode the offset?

 
I use the same code (Thank WHR!) and it's great. Just need to make sure your computer time is set right and I guess it also wouldn't work with backtesting.
 
In init() what part was not clear?
   if(Srvr_To_UTC_Auto){
      if                  ( IsTesting() ){      Srvr_To_UTC_Auto = false;
         AlertMe( "Warning, use manual UTCoffsets only on backtest.",
            " Automatic UTC offset calculation disabled." );                    }
 
ydrol: Hi, what is the best way for managing timezones eg to consistently get iOpen(Symbol(),PERIOD_D1,0) for GMT.
What I'm doing is creating a D1 chart in the EA with whatever TZ is best
   while(true){   // Create all daily bars.
      datetime       next     = TimeSrvToTZ(BODsrv + HR2400),
                  nextAdj  = DateOfDay(next - offset) + offset;
      nextD1Adj   = TimeTzToSrv(nextAdj); // Next adjusted day start (estimated)
      int      iEOD  = iGetShift(nextD1Adj); // Find nearest bar.
      if(Time[iEOD] == nextD1Adj)   iEOD++;  // Exact, make iEOD inclusive.
      int      iHH   = iGetHighest(iBOD+1, iEOD),
               iLL   = iGetLowest( iBOD+1, iEOD);
      d1_acr[iCB][ACR_TIME]   = BODsrv;
      d1_acr[iCB][ACR_OPEN]   =  Open[iBOD];
      d1_acr[iCB][ACR_CLOSE]  = Close[iEOD];
      d1_acr[iCB][ACR_HIGH]   =  High[iHH];
      d1_acr[iCB][ACR_LOW]    =   Low[iLL];
      if(iEOD == iCB)   break;   // Update complete.
      iBOD = iEOD - 1;           BODsrv = Time[iBOD];
      int      nBars = ArrayRange(d1_acr,0);
      if( !ResizeBuffer(d1_acr, nBars + 1) ) return;
   }  // Create all daily bars.

See attached and my code

Example: NewYork market close 4PM ET (opens 6PM Sun) Thus d1_acr is:

extern int     TZselect_Brk0_UTC1_NY2     =  2;
extern int     AnalyzeDays_OffsetHrs      =  16;
//[6420] 2009.01.04 23:00:00 WHRea35: tz=2 day[12]srv={2008.12.16 21:00} O=1.41300 H=1.44340 L=1.39970 C=1.43880 My Broker is GMT
//[6420] 2009.01.04 23:00:00 WHRea35: tz=2 day[11]srv={2008.12.17 21:00} O=1.43880 H=1.47160 L=1.41840 C=1.42300
//[6420] 2009.01.04 23:00:00 WHRea35: tz=2 day[10]srv={2008.12.18 21:00} O=1.42310 H=1.43070 L=1.38230 C=1.39140 Friday
//[6420] 2009.01.04 23:00:00 WHRea35: tz=2 day[09]srv={2008.12.21 23:00} O=1.39200 H=1.41220 L=1.39010 C=1.39430 Sunday
//[6420] 2009.01.04 23:00:00 WHRea35: tz=2 day[08]srv={2008.12.22 21:00} O=1.39440 H=1.40180 L=1.39180 C=1.39570
//[6420] 2009.01.04 23:00:00 WHRea35: tz=2 day[07]srv={2008.12.23 21:00} O=1.39560 H=1.40160 L=1.39120 C=1.40000
//[6420] 2009.01.04 23:00:00 WHRea35: tz=2 day[06]srv={2008.12.24 21:00} O=1.40000 H=1.40150 L=1.40000 C=1.40140
//[6420] 2009.01.04 23:00:00 WHRea35: tz=2 day[05]srv={2008.12.26 00:15} O=1.40140 H=1.41160 L=1.39870 C=1.40550 Closed Xmas
//[6420] 2009.01.04 23:00:00 WHRea35: tz=2 day[04]srv={2008.12.28 23:00} O=1.40750 H=1.43600 L=1.39670 C=1.39710 Sunday
//[6420] 2009.01.04 23:00:00 WHRea35: tz=2 day[03]srv={2008.12.29 21:00} O=1.39700 H=1.42180 L=1.39150 C=1.40720
//[6420] 2009.01.04 23:00:00 WHRea35: tz=2 day[02]srv={2008.12.30 21:00} O=1.40720 H=1.41440 L=1.38500 C=1.39500
//[6420] 2009.01.04 23:00:00 WHRea35: tz=2 day[01]srv={2009.01.01 22:00} O=1.40310 H=1.40560 L=1.38380 C=1.38460
//[6420] 2009.01.04 23:00:00 WHRea35: tz=2 day[00]srv={2009.01.04 23:00} O=1.38840 H=1.38840 L=1.38840 C=1.38840
Files:
 

Thanks, I think this is the best approach

- Auto Calculate offset in forward/live mode

- Use hard coded offset in back testing.

- Build and manage a custom D1 array, updating it every 24 hours.


For backtesting, I did try to be clever and compute the offset based on chart volume but it was often 30 minutes out, and certainly not best practice/robust as a national holiday would affect volumes :)

I may have another stab at it out of curiosity! Another "hack" (again not best practice/robust) would be to pre-calculate get the times of the highs for some reference dates, then at runtime use iTime(iHighest(, H1,) to determine offset from data.

Again, a bit messy and requires that the H1 data is loaded for the reference Symbol and timeframe.

Now I'm using a hardcoded table mapping 'AccountCompany() to a timezone/offset' - eg "Alpari (UK) Ltd." = GMT+3 in summer!

 

FWIW Another way to get the local GMT time from windows / PC clock: (this is not modelled)


datetime localGMTTime() {
    static string name = "";
    if (name == "") name = WindowExpertName()+"#time";
    datetime gmt = GlobalVariableSet(name,0);
    GlobalVariableDel(name);
    return(gmt);
}
 

I've had another stab at auto-timezone for backtesting.

I used TickStory to create a M30 EURUSD file with GMT offset, then extracted the candle times for each days high. (from 2003 to 2013) This is my reference file. (86K)

At start up, and once a week(modelled time), I check the MT4 EURUSD M30 history against a few reference highs, looking for the same candle, and using the time difference to calculate the GMT offset.


The arguments for doing this:

pro1. You can back test across timezones and the offset will change automatically if the broker uses DST - This could also be achieved by simply changing the offset when the modelled time indicates the broker would have switched to/from DST, but using the reference file saves a lot TZ calculations

pro2. If a broker has changed timezone recently then their offsets are not consistent across all data (eg Alpari UK have varying timezones across their historical data).


There are two (maybe three) good arguments against doing this...

con1. You can enter GMT offset manual anyway - very reliable (for a given set of data, but may get confused as modelled time switches across DST?, but again you can code this. fairly easily ).

con2. You should be testing with a good tick data source anyway. (just make sure timezone is set the same as your broker - and code can cope with different brokers.)

con3. It may possibly give incorrect offset (although this can be reduced significantly, by checking more datapoints (eg Lows etc. )


So I wouldn't say this is solution is best practice at all, especially as its not too robust until I incorporate more datapoints, but it is convenient that, during backtesting, I can throw any input data at it and it 'knows' the timezone and when to swithc in/out of DST, and can cope with situations like Alpari where the offset in the history has changed

Reason: