Umgang mit Zeit (Teil 2): Die Funktionen
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:
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:
- Ermittele den Tag im Monat, einen Sonntag, an dem die Zeitumstellung stattfindet.
- Erstelle daraus ein Datum.
- Finde den nächstgelegenen Umstellungssonntag.
- 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 switchFü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:
- Vor der Umstellung auf die Sommerzeit im März.
- Vor der Umstellung auf die Winterzeit im Oktober/November.
- 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:
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:
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:
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
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.
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.