Tradetime

 

hello, 


i have some troubles with the trade time, i have written an expert to convert the trade time to i time i want to trade

here as example the settings


that works with the conversation

but in the trade history i find following, its always couple of seconds before the time

that it makes 2 trade its ok, i dont have the code done so fare

the one hour difference is from the trade server, the time conversation is, that i can enter the local time


//+------------------------------------------------------------------+
//|                                              TraderTom_V_0.1.mq5 |
//|                                  Copyright 2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"


#include <Trade/Trade.mqh>    CTrade trade;



enum Region
  {
   EU,
   USA
  };


input Region RegionOption = EU;

input string Starttime = "18:20:00" ; // zur Input machen
int magicNumber = 12345678;      // zur Input machen


//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {

   trade.SetExpertMagicNumber(magicNumber);

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {


  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

   // automatische Umschaltung für Sommer und Winterzeit nach Region EU und USA
   datetime Start=0;
   datetime Startzeit = StringToTime(Starttime);
   datetime nowGMT = TimeGMT();   // aktuelle GMT-Zeit
   int GMTOff = TimeTradeServer()-TimeGMT();
   
   

   //Print(RegionOption," ",IsDaylightSavingTimeEU(nowGMT));
   
   if(RegionOption == EU && IsDaylightSavingTimeEU(nowGMT))
     { Start = nowGMT + GMTOff - 1*3600;
     //Print("EU - Sommerzeit");
     }
     
   if(RegionOption == EU && !IsDaylightSavingTimeEU(nowGMT))
           { Start = nowGMT - GMTOff  + 1*3600;
     //Print("EU - Winterzeit");
     
     }
   if(RegionOption == USA && IsDaylightSavingTimeUS(nowGMT))
      {
      Start = nowGMT + GMTOff - 7*3600;
      //Print("USA - Sommerzeit");
      }
      
      
   if(RegionOption == USA && !IsDaylightSavingTimeUS(nowGMT))
      {
      Start = nowGMT + GMTOff - 6*3600;
      //Print("USA - Winterzeit");
      }
      
      
   //Print(Start, " ", Startzeit);

   if(Start >= Startzeit && Start <= Startzeit + 5) // hier passiert dann das was soll, anhand der Region sowie sommer und winterzeit
         
       if(PositionsTotal()== 0 )
         trade.Buy(0.1, _Symbol);


   
   if(PositionSelect(_Symbol))
     {
      trade.PositionClose(_Symbol);   // Schließt die offene Position
     }




  }


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsDaylightSavingTimeEU(datetime dt)
  {
// Gibt true zurück, wenn die übergebene UTC-Zeit in der EU-Sommerzeit liegt (zwischen 2020 und 2040)
   MqlDateTime time_struct;
   TimeToStruct(dt, time_struct);  // Konvertiere datetime in MqlDateTime-Struktur

   int year = time_struct.year;    // Jahr extrahieren
   if(year < 2020 || year > 2040)
      return false;  // Nur für Jahre 2020–2040 gültig

// Letzter Sonntag im März
   datetime dst_start = GetLastSundayOfMonth(year, 3) + 3600; // 2:00 MEZ = 1:00 UTC

// Letzter Sonntag im Oktober
   datetime dst_end = GetLastSundayOfMonth(year, 10) + 3600; // 3:00 MESZ = 1:00 UTC

   return (dt >= dst_start && dt < dst_end);
  }

// Hilfsfunktion: Gibt den letzten Sonntag eines Monats im gegebenen Jahr zurück (UTC Mitternacht)
datetime GetLastSundayOfMonth(int year, int month)
  {
   int next_month = month + 1;
   int next_year = year;

   if(next_month > 12)
     {
      next_month = 1;
      next_year += 1;
     }

   MqlDateTime dt = {0};
   dt.year  = next_year;
   dt.mon   = next_month;
   dt.day   = 1;
   dt.hour  = 0;
   dt.min   = 0;
   dt.sec   = 0;

   datetime first_of_next_month = StructToTime(dt);
   datetime last_day_of_month = first_of_next_month - 86400; // 1 Tag vorher

   TimeToStruct(last_day_of_month, dt);
   int wday = dt.day_of_week; // 0 = Sonntag, ..., 6 = Samstag

// Rückwärts zählen bis zum letzten Sonntag
   return last_day_of_month - (wday * 86400);
  }


// Gibt true zurück, wenn die übergebene UTC-Zeit in der US-Sommerzeit liegt (zwischen 2020 und 2040)
bool IsDaylightSavingTimeUS(datetime dt)
  {
   MqlDateTime time_struct;
   TimeToStruct(dt, time_struct);  // Konvertiere datetime in MqlDateTime-Struktur

   int year = time_struct.year;    // Jahr extrahieren
   if(year < 2020 || year > 2040)
      return false;  // Nur für Jahre 2020–2030 gültig

// US-Sommerzeit beginnt am zweiten Sonntag im März
   datetime dst_start = GetSecondSundayOfMonth(year, 3) + 3600; // 2:00 Uhr lokale Zeit (1:00 UTC)

// US-Sommerzeit endet am ersten Sonntag im November
   datetime dst_end = GetFirstSundayOfMonth(year, 11) + 3600;  // 2:00 Uhr lokale Zeit (1:00 UTC)

   return (dt >= dst_start && dt < dst_end);
  }

// Hilfsfunktion: Gibt den ersten Sonntag eines Monats im gegebenen Jahr zurück (UTC Mitternacht)
datetime GetFirstSundayOfMonth(int year, int month)
  {
   MqlDateTime dt = {0};
   dt.year  = year;
   dt.mon   = month;
   dt.day   = 1;
   dt.hour  = 0;
   dt.min   = 0;
   dt.sec   = 0;

   datetime first_of_month = StructToTime(dt);
   MqlDateTime first_day;
   TimeToStruct(first_of_month, first_day);

// Wochentag (0 = Sonntag, ..., 6 = Samstag)
   int wday = first_day.day_of_week;

// Berechne den ersten Sonntag
   return first_of_month + (86400 * (7 - wday) % 7);
  }

// Hilfsfunktion: Gibt den zweiten Sonntag eines Monats im gegebenen Jahr zurück (UTC Mitternacht)
datetime GetSecondSundayOfMonth(int year, int month)
  {
// Der zweite Sonntag ist der 8. bis 14. des Monats
   datetime first_sunday = GetFirstSundayOfMonth(year, month);
   return first_sunday + 86400 * 7;  // 7 Tage später
  }

//+------------------------------------------------------------------+


anyone an idea or is this a broker issiu on the trade server?


regards

 
amando:
It's a time conversion and logic issue, not the broker. StringToTime() gives you local time, but you're comparing it against server time, so it won't match. On top of that, the offset is applied incorrectly in some cases.

You're also opening and closing on the same tick, which causes duplicates. With only a 5-second window and irregular ticks, it's normal for execution to appear a few seconds early.

Finally, there's no daily control, so it can trigger more than once. The simplest fix is to convert everything to server time using TimeGMTOffset() and TimeTradeServer()-TimeGMT(), add a flag to avoid repeats, and separate the open and close logic. If you switch to OnTimer() instead of OnTick(), it will be cleaner and more predictable.
 
Miguel Angel Vico Alba #:
It's a time conversion and logic issue, not the broker. StringToTime() gives you local time, but you're comparing it against server time, so it won't match. On top of that, the offset is applied incorrectly in some cases.

why this should be a logic issiu i dont understand

i tried out

    Print(TimeLocal()," + ", TimeTradeServer());    

and its come exactly the same time.

so if i understand you right, its better to run the code in OnTime, with a 1 second timer it should be work right?


that i know, its dont anything bordering me right now, bcs its only the test for the conversation

Miguel Angel Vico Alba #:

You're also opening and closing on the same tick, which causes duplicates. With only a 5-second window and irregular ticks, it's normal for execution to appear a few seconds early.

Finally, there's no daily control, so it can trigger more than once. The simplest fix is to convert everything to server time using TimeGMTOffset() and TimeTradeServer()-TimeGMT(), add a flag to avoid repeats, and separate the open and close logic. If you switch to OnTimer() instead of OnTick(), it will be cleaner and more predictable.
 
amando # :

You asked why this should be a logic issue if TimeLocal() and TimeTradeServer() give you the same value, and if it is better to run the code in OnTimer() with a one-second timer so it works more reliably.

The times are equal in your setup because your broker's server is using the same timezone as your PC. That will not always be the case. On another broker, or if the server changes its configuration, there will be an offset. This is why the conversion logic is necessary if you want your code to work everywhere.

Running the code in OnTimer() with EventSetTimer(1) is indeed the correct approach. Tick arrival is never aligned exactly to the second, which is why you see trades executing a few seconds earlier. With a one-second timer you avoid that drift. In addition you still need to separate open and close logic and add a once per day control, otherwise duplicates and inconsistent results will appear even with the timer.

 
amando #:

why this should be a logic issiu i dont understand

i tried out

and its come exactly the same time.

Of course they are both using the local time as a reference.

Your issue is because there is a small shift in your local time (some seconds), you need to round your GMTOff to integer hour then multiply by 3600 to get rid of these lack of synchronization between your local time and server time. 

Strictly speaking it should be rounded to "quarter" of hour if you want universal code, but hour rounding will be sufficient in your case.
 
Alain Verleyen #:
r issue is becaus
Alain Verleyen #:

Of course they are both using the local time as a reference.

Your issue is because there is a small shift in your local time (some seconds), you need to round your GMTOff to integer hour then multiply by 3600 to get rid of these lack of synchronization between your local time and server time. 

Strictly speaking it should be rounded to "quarter" of hour if you want universal code, but hour rounding will be sufficient in your case.

means, when i round 09:15:00 or 09:30:00 it would be ok, but 09:35 couses this fault?

 
amando #:

means, when i round 09:15:00 or 09:30:00 it would be ok, but 09:35 couses this fault?

I didn't explain well sorry.

You local time and the server time are not synchronized (independently of any GMT/DST shift). For example, supposing the same GMT/DST on both side, your local time can be 18:20:00 but the server time is 18:19:58 !

   datetime Start=0;
   Startzeit = ..18:20..;
   datetime nowGMT = TimeGMT();   // aktuelle GMT-Zeit
   int GMTOff = 0;
   // then you set Start
   Start = 18:20:00

So your condition to trade is true BUT the server time is 18:19:58

TimeTraderServer() is based on LOCAL time (+-GMT/DST). You need to check TimeCurrent().