English Русский 中文 Español 日本語 Português
preview
Umgang mit Zeit (Teil 2): Die Funktionen

Umgang mit Zeit (Teil 2): Die Funktionen

MetaTrader 5Beispiele | 19 Oktober 2021, 09:01
1 114 1
Carl Schreiber
Carl Schreiber

Die globalen Variablen

Anstatt den Support Ihres Brokers zu fragen, von dem Sie wahrscheinlich eine unzureichende Antwort erhalten werden (wer würde schon bereit sein, eine fehlende Stunde zu erklären), schauen wir einfach selbst, welchen Zeitstempel Ihr Broker den Kursen in den Wochen der Zeitumstellung geben — aber nicht umständlich von Hand, das lassen wir ein Programm machen, wozu haben wir ja schließlich einen PC.

Vor den Funktionen werden die benötigten Variablen als globale Variablen in der Include-Datei DealingWithTime.mqh und nach der Makro-Substitution) deklariert:

//--- global variables for time switches
int      DST_USD=0,                             // act time shift USD
         DST_EUR=0,                             // act time shift EU
         DST_AUD=0,                             // act time shift Australia
         DST_RUS=0;                             // D'2014.10.26 02:00', -10800,

Diesen Variablen DST_USD, DST_EUR,.. werden die aktuelle Zeitverschiebung in den USA, der EU,... zugewiesen. Sie werden von unseren Funktionen aktualisiert und gesetzt. In der Winterzeit, die ja die Normalzeit ist, sind sie Null: die Zeit wird in diesem Zeitraum nicht verschoben.

Danach folgen die Variablen mit dem nächsten Zeitpunkt der Zeitumstellung. Sie werden hauptsächlich benötigt, um zu wissen, wann eine neue Berechnung erforderlich ist, um die CPU-Ressourcen zu schonen:

datetime nxtSwitch_USD,                         // date of next switch
         nxtSwitch_EUR,                         // date of next switch
         nxtSwitch_AUD,                         // date of next switch
         nxtSwitch_RUB = D'2014.10.26 02:00';   // Russia s different :(

Auf die russische Situation werden wir später in diesem Artikel eingehen.

Diese Struktur und ihre globale Variable sind das Herzstück von allem. :)

struct _OffsetBroker
  {
   int   USwinEUwin,                            // US=Winter & EU=Winter
         USsumEUsum,                            // US=Summer & EU=Summer
         USsumEUwin,                            // US=Summer & EU=Winter
         actOffset,                             // actual time offset of the broker
         secFxWiWi,                             // duration of FX in sec
         secFxSuSu,                             // duration of FX in sec
         secFxSuWi,                             // duration of FX in sec
         actSecFX;                              // actual duration of FX in sec
   bool  set;                                   // are all set?
  };
_OffsetBroker OffsetBroker;

Wir werden die Broker-Offsets für die drei relevanten Zeiträume und die Dauer des Devisenmarktes in diesen Zeiträumen zuweisen, sowohl für den tatsächlichen Wert als auch für eine einfache Kontrolle, ob die Werte zugewiesen wurden. Die globale Variable heißt OffsetBroker, wir werden ihr mehrmals begegnen.


Die zentrale Funktion zur Ermittlung der Zeitverschiebungen des Brokers

Durch den Aufruf dieser Funktion:

setBokerOffset();

kann ein EA, Indikator oder Skript selbst bestimmen, wann und wie der Broker mit Zeitverschiebungen umgeht. Sie wird im angehängten Skript am Anfang des Codes nach Start() platziert und die Funktion ermittelt für die relevanten Zeiträume (Sommerzeit, Winterzeit und die Zwischenzeit) die entsprechenden Werte des Brokers, die dann zur Ermittlung aller anderen benötigten Zeiten über GMT verwendet werden können. Sie befindet sich, wie alles andere auch, in der eingebundenen Include-Datei DealingWithTime.mqh, die auch die Teile aus dem ersten Artikel enthält. Nach der Variablendeklaration und den Initialisierungen und dem Nullsetzen der entsprechenden globalen Variablen:

   datetime dateEUR,dateUSD,dateAUD,dateNxt,                   // switch date for EU, AU, & US
            arrTme[];                                          // array to copy time
   int b;
   OffsetBroker.USsumEUwin =
      OffsetBroker.USsumEUsum =
         OffsetBroker.USwinEUwin = INT_MIN;
   nxtSwitch_USD = nxtSwitch_EUR = nxtSwitch_AUD = 0;          // reset variables

ermitteln wir die Wochenenden der Zeitumstellungen:

//--- AU, EU & US switches to winter time in 2020
   if(IS_DEBUG_MODE)
      Print("\n2nd half-year 2020 for ",AccountInfoString(ACCOUNT_COMPANY), "DebugMode: ",IS_DEBUG_MODE);

   nextDST("EUR", D'2020.06.21 14:00');                        // EUR: get DST and set next change
   b = CopyTime("EURUSD",PERIOD_H1,nxtSwitch_EUR,1,arrTme);    // get time last 1h bar before switch in EU
   dateEUR = arrTme[0];                                        // last hour on Friday before the weekend

   nextDST("USD", D'2020.06.21 14:00');                        // USD: get DST and set next change
   b = CopyTime("EURUSD",PERIOD_H1,nxtSwitch_USD,1,arrTme);    // get time last 1h bar before switch in USA
   dateUSD = arrTme[0];                                        // last hour on Friday before the weekend

   nextDST("AUD", D'2020.06.21 14:00');                        // AUD: get DST and set next change
   b = CopyTime("EURUSD",PERIOD_H1,nxtSwitch_AUD,1,arrTme);    // get time last 1h bar before switch in AU
   dateAUD = arrTme[0];                                        // last hour on Friday before the weekend

   dateNxt = fmax(nxtSwitch_EUR,nxtSwitch_USD)+WeekInSec;      // get the next weekend
   b = CopyTime("EURUSD",PERIOD_H1,dateNxt,1,arrTme);          // get time last 1h bar before the weekend
   dateNxt = arrTme[0];                                        // last hour on Friday before the weekend

Um es einfach zu machen, werden die meisten Ausdrucke im Debug-Modus automatisch ausgedruckt: if(IS_DEBUG_MODE). Wenn Sie also z.B. das angehängte Skript im Debugger (F5) starten, sehen Sie alle Details, aber wenn Sie das gleiche Skript direkt auf einem Chart starten, sehen Sie nur die wichtigen Dinge.

Für alle drei Zeitzonen wird der Funktionsaufruf z.B. nextDST("EUR", D'2020.06.21 14:00') zur Berechnung erstens der geltenden Zeitdifferenzen für die EU und zweitens der nächsten Umstellung verwendet. Im Juni ist Sommerzeit, und das nächste Umstellungswochenende wird die zur Winterzeit sein. In der Zeile unmittelbar danach erhalten wir die Öffnungszeit des letzten h1-Balkens am Freitag vor diesem Wochenende, da dies der Anker für unsere Berechnung sein wird. Siehe Punkt 4 der Annahmen am Ende des ersten Artikels:

          4. Fehlen Stunden zwischen Fr. 17:00 und So. 17:00 Uhr, dann fehlen die Kurse am Sonntag bis zum ersten Kurs und nicht am Freitag nach dem letzten eingegangenen Kurs.

Ich habe beschlossen, die Zeiten von h1 und "EURUSD" zu verwenden. Dieses Symbol ist dasjenige mit der längsten Historie, wahrscheinlich nicht nur bei MQ. Das bedeutet aber auch, dass, wenn der Devisenmarkt um 17:00 Uhr New Yorker Zeit schließt, die letzte Stunde oder der letzte 1-Stunden-Balken dort um 16:00 beginnt, und das ist die Stunde, die uns im weiteren Verlauf besonders interessiert. Die erste Stunde nach einem Wochenende ist dann um 17:00 Uhr am Sonntag in New York. Die Umstellung von Australien wird der Vollständigkeit halber ebenfalls festgelegt, aber im Weiteren nicht verwendet (siehe unten). Danach wird noch das erste Wochenende nach der Umstellung beider Zeitzonen ermittelt, um die Zeitverschiebung des Brokers für die nächste Position der Zeitverschiebung zu berechnen.

Dann werden für die drei Freitagsstunden die jeweiligen periodenbezogenen Zeitverschiebungen des Brokers mit der Funktion chckFriday(...) auf Basis der Zeit 16:00 in New York berechnet. Diese Funktion ist Teil der Include-Datei und wird im Folgenden besprochen.

   chckFriday(dateEUR,"EUR");                                  // function to determine broker offset for the Friday given
   chckFriday(dateUSD,"USD");                                  // function to determine broker offset for the Friday given
   chckFriday(dateNxt,"NXT");                                  // function to determine broker offset for the Friday given

Danach werden nach dem gleichen Prinzip die anderen Zeitumstellungen in der anderen Jahreshälfte berechnet — die wir (siehe oben) eigentlich nicht brauchen und die man auch auskommentieren kann:

   if(IS_DEBUG_MODE)
      Print("\n1st half-year 2021 for ",AccountInfoString(ACCOUNT_COMPANY), "DebugMode: ",IS_DEBUG_MODE);
   nxtSwitch_USD = nxtSwitch_EUR = nxtSwitch_AUD = 0;

   nextDST("AUD", D'2021.01.21 14:00');                        // AUD: get DST and set next change
   b = CopyTime("EURUSD",PERIOD_H1,nxtSwitch_AUD,1,arrTme);    // get time last 1h bar before switch in EU
   dateAUD = arrTme[0];                                        // last hour on Friday before the weekend

...
   chckFriday(dateUSD,"USD");                                  // function to determin broker offset for the Friday given
   chckFriday(dateEUR,"EUR");                                  // function to determin broker offset for the Friday given
   chckFriday(dateNxt,"NXT");                                  // function to determin broker offset for the Friday given

Schließlich werden, nachdem die Broker-Offsets erkannt und den entsprechenden Feldern zugewiesen wurden, die entscheidenden Umschaltzeiten (nxtSwitch_USD = nxtSwitch_EUR = nxtSwitch_AUD = 0) für eine spätere Verwendung auf Null zurückgesetzt. Da die Neuberechnung nur dann erfolgen soll, wenn im Laufe des historischen Verlaufs ein Wochenende mit einer Zeitumstellung 'passiert' wurde, kann eine spätere Uhrzeit die korrekten Berechnungen verhindern, also lieber einmal mehr zurücksetzen als einmal zu wenig. Anschließend wird geprüft, ob alle Werte zugewiesen wurden und das Ergebnis in das Expert-Journal gedruckt und die Prüfung zurückgegeben:

   nxtSwitch_USD = nxtSwitch_EUR = nxtSwitch_AUD = 0;          // reset variables for use by a user
   if(OffsetBroker.USsumEUwin != INT_MIN
      && OffsetBroker.USsumEUsum != INT_MIN
      && OffsetBroker.USwinEUwin != INT_MIN
     )
      OffsetBroker.set = true;
   else
      OffsetBroker.set = false;
   if(OffsetBroker.set)
      Print("\nTime Offset of ",AccountInfoString(ACCOUNT_COMPANY),": ",
            "\nUS=Winter & EU=Winter (USwinEUwin) = ",OffsetBroker.USwinEUwin,
            "\nUS=Summer & EU=Summer (USsumEUsum) = ",OffsetBroker.USsumEUsum,
            "\nUS=Summer & EU=Winter (USsumEUwin) = ",OffsetBroker.USsumEUwin,
            "\n");
   else
      Print(__FILE__,"[",__LINE__,"] Assigning the broker offset went wrong - somehow.");
   return(OffsetBroker.set);

Wenn alles in Ordnung ist, sieht man z.B. diese Zeilen:

Time Offset of MetaQuotes Software Corp.:
US=Winter & EU=Winter (USwinEUwin)       =   -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin)    =   -7200

Dies ermöglicht es jedem Nutzer, diese Werte für Eingabevariablen anstelle der Funktion zu verwenden, die ausgeführt werden muss, bevor ein EA entweder im Strategietester oder live auf einem Chart funktioniert. Ein Beispiel finden Sie am Ende dieses Artikels.


Die Zeitverschiebungen des Brokers bestimmen und einstellen

Betrachten wir nun die Funktion chckFriday(...). Sie ermittelt die Zeitverschiebung des jeweiligen Brokers für die verschiedenen Zeiträume und weist sie dem jeweiligen Feld der globalen Variablen OffsetBroker aus dem Tpy der Struktur _OffsetBroker zu. Die Struktur kennt diese drei Felder:

   int   USwinEUwin,                            // US=Winter & EU=Winter
         USsumEUsum,                            // US=Summer & EU=Summer
         USsumEUwin,                            // US=Summer & EU=Winter

Sie werden der jeweiligen Zeitverschiebung des Maklers der entsprechenden Zeiträume zugeordnet. Die Zeiträume sind:

  • beide Regionen sind gleich, entweder Winter (oder Standardzeit) oder Sommer, oder
  • USA, bereits (noch) im Sommer und die EU noch (bereits) im Winter.

Die umgekehrte Situation, dass die USA bereits (noch) im Winter, die EU aber noch (schon) im Sommer ist, gibt es nicht. Hier stellt sich nicht nur die Frage, warum es die vierte Kategorie nicht gibt und was ist mit Australien oder AUD — fehlt das hier?

Hier sind die Regeln für den Wechsel:

  • EU: letzter Sonntag im Oktober und letzter Sonntag im März
  • US: 1. Sonntag im November und 2. Sonntag im März und
  • AU: 1. Sonntag im November und letzter Sonntag im März


Zur ersten Frage. Die EU stellt ein oder zwei Wochen vor den USA auf Winterzeit um: da ist in den USA noch Sommer, während es in der EU schon Winter ist, also wird der Wert dem USsumEUwin Feld der OffsetBroker Variable zugewiesen. Dann wechseln die USA im Frühjahr vor der EU zur Sommerzeit, dann ist in den USA wieder für ein oder zwei Wochen Sommer, während in der EU noch Winter ist. Auch hier wird der Wert dem USsumEUwin Feld der OffsetBroker Variablen zugewiesen. Damit wird deutlich, dass der umgekehrte Fall EU schon (noch) Sommer, die USA aber noch (schon) Winter gar nicht vorkommt. Damit erübrigt sich eigentlich die Berechnung der Broker-Zeitverschiebungen für die beiden Umstellungszeiträume im Herbst und im Frühjahr. Es wird trotzdem ausgeführt — einfach wegen der Vollständigkeit und der Kontrolle.

Zur zweiten Frage. Australien stellt im November um, wie die USA, und im Frühjahr wie die EU. Es gibt also keine zusätzlichen unterschiedlichen Wochenenden für die Umstellung. Allerdings wird die Uhr in Australien um 1 Stunde vorgestellt, wenn es in der EU und den USA Winter ist, weil Weihnachten und Neujahr dort in den Sommer fallen.

Wenn wir nun schon die Zeitverschiebung für einen bestimmten Zeitraum berechnen, dann können wir auch die aktuelle Dauer gleich mitberechnen, die der Devisenmarkt in diesen Wochen geöffnet ist. Diese Werte werden in den Feldern secFxWiWi, secFxSuSu, secFxSuWi und der aktuell gültige Wert in actSecFX gespeichert. Am Ende des Artikels, im Kapitel Anwendung, wird gezeigt, wie man damit umgeht.

Doch bevor die Werte zugewiesen werden können, müssen sie erst einmal ermittelt werden. Nach der Variablendeklaration und dem Zurücksetzen der globalen Variablen werden die Zeitverschiebungen für EU und USD für den gegebenen Zeitpunkt tB (time Broker) berechnet:

//+------------------------------------------------------------------+
//| auxiliary function to determine time offset of the broker        |
//+------------------------------------------------------------------+
int chckFriday(
   datetime tB,                                                // time Broker: the last hour on Friday
   string cmt=""                                               // text to start the line
)
  {

   int hNY, hGMT, hTC, hDiff;
   nxtSwitch_AUD = nxtSwitch_USD = nxtSwitch_EUR = 0;          // reset to be save
   nextDST("EUR",tB);                                          // get the offset for EUR of the time tB given
   nextDST("USD",tB);                                          // get the offset for USD of the time tB given

Hier ist tB der Beginn der letzten Stunde des Freitags, d.h. wenn es in New York 16:00 Uhr ist. Diese Annahme ist die Grundlage für die weitere Berechnung, denn wir können die GMT für diese Zeit berechnen:

tGMT = tNY + (NYShift + DST_USD)

und damit den Offset des Brokers zur GMT. Diesen Offset ermitteln wir folgendermaßen: Von der letzten Freitagsstunde des Brokers tB subtrahieren wir die vergangenen Sekunden dieses Tages, SoB(tB). Wir erhalten die Zeit 00:00 für den Tag und addieren dann die Sekunden bis 16:00 (16*3600). Jetzt kennen wir die New Yorker Zeit, von der wir durch Addition von NYShift + DST_USD die GMT erhalten. Jetzt können wir leicht den Zeitversatz des Brokers von der GMT bestimmen und ihn dann dem entsprechenden Feld von OffsetBroker zuweisen.
In der Funktion erfolgt dies alles in Stunden (statt in Sekunden) mit der Makro-Substitution HoD() — Hour of Day, aus Gründen der Dokumentation und der leichteren Überprüfbarkeit im Ausdruck:

   hNY   = HoD(tB - SoD(tB) + 16*3600);                        // get the hour of New York time
   hGMT  = HoD(tB - SoD(tB) + 16*3600 + NYShift + DST_USD);    // get the hour of GMT
   hTC   = HoD(tB);                                            // get the hour of the time given
   hDiff = hGMT - HoD(tB);                                     // get the difference between GMT and the broker

Es ist doch gar nicht so schwer. ;)

Sicherheitshalber wird das Folgende eingefügt. Es wird geprüft, ob die nicht zu erwartende Situation, USA im Sommer und EU im Winter, nicht eintritt:

   if(DST_USD==0 && DST_EUR!=0)                                // this should not occur
      Alert(__LINE__," ",TOSTR(DST_USD),TOSTR(DST_EUR),"  USwin && EUsum");

Nun können wir die gefundene Differenz und die Dauer der Öffnung des FX-Marktes zuweisen:

//--- set the broker offset for the various time situations:
   if(DST_USD+DST_EUR==0)                                      // both in winter (normal) time
     {
      OffsetBroker.actOffset = OffsetBroker.USwinEUwin = hDiff*3600;
      OffsetBroker.actSecFX  = OffsetBroker.secFxWiWi = SoW(tB);
     }
   else
      if(DST_USD == DST_EUR)                                   // else both in summer time
        {
         OffsetBroker.actOffset = OffsetBroker.USsumEUsum = hDiff*3600;
         OffsetBroker.actSecFX  = OffsetBroker.secFxSuSu = SoW(tB);
        }
      else
         if(DST_USD!=0 && DST_EUR==0)                          // US:summer EU:winter
           {
            OffsetBroker.actOffset = OffsetBroker.USsumEUwin = hDiff*3600;
            OffsetBroker.actSecFX  = OffsetBroker.secFxSuWi = SoW(tB);
           }

Schließlich werden alle gefundenen Werte ausgedruckt und der letzte tatsächliche Offset zurückgegeben:

//--- calc the ring of times NY->GMT->Broker->GMT->NY <= the last NY must always be 16!!
   Print(cmt,": ",DoWs(tB),TimeToString(tB),": ",TOSTR(hNY),TOSTR(hGMT),TOSTR(hTC),TOSTR(hDiff),
         " BrokerTime => GMT: ",TimeToString(tB+OffsetBroker.actOffset),
         " => tNY: ",TimeToString((tB + OffsetBroker.actOffset)-(NYShift + DST_USD)),
         "  End-FX after: ",OffsetBroker.actSecFX/3600,"h"
        );
   return(OffsetBroker.actOffset);

Das sieht wie folgt aus:

EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End FX in: 143h
USD: Fr.2020.10.30 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End FX in: 142h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End FX in: 143h

Hier sind einige interessante Dinge zu sehen, die es wert sind, diskutiert zu werden. Die EU schaltet zuerst am 25.10. um. Eine Woche später, am 1.11. die USA. In dieser Zwischenzeit beginnt die letzte Stunde am Freitag bei MQ um 22:00 statt um 23:00 und die Woche endet mit diesem Balken nach 142 Stunden statt normalerweise nach 143 Stunden. 143 oder 142 Stunden? Die FX-Woche hat nur 120 Stunden: 5*24=120? Die Sekunden der Woche (SoW()) und die anderen vergleichbaren Funktionen beziehen sich auf die kalendarische Woche, die am Sonntag um 00:00 Uhr beginnt. Aber von So. 00:00 bis Fr. 23:00 Uhr sind es nun 6* 24-1 = 143. Dieser Wert wird im Folgenden verwendet, um für jeden beliebigen Zeitpunkt in einer Woche die verbleibende Zeit zu berechnen, die der Devisenmarkt geöffnet bleibt.

Diese drei Zeilen dienen auch dazu, die Logik und die Berechnung zu überprüfen und als Beispiel dafür, wie ein Nutzer eine gewünschte Ortszeit aus der GMT bestimmen kann. Von links beginnend folgt auf den Zeitstempel des Brokers die angenommene Zeit in New York, hNY: 16, dann die Stunde der GMT auf der Grundlage der New Yorker Zeit, die Stunde des Brokers und seine Zeitverschiebung: -2 oder -3. Im zweiten Teil weiter rechts wird GMT aus der Zeit des Brokers (tB+OffsetBroker.actOffset) und dann aus GMT wieder die Zeit in New York ((tB + OffsetBroker.actOffset)-(NYShift + DST_USD)) berechnet. Hier muss tNY immer 16:00 sein und das ist auch so. Eine zweite Prüfung für beliebige Zeiten in der Historie und für andere Broker wird weiter unten durchgeführt.


Berechnung der Wochenenden der Zeitumstellung

Doch bevor wir zu der Prüfung kommen, bei der wir die Zeithistorie für "EURUSD" durchgehen, müssen wir das Herzstück der Berechnung besprechen, die Funktion nextDST(...).
Die Funktion wird mit dem Parameter zone für die Zeitzone "USD", "EUR" oder "AUD" (wobei "AUD" nicht wirklich benötigt wird) und t, dem Parameter für eine aktuelle Zeit, in der Regel die aktuelle Brokerzeit TimeCurrent(). Zunächst wird geprüft, ob überhaupt eine Neuberechnung notwendig ist (hier für "EUR"):

void nextDST(string zone, datetime t)
  {
   if((zone == "EUR") && t < nxtSwitch_EUR)
     {
      if(IS_DEBUG_MODE)
         Print("no change as time < nxtSwitch_EUR");
      return;
     }
...

Dies zeigt auch, warum es wichtig ist, die Werte für nxtSwitch_EUR zu Beginn des Tests auf Null zu setzen, da sonst eine Neuberechnung möglicherweise nicht für die gesamte Testdauer durchgeführt wird.

Nach der Variablendeklaration und Initialisierung kommen wir dann zum Kern der Funktion, der nicht von mir stammt. Vor geraumer Zeit habe ich irgendwo im Netz einen Algorithmus gefunden, der einen bestimmten Tag im Monat bestimmt. Er wird verwendet, um die Sommer- oder Winterzeit für einen bestimmten Zeitpunkt zu bestimmen. Der Algorithmus ist gar nicht so kompliziert:

  1. Ermittele den Tag im Monat, einen Sonntag, an dem die Zeitumstellung stattfindet.
  2. Erstelle daraus ein Datum.
  3. Finde den nächstgelegenen Umstellungssonntag.
  4. Bestimme die Zeitverschiebung, entweder 0h oder -1h, und den nächsten Umstellungssonntag.

Die Magie dieses Algorithmus liegt in der Codezeile, die den Tag im Monat der Zeitumstellung bestimmt. Für die EU ist es der letzte Sonntag im März, und er wird wie folgt berechnet (wie gesagt, die Idee der Formel stammt nicht von mir):

d = (int)(31 - MathMod((4 + MathFloor(5*y/4)), 7));         // determing the last Sunday in March for the EU switch
Für das Jahr 2021 wird der letzte Sonntag im März, hier als EXCEL-Formel, ermittelt als d=25:

31 - MOD(ROUNDDOWN(5*2021/4);7) = 25.


Daraus wird dann der Zeitstempel gebildet, an dem die EU auf Sommerzeit umschaltet: Der 25. März 2021, der letzte Sonntag im März:
spr = StringToTime(""+(string)y+".03."+(string)d+" 03:00"); // convert to datetime format

Die Vorgehensweise für alle anderen Daten ist ähnlich und bedarf keiner gesonderten Erklärung.
Hier nun ein größerer Abschnitt des Codes, der für ein bestimmtes Datum die aktuelle Sommer- bzw. Winterzeitumstellung und das nächste Umstellungsdatum in der EU ermittelt. Wir brauchen drei Abschnitte in einem Jahr: vor der ersten, zwischen der ersten und der zweiten und nach der zweiten Zeitumstellung. Die nächste Zeitumstellung liegt dann bereits im nächsten Jahr und das muss berücksichtigt werden:

   if(zone == "EUR")
     {
      d = (int)(31 - MathMod((4 + MathFloor(5*y/4)), 7));         // determing the last Sunday in March for the EU switch
      spr = StringToTime(""+(string)y+".03."+(string)d+" 03:00"); // convert to datetime format
      if(t < spr)
        {
         DST_EUR = 0;                                             // no time offset
         nxtSwitch_EUR = spr;                                     // set the next time switch
         if(IS_DEBUG_MODE)
            Print(zone,"-DST for ",TimeToString(t)," DST: ",StringFormat("% 5i",DST_EUR),"  nxtSwitch: ",DoWs(nxtSwitch_EUR)," ",TimeToString(nxtSwitch_EUR));
         return;
        }
      d = (int)(31 - MathMod((1 + MathFloor(5*y/4)), 7));         // determing the last Sunday in October for the EU switch
      aut = StringToTime(""+(string)y+".10."+(string)d+" 03:00"); // convert to datetime format
      if(t < aut)
        {
         DST_EUR =-3600;                           // = +1h => 09:00 London time = GMT+05h+DST_EU = GMT+0+1 = GMT+1;
         nxtSwitch_EUR = aut;                                     // set the next time switch
         if(IS_DEBUG_MODE)
            Print(zone,"-DST for ",TimeToString(t)," DST: ",StringFormat("% 5i",DST_EUR),"  nxtSwitch: ",DoWs(nxtSwitch_EUR)," ",TimeToString(nxtSwitch_EUR));
         return;
        }
      y++;                                                        // re-calc the spring switch for the next year
      d = (int)(31 - MathMod((4 + MathFloor(5*y/4)), 7));         // determing the last Sunday in March for the EU switch
      spr = StringToTime(""+(string)y+".03."+(string)d+" 03:00"); // convert to datetime format
      if(t < spr)
        {
         DST_EUR = 0;                                             // no time offset
         nxtSwitch_EUR = spr;                                     // set the next time switch
         if(IS_DEBUG_MODE)
            Print(zone,"-DST for ",TimeToString(t)," DST: ",StringFormat("% 5i",DST_EUR),"  nxtSwitch: ",DoWs(nxtSwitch_EUR)," ",TimeToString(nxtSwitch_EUR));
         return;
        }
      Print("ERROR for ",zone," @ ",TimeToString(t)," DST: ",StringFormat("% 5i",DST_EUR),"  nxtSwitch: ",DoWs(nxtSwitch_EUR)," ",TimeToString(nxtSwitch_EUR),"  winter: ",TimeToString(aut),"  spring: ",TimeToString(spr));
      return;
     }

Man kann drei Abschnitte innerhalb eines Jahres sehen:

  1. Vor der Umstellung auf die Sommerzeit im März.
  2. Vor der Umstellung auf die Winterzeit im Oktober/November.
  3. In der Winterzeit die Umstellung auf die Sommerzeit im nächsten Jahr.

Dies wiederholt sich für EUR, USD und AUD.

Durch die einzelnen Aufrufe der Funktion nextDST(..)

nextDST("EUR", D'2019.02.05 20:00');
nextDST("EUR", D'2019.06.05 20:00');
nextDST("EUR", D'2019.11.20 20:00');
        
nextDST("USD", D'2019.02.05 20:00');
nextDST("USD", D'2019.06.05 20:00');
nextDST("USD", D'2019.11.20 20:00');
        
nextDST("AUD", D'2019.02.05 20:00');
nextDST("AUD", D'2019.06.05 20:00');
nextDST("AUD", D'2019.11.20 20:00');

werden alle drei relevanten Zeitpunkte des Jahres für die drei Regionen testen. Dies ist das Ergebnis:

EU: last Sunday in March and last Sunday in October:
    EUR-DST for 2019.02.05 20:00 DST:        0   nxtSwitch: Su. 2019.03.31 03:00
    EUR-DST for 2019.06.05 20:00 DST: -3600   nxtSwitch: Su. 2019.10.27 03:00
    EUR-DST for 2019.11.20 20:00 DST:        0   nxtSwitch: Su. 2020.03.29 03:00

US: 2nd Sunday in March and 1st Sunday in November:
    USD-DST for 2019.02.05 20:00 DST:        0   nxtSwitch: Su. 2019.03.10 03:00
    USD-DST for 2019.06.05 20:00 DST: -3600   nxtSwitch: Su. 2019.11.03 03:00
    USD-DST for 2019.11.20 20:00 DST:        0   nxtSwitch: Su. 2020.03.08 03:00

AU: 1st Sunday in November and last Sunday in March:
    AUD-DST for 2019.02.05 20:00 DST: -3600   nxtSwitch: Su. 2019.03.31 03:00
    AUD-DST for 2019.06.05 20:00 DST:        0   nxtSwitch: Su. 2019.11.03 03:00
    AUD-DST for 2019.11.20 20:00 DST: -3600   nxtSwitch: Su. 2020.03.29 03:00

Vielleicht ist die Zeitumstellung in Australien verwirrend, aber Australien liegt im Gegensatz zu den USA und Europa auf der Südhalbkugel, wo der Jahreswechsel in der Mitte des Sommers liegt und es daher zu erwarten ist, dass ihre Sommerzeit im europäischen Winter liegt.


Die Umstellung in Russland

Eine kleine Anmerkung: Da MQ russische Wurzeln hat und es viele russische Nutzer gibt, sind auch die russischen Zeitumstellungen enthalten. Wegen der großen Anzahl von Umstellungen, wann und wie die Uhren in Russland umgestellt wurden, habe ich mich jedoch für ein zweidimensionales Array entschieden, in das die Zeiten und die jeweiligen Verschiebungen eingetragen wurden und das mit dieser Funktion abgefragt werden kann:

long RussiaTimeSwitch[][2] =
  {
   D'1970.01.00 00:00', -10800,
   D'1980.01.00 00:00', -10800,
   D'1981.04.01 00:00', -14400,
...
   D'2012.01.00 00:00', -14400,
   D'2014.10.26 02:00', -10800,
   D'3000.12.31 23:59', -10800
  };
int SzRussiaTimeSwitch = 67;                    // ArraySize of RussiaTimeSwitch

//+------------------------------------------------------------------+
//| Russian Time Switches                                            |
//+------------------------------------------------------------------+
void offsetRubGMT(const datetime t)
  {
   int i = SzRussiaTimeSwitch; //ArrayRange(RussiaTimeSwitch,0); 66
   while(i-->0 && t < RussiaTimeSwitch[i][0])
      continue;
// t >= RussiaTimeSwitch[i][0]
   nxtSwitch_RUB  = (datetime)RussiaTimeSwitch[fmin(SzRussiaTimeSwitch-1,i+1)][0];
   DST_RUS        = (int)RussiaTimeSwitch[fmin(SzRussiaTimeSwitch-1,i+1)][1];
   return;
  }
//+------------------------------------------------------------------+


Die Funktion, die die Zeiten auf dem neuesten Stand hält

Nun kommen wir zur letzten Funktion dieses Projekts, der Funktion, die die entscheidenden Werte auf dem neuesten Stand hält:

//+------------------------------------------------------------------+
//| function to determin broker offset for the time tB given         |
//+------------------------------------------------------------------+
void checkTimeOffset(datetime tB)
  {
   if(tB < nxtSwitch_USD && tB < nxtSwitch_EUR && tB < nxtSwitch_AUD)
      return;                                                  // nothing has changed, return

Sie fragt auch gleich zu Beginn, ob die Zeitverschiebung (und das nächste Umstellungsdatum) gesetzt werden muss. Wenn nicht, wird die Funktion sofort verlassen.

Ansonsten werden die Werte für "EUR", "USD", "AUD" und "RUB" mit der oben beschriebenen Funktion nextDST() berechnet:

   if(tB>nxtSwitch_USD)
      nextDST("USD", tB);                                      // US has switched
   if(tB>nxtSwitch_EUR)
      nextDST("EUR", tB);                                      // EU has switched
   if(tB>nxtSwitch_AUD)
      nextDST("AUD", tB);                                      // AU has switched
   if(tB>nxtSwitch_RUB)
      nextDST("RUB", tB);                                      // RU has switched

"USD" und "EUR" werden benötigt, um den Broker-Offset zu bestimmen. "AUD" und "RUB" werden nur benötigt, wenn ein Nutzer sie wissen will, ansonsten kann man sie einfach durch // deaktivieren.

Dann muss je nach Zeitraum dem Feld OffsetBroker.actOffset der ab diesem Zeitpunkt gültige Zeitversatz des Brokers und OffsetBroker.actSecFX der aktuelle Eröffnungszeitraum des Devisenmarktes zugewiesen werden:

   if(DST_USD+DST_EUR==0)                                      // both in winter (normal) time
     {
      OffsetBroker.actOffset = OffsetBroker.USwinEUwin;
      OffsetBroker.actSecFX  = OffsetBroker.secFxWiWi;
     }
   else
      if(DST_USD == DST_EUR)                                   // else both in summer time
        {
         OffsetBroker.actOffset = OffsetBroker.USsumEUsum;
         OffsetBroker.actSecFX  = OffsetBroker.secFxSuSu;
        }
      else
         if(DST_USD != DST_EUR)                                // US:summer EU:winter
           {
            OffsetBroker.actOffset = OffsetBroker.USsumEUwin;
            OffsetBroker.actSecFX  = OffsetBroker.secFxSuWi;
           }

Das war's. Dies sind alle Funktionen, die zur Nutzung notwendig sind: Die Ermittlung der Zeitverschiebungen des Brokers aus einem Kurs und die Funktion, die immer die aktuelle Zeitverschiebung ermittelt und aus der sich die GMT und damit jede andere Ortszeit auch im Strategietester leicht ermitteln lässt.

Wir zeigen nun zwei Möglichkeiten, alles zu nutzen.


Das Skript zur Demonstration von Einstellung und Verwendung

Zunächst verwenden wir es in dem (angehängten) Skript, DealingWithTimeScript.mq5:

#include <DealingWithTime.mqh>
//+------------------------------------------------------------------+
//| Finding the broker offsets                                       |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- step 1: set the broker time offsets in winter, summer and in between
   bool isTimeSet = setBokerOffset();
   if(!isTimeSet)
     {
      Alert("setBokerOffset failed");
      return;
     }

Dies wird dann in das Log der Experten ausgegeben:

EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 142h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 142h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Time Offset of MetaQuotes Software Corp.: 
US=Winter & EU=Winter (USwinEUwin)      =  -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin)   =   -7200

Dies ermöglicht es dem Nutzer bereits, die gefundenen Abfragen den Eingabevariablen zuzuordnen. Dies ist das Beispiel des nächsten Kapitels. Was wir hier sehen, ist bereits erklärt, also gehen wir zum nächsten Schritt dieses Skripts über. Wir simulieren einen Weg von der Vergangenheit zur aktuellen Stunde des Brokers und berechnen und drucken die Werte von GMT, New York und die verbleibende Zeit, die der Forex-Markt für zufällig ausgewählte Zeitstempel geöffnet bleibt.

Die gesamte Historie der 1h-Zeitstempel von "EURUSD" erhalten wir mit der Funktion CopyTime("EURUSD",PERIOD_H1,datetime(0),TimeCurrent(),arr1h).

Um aber nicht in Unmengen von Daten und einem langen Ausdruck für diesen langen Zeitraum zu ertrinken, zeigen wir nur die Daten von zufällig bestimmten Balken. Dazu wählen wir aus, wie viele Daten es sein sollen. Bei den gegebenen 5 werden es etwa 10 sein, denn im zufälligen Mittel beträgt die Sprungweite etwa die Hälfte von sz/5:

//--- step 2: get the quotes (here only 1h time stamps)
   datetime arr1h[], tGMT, tNY, tLeft;
   CopyTime("EURUSD",PERIOD_H1,datetime(0),TimeCurrent(),arr1h);
   int b       = 0,
       sz      = ArraySize(arr1h)-1,                  // oldest time stamp
       nChecks = sz/5,                                // ~2*5+1 randomly chosen bars
       chckBar = MathRand()%nChecks;                  // index of the first bar to check

Jetzt gehen wir alle Balken durch, vom ältesten bis zum aktuellen, wie bei einem Test oder einer Optimierung im Strategietester: while(++b<=sz). Als Erstes prüfen wir die Zeitlage für jeden neuen Balken: checkTimeOffset(arr1h[b]). Wir erinnern uns, dass in dieser Funktion als Erstes geprüft wird, ob eine Neuberechnung erforderlich ist, sodass dieser Aufruf trotz seiner Häufigkeit nicht sehr ressourcenintensiv ist:

//---  step 3: simulate an EA or an indicator go through the time from the past to now
   while(++b<=sz)
     {
      //--- check the time situation, normally do it at the first bar after the weekend
      checkTimeOffset(arr1h[b]);

Nun berechnen wir (nur) für den durch den Zufallswert bestimmten Balken GMT (tGMT), die New Yorker Zeit (tNY) und tLeft, die verbleibende Zeit bis zum Schließen des Devisenmarktes. Dann wird dies ausgedruckt und der Index des nächsten Balkens berechnet:

      //--- for a randomly selected bar calc. the times of GMT, NY & tLeft and print them
      if(b>=chckBar || b==sz)
        {
         tGMT  = arr1h[b] + OffsetBroker.actOffset;         // GMT
         tNY   = tGMT - (NYShift+DST_USD);                  // time in New York
         tLeft = OffsetBroker.actSecFX - SoW(arr1h[b]);     // time till FX closes
         PrintFormat("DST_EUR:%+ 6i  DST_EUR:%+ 6i  t[%6i]  tBrk: %s%s  "+
                     "GMT: %s%s  NY: %s%s  End-FX: %2ih => left: %2ih ",
                     DST_EUR,DST_USD,b,
                     DoWs(arr1h[b]),TimeToString(arr1h[b],TIME_DATE|TIME_MINUTES),
                     DoWs(tGMT),TimeToString(tGMT,TIME_DATE|TIME_MINUTES),
                     DoWs(tNY),TimeToString(tNY,TIME_DATE|TIME_MINUTES),
                     OffsetBroker.actSecFX/3600,tLeft/3600
                    );
         chckBar += MathRand()%nChecks;               // calc. the index of the next bar to check
        }

Hier nun der vollständige Ausdruck dieses Skripts für ein Demokonto von Metaquotes:

EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 142h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 142h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Time Offset of MetaQuotes Software Corp.: 
US=Winter & EU=Winter (USwinEUwin)      =  -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin)   =   -7200

DST_EUR: -3600  DST_EUR: -3600  t[ 28194]  tBrk: Mo.2002.05.20 22:00  GMT: Mo.2002.05.20 19:00  NY: Mo.2002.05.20 15:00  End-FX: 143h => left: 97h 
DST_EUR: -3600  DST_EUR: -3600  t[ 40805]  tBrk: We.2004.05.26 06:00  GMT: We.2004.05.26 03:00  NY: Tu.2004.05.25 23:00  End-FX: 143h => left: 65h 
DST_EUR: -3600  DST_EUR: -3600  t[ 42882]  tBrk: Th.2004.09.23 19:00  GMT: Th.2004.09.23 16:00  NY: Th.2004.09.23 12:00  End-FX: 143h => left: 28h 
DST_EUR:      +0  DST_EUR:     +0  t[ 44752]  tBrk: Tu.2005.01.11 17:00  GMT: Tu.2005.01.11 15:00  NY: Tu.2005.01.11 10:00  End-FX: 143h => left: 78h 
DST_EUR:      +0  DST_EUR: -3600  t[ 64593]  tBrk: We.2008.03.26 03:00  GMT: We.2008.03.26 01:00  NY: Tu.2008.03.25 21:00  End-FX: 142h => left: 67h 
DST_EUR:      +0  DST_EUR:     +0  t[ 88533]  tBrk: Tu.2012.02.07 13:00  GMT: Tu.2012.02.07 11:00  NY: Tu.2012.02.07 06:00  End-FX: 143h => left: 82h 
DST_EUR:      +0  DST_EUR:     +0  t[118058]  tBrk: We.2016.11.16 06:00  GMT: We.2016.11.16 04:00  NY: Tu.2016.11.15 23:00  End-FX: 143h => left: 65h 
DST_EUR: -3600  DST_EUR: -3600  t[121841]  tBrk: Mo.2017.06.26 05:00  GMT: Mo.2017.06.26 02:00  NY: Su.2017.06.25 22:00  End-FX: 143h => left: 114h 
DST_EUR:      +0  DST_EUR: -3600  t[144995]  tBrk: Mo.2021.03.22 06:00  GMT: Mo.2021.03.22 04:00  NY: Mo.2021.03.22 00:00  End-FX: 142h => left: 112h 
DST_EUR: -3600  DST_EUR: -3600  t[148265]  tBrk: Tu.2021.09.28 15:00  GMT: Tu.2021.09.28 12:00  NY: Tu.2021.09.28 08:00  End-FX: 143h => left: 80h 

Die ersten beiden Blöcke wurden bereits besprochen. Der dritte und letzte Teil zeigt für die zufällig gewählten Zeitpunkte die jeweiligen Zeitdifferenzen von EU und USA, den Index des Zeitpunktes, gefolgt von den Zeiten des Brokers, GMT und New York, gefolgt von der Eröffnungszeit des Devisenmarktes zu diesem Zeitpunkt und der verbleibenden Zeit — der Übersichtlichkeit halber umgerechnet in Stunden statt Sekunden. Dies kann jetzt schnell überprüft werden: Am 20.5.2002 ist Brokerzeit (MQ) 22:00, es gilt Sommerzeit, GMT = Broker-3h = 19:00 und NY = GMT - (5h-1h) = 15:00 und der Devisenmarkt schließt in 97 Stunden. 97 = 4*24 (Mo.22:00-Fri.22:00 = 96h) +1h (Fr.22:00-23:00) — qed.

Ein EA oder Indikator, der nur die verschiedenen Offsets benötigt, braucht also nur zwei Funktionsaufrufe:

   bool isTimeSet = setBokerOffset();
   if(!isTimeSet)
     {
      Alert("setBokerOffset failed");
      return;
     }
..
   checkTimeOffset(TimeCurrent());


Die Alternative, die Verwendung von Eingabevariablen

Zum Schluss noch ein Beispiel, wie ein EA dies über seine Eingabevariablen nutzen kann. Mit dem Skript von oben bekommen Sie den folgenden Ausdruck:

Time Offset of MetaQuotes Software Corp.:
US=Winter & EU=Winter (USwinEUwin)      =  -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin)   =   -7200

Mit diesem Wissen würde ein EA (nicht angehängt, Sie können ihn von hier kopieren) wie folgt aussehen:

#include <DealingWithTime.mqh>
// offsets of MetaQuotes demo account: DO NOT USE THEM FOR DIFFERENT BROKERS!!
input int   USwinEUwin=  -7200;    // US=Winter & EU=Winter
input int   USsumEUsum= -10800;    // US=Summer & EU=Summer
input int   USsumEUwin=  -7200;    // US=Summer & EU=Winter

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   OffsetBroker.USwinEUwin = USwinEUwin;
   OffsetBroker.USsumEUsum = USsumEUsum;
   OffsetBroker.USsumEUwin = USsumEUwin;
   OffsetBroker.actOffset  = WRONG_VALUE; 
   
   nxtSwitch_USD = nxtSwitch_EUR = nxtSwitch_AUD = 0;
   //--- Just a simple test if not ste or changed
   if(OffsetBroker.USwinEUwin+OffsetBroker.USsumEUsum+OffsetBroker.USsumEUwin==0)
      OffsetBroker.set     = false;
   else
      OffsetBroker.set     = true;
   //...
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   checkTimeOffset(TimeCurrent());
   tGMT  = TimeCurrent() + OffsetBroker.actOffset;    // GMT
   tNY   = tGMT - (NYShift+DST_USD);                  // time in New York
   tLon  = tGMT - (LondonShift+DST_EUR);              // time in London
   tSyd  = tGMT - (SidneyShift+DST_AUD);              // time in Sidney
   tMosc = tGMT - (MoskwaShift+DST_RUS);              // time in Moscow
   tTok  = tGMT - (TokyoShift);                       // time in Tokyo - no DST

   //...
   
  }

Hier habe ich die Offests von Metaquotes verwendet. Stellen Sie sicher, dass Sie die Offsets Ihres Brokers verwenden!

In OnTick() werden zuerst die Zeit-Offsets berechnet und gleich danach GMT und die Ortszeiten von New York, London, Sydney, Moskau und Tokio, um zu zeigen, wie einfach das jetzt ist. Und vergessen Sie nicht: Beachten Sie die Klammern.


Schlussfolgerung

Statt einiger abschließender Worte nur die Ergebnisse von (nur) der Funktion setBokerOffset(), angewandt auf Demokonten verschiedener Broker:

EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 142h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 142h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Time Offset of MetaQuotes Software Corp.: 
US=Winter & EU=Winter (USwinEUwin) = -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin) = -7200



EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 142h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 142h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Time Offset of RoboForex Ltd: 
US=Winter & EU=Winter (USwinEUwin) = -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin) = -7200


EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 142h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 142h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Time Offset of Alpari International: 
US=Winter & EU=Winter (USwinEUwin) = -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin) = -7200


EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 143h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 143h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Time Offset of Pepperstone Group Limited: 
US=Winter & EU=Winter (USwinEUwin) = -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin) = -10800


EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 143h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 143h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Time Offset of Eightcap Pty Ltd: 
US=Winter & EU=Winter (USwinEUwin) = -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin) = -10800

EUR: Fr.2020.10.23 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 143h
USD: Fr.2020.10.30 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 142h
NXT: Fr.2020.11.06 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 143h
USD: Fr.2021.03.12 23:00: hNY:16  hGMT:21  hTC:23  hDiff:-2   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 143h
EUR: Fr.2021.03.26 22:00: hNY:16  hGMT:20  hTC:22  hDiff:-2   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 142h
NXT: Fr.2021.04.02 23:00: hNY:16  hGMT:20  hTC:23  hDiff:-3   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 143h

Time Offset of InstaForex Companies Group: 
US=Winter & EU=Winter (USwinEUwin) = -7200
US=Summer & EU=Summer (USsumEUsum) = -10800
US=Summer & EU=Winter (USsumEUwin) = -7200


EUR: Fr.2020.10.23 21:00: hNY:16  hGMT:20  hTC:21  hDiff:-1   BrokerTime => GMT: 2020.10.23 20:00 => tNY: 2020.10.23 16:00  End-FX after: 141h
USD: Fr.2020.10.30 21:00: hNY:16  hGMT:20  hTC:21  hDiff:-1   BrokerTime => GMT: 2020.10.30 20:00 => tNY: 2020.10.30 16:00  End-FX after: 141h
NXT: Fr.2020.11.06 21:00: hNY:16  hGMT:21  hTC:21  hDiff: 0   BrokerTime => GMT: 2020.11.06 21:00 => tNY: 2020.11.06 16:00  End-FX after: 141h
USD: Fr.2021.03.12 21:00: hNY:16  hGMT:21  hTC:21  hDiff: 0   BrokerTime => GMT: 2021.03.12 21:00 => tNY: 2021.03.12 16:00  End-FX after: 141h
EUR: Fr.2021.03.26 21:00: hNY:16  hGMT:20  hTC:21  hDiff:-1   BrokerTime => GMT: 2021.03.26 20:00 => tNY: 2021.03.26 16:00  End-FX after: 141h
NXT: Fr.2021.04.02 21:00: hNY:16  hGMT:20  hTC:21  hDiff:-1   BrokerTime => GMT: 2021.04.02 20:00 => tNY: 2021.04.02 16:00  End-FX after: 141h

Time Offset of JFD Group Ltd: 
US=Winter & EU=Winter (USwinEUwin) = 0
US=Summer & EU=Summer (USsumEUsum) = -3600
US=Summer & EU=Winter (USsumEUwin) = -3600

Möge der Handel Sie bereichern. :)



Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/9929

Beigefügte Dateien |
DealingWithTime.mqh (52.89 KB)
Letzte Kommentare | Zur Diskussion im Händlerforum (1)
Carl Schreiber
Carl Schreiber | 5 Juli 2023 in 18:49

Die Version von DealingWithTime.mqh v. 1.01 des Artikels „Umgang mit der Zeit (Teil 2): Die Funktionen“ ( https://www.mql5.com/en/articles/9929 ) funktionierte nicht mehr, da MQ die geändert hat Verhalten der CopyTime() -Funktion einige Zeit nach Veröffentlichung dieses Artikels. Jetzt gibt diese Funktion keine zukünftigen Zeitwerte mehr zurück, wenn diese größer sind als TimeCurrent(), das für die Parameter start_time und/oder stop_time angegeben wurde. Stattdessen wird die Öffnungszeit des letzten, aktuellen Balkens als größtmöglicher Wert zurückgegeben.

Da auf diese Weise unter anderem das Ende der FX-Session ermittelt wurde, um den Offset der Broker-Zeit zu ermitteln, führt dies nun zu falschen Werten!

Diese Berechnung wurde in Version 2.03 geändert. Diese neue Version ist jetzt in der CodeBase hier erhältlich: https://www.mql5.com/en/code/45287.

Aber auch die Berechnung der Zeitumstellung wurde komplett geändert, sodass nun auch die komplizierten Zeiten der Zeitumstellung von Sydney (Australien) zurück in die 70er Jahre abgedeckt sind.

Anbei ist auch die Tabelle DST 1975 - 2030.xlsx als Zip-Datei mit allen Zeitänderungen seit den 70er Jahren, damit jeder die korrekte Funktionsweise der Formeln überprüfen kann, hier eine Beispielserie der Tabelle:

Am 01.01.1982 ist in den USA Winterzeit (DST==0) und die nächste Umstellung erfolgt am 25.04.1982, dem letzten (25. des Monats) Sonntag im April (4). Die Tabelle ist bereits nach der geografischen Zeitzone (Spalte A), dann nach der Zeitzone des Jahres (Spalte L, spr=spring, aut=autumn,) und schließlich nach dem Abfragedatum (Spalte C) sortiert. Die Tabelle kann automatisch durch den enthaltenen EA erstellt werden (ein Skript kann nicht im Debug-Modus ausgeführt werden). Test_DST 2.mq5, wenn Sie es im Debug-Modus ausführen und die Zeilen des Journalprotokolls im Debugger kopieren und in ein Tabellenprogramm einfügen; Das Zelltrennzeichen wäre das Leerzeichen.

Außerdem gibt es jetzt eine neue, einfache Funktion SecTillClose() , die Ihnen die verbleibende Zeit in Sekunden (die Zeitwährung von MQ) bis zur Schließung des Forex-Marktes angibt – ohne CopyTime() . Dies ist für diejenigen interessant, die ihre Positionen vor dem Wochenende schließen oder nicht in einem definierten Zeitraum vor dem Wochenende eine neue Position eröffnen möchten.

Der enthaltene Indikator DealingWithTime_TestIndi.mq5 zeigt als Kommentar auf dem Chart nicht nur die Sommer-/Winterzeit von Europa, den USA und Australien (Sydney), sondern auch die aktuelle Zeit und die Zeitverschiebung verschiedener Städte. Hier finden Sie weiters eine Tabelle mit verschiedenen Ortszeiten von Großstädten zum Beispiel für einen Vergleich mit: https://www.timeanddate.com/worldclock/. Sie können die Werte somit jederzeit überprüfen. Dieser Indikator zeigt auch, wie diese Werte ermittelt und verwendet werden (was wird von was subtrahiert oder addiert), so dass es einfacher ist, ihn selbst zu verwenden – Kopieren und Einfügen, die schnellste Form der Programmierung.

Die letzten beiden Zeilen zeigen außerdem die letzte Sekunde der aktuellen FX-Sitzung und die verbleibende Zeit in Stunden (ist einfacher zu beurteilen) und in Sekunden. Wenn in New York freitags um 17:00 Uhr Ortszeit die FX-Sitzung geschlossen ist, gibt es keine gültige Bar mit einer Öffnungszeit um 17:00 Uhr New Yorker Zeit. Daher wird in dieser Funktion 1 Sekunde abgezogen, um die letzte gültige Öffnungszeit des letzten Balkens in der Maklerzeit zu erhalten. Einige Broker beenden ihre FX-Sitzung jedoch einige Minuten früher, indem sie keine Preise mehr bereitstellen und keine Handelsaufträge mehr annehmen.


Programmierung eines Tiefen Neuronalen Netzes von Grund auf mit der Sprache MQL Programmierung eines Tiefen Neuronalen Netzes von Grund auf mit der Sprache MQL
Dieser Artikel soll dem Leser zeigen, wie man ein Deep Neural Network (Tiefes Neuronales Netz) von Grund auf mit der Sprache MQL4/5 erstellt.
Grafiken in der Bibliothek DoEasy (Teil 83): Die Klasse des abstrakten grafischen Standardobjekts Grafiken in der Bibliothek DoEasy (Teil 83): Die Klasse des abstrakten grafischen Standardobjekts
In diesem Artikel werde ich die Klasse des abstrakten grafischen Objekts erstellen. Dieses Objekt soll als Grundlage für die Erstellung der Klasse der grafischen Standardobjekte dienen. Grafische Objekte haben mehrere Eigenschaften. Daher muss ich vor der eigentlichen Erstellung der Klasse des abstrakten grafischen Objekts eine Menge Vorarbeit leisten. Dazu gehört das Festlegen der Eigenschaften in den Enumerationen der Bibliothek.
Bessere Programmierer (Teil 06): 9 Gewohnheiten, die zu effektiver Codierung führen Bessere Programmierer (Teil 06): 9 Gewohnheiten, die zu effektiver Codierung führen
Es geht nicht immer nur darum, den Code zu schreiben, der zu effektiver Programmierung führt. Es gibt bestimmte Gewohnheiten, die meiner Erfahrung nach zu einer effektiven Programmierung führen. In diesem Artikel werden wir einige von ihnen im Detail besprechen. Dieser Artikel ist ein Muss für jeden Programmierer, der seine Fähigkeit verbessern möchte, komplexe Algorithmen mit weniger Aufwand zu schreiben.
Umgang mit Zeit (Teil 1): Die Grundlagen Umgang mit Zeit (Teil 1): Die Grundlagen
Funktionen und Codeschnipsel, die den Umgang mit der Zeit, dem Broker-Offset und der Umstellung auf Sommer- oder Winterzeit vereinfachen und verdeutlichen. Genaues Timing kann ein entscheidendes Element beim Handel sein. Ist die Börse in London oder New York zur aktuellen Stunde bereits geöffnet oder noch nicht, wann beginnt und endet die Handelszeit für den Forex-Handel? Für einen Händler, der manuell und live handelt, ist dies kein großes Problem.