Verwendung des MQL5-Wirtschaftskalenders zur Nachrichtenfilterung (Teil 1): Implementierung von Zeitfenstern vor und nach Nachrichtenereignissen in MQL5
Typische und weniger offensichtliche Probleme
Die meisten Nachrichtenfilter für Handelsroboter erfüllen nur eine einzige Funktion: Sie blockieren neue Trades während der Veröffentlichung von Nachrichten. Das reicht nicht aus.
Bei der Veröffentlichung wichtiger Wirtschaftsdaten kommt es am Markt häufig zu folgenden Entwicklungen:
- Plötzliche Preissprünge,
- Erweiterung des Spread,
- Slippage,
- Dochte, die Stop-Loss-Marken gezielt auslösen.
Offene Positionen bleiben dem Risiko weiterhin ausgesetzt, was den statistischen Vorteil einer Strategie vollständig zunichte machen kann.
Weitere Themen sind unter anderem:
- Compliance bei Prop-Firmen – strenge Zeitfenster vor und nach bestimmten Nachrichtenereignissen müssen eingehalten werden.
- Währungsrelevanz – nicht alle Nachrichten wirken sich auf alle Symbole aus; die Filterung muss währungsspezifisch erfolgen.
- Strategieinstabilität bei Nachrichten – Stopps werden oft eher durch eine Ausweitung des Spreads als durch tatsächliche Kursbewegungen ausgelöst.
- Zustandsverlust nach einem Neustart des EAs oder des VPS – bei vielen Implementierungen wird die Handelslogik während Unterbrechungen nicht beibehalten.
- Kein Testmodus – das Verhalten lässt sich ohne aktuelle Nachrichtenereignisse nur schwer überprüfen.
Die Lösung
Die Lösung besteht darin, mithilfe des nativen MQL5-Wirtschaftskalenders einen strukturierten Nachrichtenfilter zu erstellen.
Das System:
- bewertet die Relevanz von Nachrichten anhand der Währungen des Symbols,
- filtert nach Wichtigkeitsgrad,
- wendet konfigurierbare Puffer vor und nach den Nachrichten an,
- blockiert neue Trades während aktiver Nachrichtenfenster,
- schließt Positionen optional vor Ereignissen mit erheblichen Auswirkungen,
- erkennt die Übergänge beim Beginn und Ende von Nachrichtenfenstern korrekt.
Anstelle eines einfachen Ein-/Aus-Schalters wird dies zu einem risikobewussten Mechanismus.
Geltungsbereich des Artikels
Dies ist Teil 1 eines nachrichtenorientierten Handelssystems für MQL5.
In diesem Artikel geht es um:
- Nachrichten nach ihrer Wichtigkeit zu erkennen,
- Zuordnung von Ereignissen zu Symbolen auf der Grundlage der Währungslogik,
- Festlegung von Zeitfenstern vor und nach der Veröffentlichung von Nachrichten,
- die Verhinderung neuer Trades,
- Schließen von Positionen vor Nachrichtenereignissen mit hoher Bedeutung.
Auf fortgeschrittene Mechanismen zum Stopp-Management und zur Zustandswiederherstellung wird separat eingegangen, um die Umsetzung fokussiert und praxisorientiert zu halten.
Nachfolgend finden Sie ein Ablaufdiagramm, das zusammenfasst, wie sich der Nachrichtenfilter in diesem Artikel verhält.

Der MQL5-Kalender: Der in diesem Artikel verwendete Ansatz und warum er notwendig ist
Früher mussten Händler News-Daten per WebRequest von externen Websites abrufen, um Nachrichtendaten zu erhalten. Dies ist langsam, unzuverlässig und lässt sich nur schwer genau im Backtest nachstellen. Heute bietet MQL5 die MqlCalendar-Funktionen an, mit denen wir Wirtschaftsdaten direkt aus dem Terminal abrufen können.
Diese Methode ist schneller, weil keine HTTP-Anfragen nötig sind. Die Daten werden aus einem lokalen Cache geladen, und News-Ereignisse lassen sich für historische Tests präziser simulieren als mit externen Diensten. Zudem ist der Ansatz robuster, da keine defekten Links, API-Änderungen oder ähnlichen Probleme auftreten.
Einschränkungen und gestalterische Überlegungen
Diese Implementierung ist darauf ausgelegt, ressourcenschonend, deterministisch und mit dem nativen MQL5-Wirtschaftskalender kompatibel zu sein. Daher müssen einige Einschränkungen und Annahmen klar dargelegt werden.- Der Nachrichtenfilter lädt Kalendertermine innerhalb eines rollierenden 24-Stunden-Fensters. Dieser Ansatz minimiert wiederholte Kalenderabfragen und verbessert die Performance zur Laufzeit, bedeutet jedoch auch, dass Ereignisse, die über die nächsten 24 Stunden hinausgehen, nicht vorab geladen werden; der Kalender-Cache muss regelmäßig aktualisiert werden, um die Genauigkeit zu gewährleisten.
- Heuristische Zuordnung von Symbolen zu Währungen. Die Relevanz von Symbolen wird anhand heuristischer Regeln ermittelt, wie beispielsweise der Ermittlung der Basis- und Notierungswährung bei Devisensymbolen sowie der schlüsselwortbasierten Erkennung bei Indizes, Metallen und Rohstoffen. Dies funktioniert zwar bei den üblichen Namenskonventionen der Broker, es ist jedoch nicht gewährleistet, dass alle benutzerdefinierten Symbole abgedeckt sind. Aus diesem Grund steht eine manuelle Währungsüberschreibung zur Verfügung, um Sonderfälle oder proprietäre Symbolformate zu behandeln.
- Alle Zeitvergleiche werden anhand der aktuellen Uhrzeit des Handelsservers durchgeführt. Die Ereignisse im MQL5-Wirtschaftskalender sind ebenfalls mit einem Zeitstempel versehen, der sich auf die Serverumgebung bezieht. Dennoch können aufgrund von Zeitunterschieden zwischen den Servern der Broker, der Umstellung auf Sommerzeit sowie der Bedingungen bei historischen Tests Abweichungen auftreten. Aus diesem Grund sind die Pufferfenster vor und nach den Nachrichten konfigurierbar und nicht fest vorgegeben.
- Diese Implementierung stützt sich vollständig auf den vom Broker bereitgestellten MQL5-Wirtschaftskalender. Wenn der Broker bestimmte Ereignisse, Länder oder Wichtigkeitsstufen nicht korrekt angibt, können diese Ereignisse vom Filter nicht erkannt werden. Das System ist daher nur so vollständig wie die zugrunde liegenden Kalenderdaten, die vom Broker bereitgestellt werden.
Zeitfenster verstehen
Der Nachrichtenfilter reagiert nicht nur auf den genauen Zeitpunkt der Veröffentlichung eines Ereignisses. Stattdessen definiert der Filter ein konfigurierbares Pufferfenster um das Ereignis herum, um der Volatilität vor der Veröffentlichung und der Marktinstabilität nach der Veröffentlichung Rechnung zu tragen. Das Zeitfenster umfasst einen Vorlaufpuffer (Minuten vor dem Ereignis), den eigentlichen Veröffentlichungszeitpunkt des Ereignisses und einen Nachlaufpuffer (Minuten nach dem Ereignis). Jeder Zeitpunkt, der in diesen kombinierten Zeitraum fällt, wird als aktiver Nachrichtenzeitraum behandelt.
Unten sehen Sie eine Abbildung, die veranschaulicht, wie das Nachrichtenfenster funktioniert.

Umsetzung
Schritt 1: Definition der Kernstrukturen
Bevor wir Wirtschaftsnachrichten erkennen oder darauf reagieren können, müssen wir zunächst festlegen, wie die Nachrichtendaten gespeichert werden sollen und wie das System erfasst, ob ein Nachrichtenfenster aktiv ist.
Viele Anfänger-Implementierungen versuchen, bei jedem Tick direkt auf neue Ereignisse zu prüfen, ohne die Daten ordnungsgemäß zu organisieren, was schnell zu unnötiger CPU-Auslastung, wiederholten Berechnungen und einer unübersichtlichen Logik führt, die schwer zu warten oder zu erweitern ist. Um diese Probleme zu vermeiden, definieren wir zunächst einfache und klar abgegrenzte Datenstrukturen, die zwei grundlegende Zwecke erfüllen:- Speichern von Ereignissen aus dem Wirtschaftskalender, die aus MetaTrader abgerufen wurden
- Erfassung, ob sich das Handelssystem derzeit in einem nachrichtenbedingten Sperrfenster befindet
Verwendung der Struktur des MQL5-Wirtschaftskalenders
MetaTrader 5 bietet eine integrierte Struktur namens MqlCalendarValue.
Diese Struktur enthält alle wesentlichen Informationen zu einem wirtschaftlichen Ereignis, darunter den geplanten Zeitpunkt des Ereignisses, die zugehörige Währung, die Bedeutung (gering, mittel oder hoch) sowie die Ist-, Prognose- und die vorherigen Werte.
Anstatt eine eigene Struktur für wirtschaftliche Ereignisse zu definieren, nutzen wir diesen integrierten Typ, um die Kompatibilität mit dem MQL5-Wirtschaftskalender zu gewährleisten und das Risiko von Implementierungsfehlern zu verringern.
Wir speichern Kalenderdaten in einem Array, das später alle relevanten Ereignisse des aktuellen Handelstages enthält.

Szenarien und erwartetes Verhalten
Im Folgenden wird veranschaulicht, wie sich der Nachrichtenfilter bei verschiedenen Symbolen und wirtschaftlichen Ereignissen voraussichtlich verhalten wird. Dies setzt voraus, dass der Wirtschaftskalender ein entsprechendes Ereignis enthält und das konfigurierte Zeitfenster aktiv ist. Die folgenden Abbildungen dienen als Beispiele und zeigen nicht alle möglichen Szenarien, die die Funktionsweise des Filters abdecken.
| Symbol | Ereignis-Währung | Ereignis-Bedeutung | Im Nachrichtenfenster | Erwartetes Ergebnis |
|---|---|---|---|---|
| EURUSD | EUR oder USD | Hoch (Rot) | Ja | Neue Trades blockiert |
| EURUSD | EUR oder USD | Hoch | Nein | Handel erlaubt |
| EURUSD | EUR oder USD | Niedrig (Grau) | Ja | Wenn Nachrichten mit geringer Bedeutung nicht aktiviert sind, bleibt der Handel erlaubt. |
| EURUSD | GBP | Hoch, Niedrig oder Mittel | Ja | Handel erlaubt |
| GOLD | USD | Hoch | Ja | Neue Trades blockiert |
| US100 | USD | Mittel (Gelb) | Ja | Neue Trades gesperrt (sofern Moderate aktiviert ist) |
| GBPJPY | GBP oder JPY | Hoch | Nein | Handel erlaubt |
| AUDUSD | AUD oder USD | Hoch | Nach dem Fenster | Handel erlaubt |
In jedem Fall basiert die Entscheidung ausschließlich auf der Währungsrelevanz und der Übereinstimmung der Zeitfenster. Wenn die Währung eines Ereignisses mit den für das Symbol relevanten Währungen übereinstimmt und der aktuelle Zeitpunkt innerhalb des konfigurierten Pufferfensters liegt, wechselt der Nachrichtenfilter in den aktiven Zustand.
Bei der manuellen Validierung des Strategietesters können die Testdaten verwendet werden, um bestimmte Ereigniszeitpunkte zu simulieren. Dadurch lässt sich das Nachrichtenfenster deterministisch auslösen, ohne dass man auf aktuelle Kalenderdaten angewiesen ist.
Die Währungsrelevanz von Symbolen verstehen
Wirtschaftsnachrichten beziehen sich auf Währungen und nicht auf Handelssymbole. Um festzustellen, ob ein bestimmtes Ereignis relevant ist, ermittelt das System eine Reihe von Währungen, die mit dem aktuell gehandelten Symbol verbunden sind, und vergleicht diese mit der für das Ereignis angegebenen Währung.
Bei standardmäßigen FX-Symbolen werden Basis- und Kurswährung direkt aus dem Symbolnamen extrahiert (beispielsweise sind bei EURUSD EUR und USD).
Bei Indizes, Metallen und Rohstoffen werden vorab festgelegte Schlüsselwort-Heuristiken verwendet, um das Symbol der Währung zuzuordnen, die den größten Einfluss darauf hat (beispielsweise ist GOLD der USD und GER40 der EUR).
Wenn ein Symbol keinem bekannten Muster entspricht, kann in den Eingaben eine manuelle Währungsüberschreibung vorgenommen werden, um explizit festzulegen, welche Währung überwacht werden soll. Ein Wirtschaftsereignis gilt als relevant, wenn seine Währung mit mindestens einer der dem Symbol zugeordneten Währungen übereinstimmt.
Praktischer Schritt
Die Nachrichtenlage im Blick behalten
Ein Nachrichtenfilter sollte nicht bei jedem Tick dieselben Informationen immer wieder neu auswerten.
Um dies zu verhindern, führen wir ein einfaches Statusflag ein, mit dem das System speichern kann, ob es sich derzeit in einem nachrichtenbedingten Sperrfenster befindet.
Zudem wird ein Zeitstempel verwendet, um zu erfassen, wann die Kalenderdaten zuletzt geladen wurden. Dadurch ist es möglich, Kalenderinformationen nur bei Bedarf zu aktualisieren, anstatt sie ständig abzufragen.
Dieser Ansatz trägt dazu bei, die CPU-Auslastung zu senken, die Ausführungseffizienz zu verbessern, die Logik vorhersehbar und leicht nachvollziehbar zu halten sowie eine übersichtliche Protokollierung und Fehlerbehebung zu gewährleisten.
Am Ende dieses Schritts verfügt der Expert Advisor zwar noch nicht über eine funktionsfähige Nachrichtenlogik, aber er hat eine übersichtliche und skalierbare Struktur, auf der die nächsten Schritte aufbauen werden.
//+------------------------------------------------------------------+ //| News Filter Integration.mq5 | //| soloharbinger | //+------------------------------------------------------------------+ #property copyright "soloharbinger" #property link "" #property version "1.01" #include <Trade/Trade.mqh> //=================================================================== // GLOBAL VARIABLES | //=================================================================== MqlCalendarValue TodayEvents[]; // Stores calendar events for the trading day datetime lastCalendarLoad = 0; // TimeStamp of the last calendar update into our above value CTrade trade; // Ctrade instance for order management //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Print("News Filter Demo initialized"); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- // News detection logics will be implemented in the next steps } //+------------------------------------------------------------------+
Schritt 2: Laden und Zwischenspeichern von Ereignissen aus dem Wirtschaftskalender
Sobald die grundlegenden Datenstrukturen eingerichtet sind, besteht die nächste Herausforderung darin, Wirtschaftsnachrichten effizient zu beschaffen.
Der MQL5-Wirtschaftskalender enthält Tausende Ereignissen, die sich über mehrere Jahre erstrecken. Es wäre äußerst ineffizient und unnötig, bei jedem Tick den gesamten Kalender zu durchsuchen. Ein solcher Ansatz verschwendet CPU-Ressourcen und kann einen Expert Advisor erheblich verlangsamen, insbesondere wenn mehrere Instanzen ausgeführt werden.
Um dies zu vermeiden, führen wir einen Mechanismus zum kontrollierten Laden ein, der nur die Ereignisse abruft, die wir tatsächlich benötigen.
Warum Caching notwendig ist
Wirtschaftsnachrichten ändern sich nicht von Sekunde zu Sekunde; sie sind im Voraus geplant und können über viele Ticks hinweg wiederverwendet werden. Aus diesem Grund macht es keinen Sinn, bei jeder Preisaktualisierung immer wieder die Kalenderdaten abzufragen.
Stattdessen laden wir Kalenderereignisse einmalig bei der Initialisierung und anschließend in regelmäßigen Abständen nach einem festgelegten Zeitintervall, um plötzliche Änderungen bei der Veröffentlichung von Marktdaten oder Ereignissen zu berücksichtigen.
Die abgerufenen Daten werden im Array TodayEvents[] gespeichert, wo sie von nachfolgenden Logikfunktionen ohne zusätzlichen Aufwand wiederverwendet werden können.
Festlegen des Zeitraums für das Laden von Ereignissen
Für diesen Artikel definieren wir einen gleitenden 24-Stunden-Zeitraum, der von der aktuellen Serverzeit bis 24 Stunden in die Zukunft reicht.
Dieses Zeitfenster ist groß genug, um Nachrichten vor Börsenbeginn, Ereignisse im Tagesverlauf sowie Veröffentlichungen gegen Ende des Handelstages oder über Nacht zu erfassen. Die genaue Dauer des Zeitraums lässt sich anpassen, doch 24 Stunden bieten einen klaren und einsteigerfreundlichen Ausgangspunkt.
Die Funktion Kalenderereignis laden
Wir kapseln die Logik zum Abrufen des Kalenders in einer eigenen Funktion ein.
Dadurch bleibt der Code übersichtlich und es wird verhindert, dass die Kalenderlogik über den gesamten EA verstreut ist.
Die Funktion prüft, ob der Kalender kürzlich geladen wurde, überspringt das erneute Laden, wenn die zwischengespeicherten Daten noch gültig sind, fragt den Wirtschaftskalender für den definierten Zeitraum ab und speichert die Ergebnisse im Array TodayEvents[].
Zum jetzigen Zeitpunkt wird noch keine Filterung angewendet. Wir erfassen lediglich Rohdaten zu Ereignissen.
//=================================================================== // Load calendar (24-hour horizon) //=================================================================== void LoadTodayCalendarEvents() { datetime now = TimeCurrent(); datetime fromTime = now; datetime toTime = now + 24 * 3600; // Load next 24 hours ArrayFree(TodayEvents); int count = CalendarValueHistory(TodayEvents, fromTime, toTime); PrintFormat("Loaded %d calendar records for the next 24 hours.", count); if(count <= 0) { // Still update timestamp to prevent constant reloading attempts lastCalendarLoad = now; return; } // Debug: print first few events for verification for(int i = 0; i < MathMin(count, 5); i++) { MqlCalendarEvent ev; if(CalendarEventById(TodayEvents[i].event_id, ev)) { PrintFormat("Event %d: %s | Time: %s | Importance: %d", i, ev.name, TimeToString(TodayEvents[i].time), ev.importance); } } lastCalendarLoad = now; }

Schritt 3: Intelligente Währungsfilterung
Ein häufiges Ärgernis bei einfachen Nachrichtenfiltern ist die unnötige Blockierung von Trades.
Wenn ein Expert Advisor beispielsweise mit EURUSD handelt, sollte er den Handel nicht einfach deshalb einstellen, weil eine wichtige Nachricht zum australischen Dollar (AUD) veröffentlicht wird. Leider behandeln viele vereinfachte Implementierungen alle Nachrichten als gleichermaßen gefährlich, was zu verpassten Handelsmöglichkeiten und unnötigen Ausfallzeiten führt.
Um dieses Problem zu lösen, führen wir eine intelligente Währungsfilterung ein.
Das Ziel dieses Schritts ist einfach: Reagieren Sie nur auf Nachrichtenereignisse, die für das gehandelte Symbol tatsächlich relevant sind.
Warum die Währungsfilterung wichtig ist
Jedes wirtschaftliche Ereignis steht in Zusammenhang mit einem bestimmten Land und einer bestimmten Währung.
Gleichzeitig ist jedes Handelssymbol von einer oder mehreren zugrunde liegenden Währungen beeinflusst.
Wenn wir diese beiden nicht richtig miteinander abgleichen:
- Der EA kann den Handel unterbrechen, obwohl dies nicht erforderlich wäre, oder – schlimmer noch – Nachrichten ignorieren, die sich tatsächlich auf das Symbol auswirken.
Ein Nachrichtenfilter muss daher zwei Fragen beantworten:
- Welche Währungen beeinflussen dieses Handelssymbol, und zu welcher Währung gehört dieses Nachrichtenereignis?
Erst wenn beide übereinstimmen, sollte das Ereignis als relevant angesehen werden.
Relevante Währungen aus dem Handelssymbol extrahieren
Zunächst ermitteln wir, welche Währungen das aktuelle Symbol beeinflussen.
Bei Standard-Devisenpaaren ist dies ganz einfach: Die ersten drei Buchstaben stehen für die Basiswährung, die nächsten drei Buchstaben für die Gegenwährung.
Zum Beispiel:
- EURUSD → EUR und USD oder GBPJPY → GBP und JPY.
Allerdings folgen nicht alle Instrumente diesem Format.
Indizes, Metalle und Rohstoffe erfordern oft eine besondere Handhabung.
Um das System flexibel zu halten, kapseln wir diese Logik in einer Funktion namens GetRelevantCurrencies().
Diese Funktion extrahiert automatisch die Basis- und Notierungswährungen für Devisenpaare, wendet eine einfache Schlüsselworterkennung für Indizes und Rohstoffe an, ermöglicht eine manuelle Übersteuerung, wenn die automatische Erkennung nicht ausreicht, und gibt eine durch Kommas getrennte Liste der für das Symbol relevanten Währungen zurück.
//=================================================================== // Helper: Return CSV list of relevant currencies for symbol //=================================================================== string GetRelevantCurrencies(string symbol) { // 1. Check Manual Override if(StringLen(SymbolCurrencyOverride) > 0) { return SymbolCurrencyOverride; } string upper = symbol; StringToUpper(upper); // 2. Standard Forex Pair Logic (e.g. EURUSD -> EUR,USD) if(StringLen(symbol) == 6) { string baseCurr = StringSubstr(upper, 0, 3); string quoteCurr = StringSubstr(upper, 3, 3); return baseCurr + "," + quoteCurr; } // 3. Heuristics for Indices/Commodities if(StringFind(upper, "GER") != -1 || StringFind(upper, "DE40") != -1 || StringFind(upper, "DAX") != -1) return "EUR"; if(StringFind(upper, "UK") != -1 || StringFind(upper, "FTSE") != -1) return "GBP"; if(StringFind(upper, "US30") != -1 || StringFind(upper, "DJ") != -1) return "USD"; if(StringFind(upper, "SPX") != -1 || StringFind(upper, "US500") != -1) return "USD"; if(StringFind(upper, "NAS") != -1 || StringFind(upper, "US100") != -1) return "USD"; if(StringFind(upper, "XAU") != -1 || StringFind(upper, "GOLD") != -1) return "USD"; if(StringFind(upper, "XAG") != -1 || StringFind(upper, "SILVER") != -1) return "USD"; if(StringFind(upper, "OIL") != -1 || StringFind(upper, "WTI") != -1 || StringFind(upper, "BRENT") != -1) return "USD"; if(StringFind(upper, "JPN") != -1 || StringFind(upper, "NIK") != -1) return "JPY"; if(StringFind(upper, "AUD") != -1) return "AUD"; if(StringFind(upper, "CAD") != -1) return "CAD"; if(StringFind(upper, "NZD") != -1) return "NZD"; if(StringFind(upper, "CHF") != -1) return "CHF"; if(StringFind(upper, "EUR") != -1) return "EUR"; if(StringFind(upper, "GBP") != -1) return "GBP"; if(StringFind(upper, "JPY") != -1) return "JPY"; // Fallback: if we can't guess, return nothing (safe mode) return ""; }
Zu diesem Zeitpunkt weiß der EA zwar, welche Währungen für das aktuelle Symbol relevant sind, er weiß jedoch noch nicht, zu welcher Währung ein Nachrichtenereignis gehört.
Das klären wir als Nächstes.
Bestimmung der Währung eines Nachrichtenereignisses.
In den Einträgen des Wirtschaftskalenders wird kein Währungscode wie USD oder EUR direkt gespeichert; stattdessen ist jedes Ereignis mit einer Länderkennung verknüpft. Um die Währung des Ereignisses zu ermitteln, müssen wir die Länderangaben des Ereignisses abrufen und die diesem Land zugeordnete Währung auslesen.
MQL5 bietet mit der Funktion CalendarCountryById() eine direkte und zuverlässige Möglichkeit, dies zu bewerkstelligen.
Wir kapseln diese Logik in einer Hilfsfunktion namens GetCurrencyFromEventDirect().
//=================================================================== // Utility: Get currency from calendar event (via Country ID) //=================================================================== string GetCurrencyFromEventDirect(const MqlCalendarEvent &ev) { MqlCalendarCountry country; if(CalendarCountryById(ev.country_id, country)) { return country.currency; // Returns "USD", "EUR", etc. } return ""; }
Mit dieser Funktion können wir
einen Kalendertermin in einen konkreten Währungscode wie USD, EUR oder GBP umwandeln.
Was wir bisher erreicht haben
Am Ende dieses Schritts kann der EA feststellen, welche Währungen das aktuelle Symbol beeinflussen, er kann bestimmen, zu welcher Währung ein Nachrichtenereignis gehört, und die Grundlage dafür ist geschaffen, irrelevante Nachrichtenereignisse zu ignorieren.
Bislang wurde noch keine Logik zur Handelsblockierung angewendet.
Zum jetzigen Zeitpunkt führt das System noch keine einschneidenden Maßnahmen durch; es erkennt lediglich die Relevanz, was für jeden intelligenten Nachrichtenfilter wichtig ist.Anschließend kombinieren wir die zwischengespeicherten Kalenderereignisse (Schritt 2) und die entsprechenden Symbolwährungen (Schritt 3), um festzustellen, ob ein relevantes Ereignis derzeit aktiv ist. In diesem Zusammenhang legen wir Zeitfenster fest und wenden eine Filterung nach Bedeutungsstufe an
Schritt 4: Relevante Nachrichtenereignisse erkennen und vermeiden
Da wir nun Ereignisse aus dem Wirtschaftskalender laden und zwischenspeichern können (Schritt 2) und feststellen können, welche Währungen für das Handelssymbol relevant sind (Schritt 3), können wir nun prüfen, ob es derzeit relevante Wirtschaftsnachrichten gibt, die dieses Symbol betreffen. In diesem Stadium erkennt der Expert Advisor nur relevante Nachrichten und die Zeitspanne, die rund um den Veröffentlichungszeitpunkt gemieden werden soll.
Erkennungsregeln auf hoher Ebene
Ein Nachrichtenereignis gilt nur dann als relevant, wenn es innerhalb der zwischengespeicherten Kalenderdaten stattfindet, der Wichtigkeitsgrad des Ereignisses unseren Filtereinstellungen entspricht, die Währung des Ereignisses mit einer der für das Symbol relevanten Währungen übereinstimmt und der aktuelle Zeitpunkt innerhalb des definierten Zeitfensters vor und nach der Veröffentlichung der Nachricht liegt.
Erst wenn alle vier Bedingungen erfüllt sind, meldet die Funktion, dass ein Nachrichtenfenster aktiv ist.
Kalenderdaten sicher neu laden
Bevor wir Termine einlesen, stellen wir sicher, dass die Kalenderdaten noch gültig sind.
Kalenderdaten werden nur dann neu geladen, wenn sie zuvor noch nie geladen wurden oder die zwischengespeicherten Daten älter sind als ein festgelegtes Intervall (beispielsweise 6 Stunden).
Dadurch wird verhindert, dass bei jedem Tick unnötige Aufrufe der Kalenderfunktionen erfolgen und eine neue Aktualisierung der Nachrichten übersehen wird.
Erkennungsfunktion unten
//=================================================================== // Core Detection Logic // Returns true if 'now' is inside a news window for the specific symbol //=================================================================== bool isUpcomingNews(const string symbol) { datetime now = TimeCurrent(); // A. Cache Management if(lastCalendarLoad == 0 || (now - lastCalendarLoad) > (datetime)CacheReloadHours * 3600) { LoadTodayCalendarEvents(); } if(ArraySize(TodayEvents) == 0) return false; // B. Testing Simulation if(EnableNewsTesting) { if(TestNewsNow) return true; datetime t = StringToTime(TestNewsTime); if(t > 0) { datetime start = t - TestNewsDuration * 60; datetime end = t + TestNewsDuration * 60; if(now >= start && now <= end) return true; } } // C. Optimization: Prepare Currency List OUTSIDE the loop string relevant = GetRelevantCurrencies(symbol); if(StringLen(relevant) == 0) return false; string currencyArray[]; int currencyCount = StringSplit(relevant, ',', currencyArray); for(int k = 0; k < currencyCount; k++) { StringTrimLeft(currencyArray[k]); StringTrimRight(currencyArray[k]); StringToUpper(currencyArray[k]); } // D. Event Scan for(int i = 0; i < ArraySize(TodayEvents); i++) { MqlCalendarEvent ev; // Retrieve event details from ID if(!CalendarEventById(TodayEvents[i].event_id, ev)) continue; // 1. Importance Filter bool okImportance = false; switch(NewsImportanceMode) { case NEWS_HIGH_ONLY: okImportance = (ev.importance == CALENDAR_IMPORTANCE_HIGH); break; case NEWS_MODERATE_ONLY: okImportance = (ev.importance == CALENDAR_IMPORTANCE_MODERATE); break; case NEWS_HIGH_AND_MODERATE: okImportance = (ev.importance == CALENDAR_IMPORTANCE_HIGH || ev.importance == CALENDAR_IMPORTANCE_MODERATE); break; } if(!okImportance) continue; // 2. Currency Relevance Filter string eventCurrency = GetCurrencyFromEventDirect(ev); if(StringLen(eventCurrency) == 0) continue; bool affect = false; for(int j = 0; j < currencyCount; j++) { if(eventCurrency == currencyArray[j]) { affect = true; break; } } if(!affect) continue; // 3. Time Window Check datetime eventTime = TodayEvents[i].time; datetime windowStart = eventTime - (NewsMinutesBefore * 60); datetime windowEnd = eventTime + (NewsMinutesAfter * 60); if(now >= windowStart && now <= windowEnd) { // Optional: Print once per detection to avoid log spam static string lastDetectedKey = ""; string key = ev.name + "|" + TimeToString(eventTime); if(key != lastDetectedKey) { PrintFormat("NEWS: %s | Time: %s | Currency: %s", ev.name, TimeToString(eventTime), eventCurrency); lastDetectedKey = key; } return true; } } return false; }
Vereinfachtes Erkennen durch den EA
Um den Rest des gesamten Expert Advisors übersichtlich und lesbar zu halten, verpacken wir die Erkennungslogik in eine einfache Schnittstellenfunktion.
Dadurch wird sichergestellt, dass die Erkennungslogik zentralisiert bleibt.
// Wrapper for external calls bool IsNewsTime(string symbol) { return isUpcomingNews(symbol); }
An dieser Stelle, an der der Nachrichtenfilter in anderen Teilen von EA benötigt wird, können wir getrost etwa Folgendes tun:
if(IsNewsTime(_Symbol))
{
// Nachrichten erkennen
}
Schritt 5: Neue Trades während Nachrichtenphasen blockieren
Zum jetzigen Zeitpunkt ist der Expert Advisor bereits in der Lage, relevante wirtschaftliche Nachrichtenereignisse präzise zu erkennen. Der letzte Schritt von Teil 1 besteht darin, diese Erkennungslogik zu nutzen, um neue Handelspositionen während eines festgelegten Zeitfensters vor und nach Nachrichtenereignissen zu blockieren.Dieser Ansatz passt perfekt zu den Anforderungen von Prop-Firmen, bei denen die häufigste Einschränkung lautet: Während der Veröffentlichung von Nachrichten mit großer Auswirkung dürfen keine neuen Positionen eröffnet werden.
Wichtig ist, dass bestehende Trades in keiner Weise verändert werden; das System verhindert lediglich neue Positionseröffnungen, solange die neuen Bedingungen gelten.
Warum wir nur Einträge blockieren (Teil 1)
Das Blockieren neuer Einstiege ist die einfachste und sicherste Form des Schutzes vor Nachrichtenauswirkungen, für Anfänger leicht verständlich, mit den Regeln von Prop-Firmen vereinbar und greift nicht in bestehende Strategien ein.
Indem wir Teil 1 ausschließlich auf die Blockierung von Einstiegen beschränken, stellen wir sicher, dass keine unbeabsichtigten Nebenwirkungen auftreten, keine unerwünschten Eingriffe in offene Trades entstehen und eine solide Grundlage für später zu implementierende, komplexere Funktionen geschaffen wird.
Wichtig: Erforderliche Eingaben für einen vollständigen Nachrichtenfilter
Um den Nachrichtenfilter so zu gestalten, dass er konfigurierbar ist und für verschiedene Handelsstile und Prop-Firmen genutzt werden kann, führen wir eine kleine Auswahl an Eingabeparametern ein.
Diese Einstellungen legen fest, ob der Nachrichtenfilter aktiviert ist, welche Wichtigkeitsstufen von Nachrichten berücksichtigt werden und wie viele Minuten vor und nach einer Nachricht der Handel gesperrt werden soll.
//=================================================================== // INPUTS //=================================================================== input group "News Filter Configuration" input bool EnableNewsFilter = false; // Enable Economic News Filter input int NewsMinutesBefore = 5; // Minutes before news to restrict input int NewsMinutesAfter = 5; // Minutes after news to restrict input bool RestrictNewTradesDuringNews = true; // Block new trades during news window input bool CloseOpenTradesBeforeHighImpactNews = false; // Close all trades before news input string SymbolCurrencyOverride = ""; // Manual currency override e.g. "USD,JPY" enum ENUM_NEWS_IMPORTANCE_MODE { NEWS_HIGH_ONLY = 0, NEWS_MODERATE_ONLY, NEWS_HIGH_AND_MODERATE }; input ENUM_NEWS_IMPORTANCE_MODE NewsImportanceMode = NEWS_HIGH_ONLY; // Importance levels // Cache reload interval input int CacheReloadHours = 6; // Reload calendar cache (hours) // News Testing helpers (Simple simulation for Part 1 demonstration) input group "Testing Parameters" input bool EnableNewsTesting = false; // Enable news testing simulation with Current symbol input string TestNewsTime = "2025.12.15 14:30:00"; // Simulated news time (yyyy.MM.dd HH:mm:ss) input int TestNewsDuration = 10; // Simulated window length (minutes) input bool TestNewsNow = false; // Manual immediate trigger
Dank dieser Eingabewerte lässt sich der EA problemlos an unterschiedliche Regeln von Prop-Firmen, konservative oder aggressive Handelsstile sowie das brokerspezifische Volatilitätsverhalten anpassen.

| Eingabename | Verwendungszwecke/Zwecke |
|---|---|
| Enable Economic News Filter | Schaltet den Nachrichtenfilter für den EA vollständig ein oder aus |
| Minutes before News to restrict | Legt fest, wie viele Minuten vor dem Nachrichtenereignis der Filter aktiv wird |
| Minutes after News to restrict | Legt fest, wie viele Minuten nach dem Nachrichtenereignis der Filter noch aktiv bleibt |
| Block new trades during news window | Eröffnung neuer Trades während des Nachrichtenfensters sperren |
| Close all trades before news | Bestehende Position schließen, sobald ein relevantes Nachrichtenfenster beginnt |
| Manual currency override | Hier wird die zu überwachende Währung manuell angegeben, wenn die automatische Erkennung nicht ausreicht (bitte leer lassen, wenn die automatische Erkennung funktioniert) |
| Importance level | Wählen Sie aus, welche Wichtigkeitsstufen für Nachrichten berücksichtigt werden sollen (hoch, mittel oder beide) |
| Reload Calendar Cache | Legt fest, wie oft die Kalenderdaten aktualisiert werden |
| Enable News testing simulation | Ermöglicht ausschließlich die manuelle Auslösung von Nachrichten |
| Simulated News time | Gibt den Zeitpunkt des simulierten Nachrichtenereignisses in einem beliebigen Format JJJJ/MM/TT hh/mm/ss in der Vergangenheit an |
| Simulated news window length [minutes] | Legt die Dauer des aktiven Fensters für ein simuliertes Nachrichtenereignis fest |
| Manual immediate trigger | Löst sofort ein simuliertes Nachrichtenfenster zum Testen aus |
Blockieren von neuen Trades mithilfe von Erkennungslogik
Da die Erkennung bereits in Schritt 4 implementiert wurde, ist das Blockieren von Transaktionen ein Kinderspiel. Anstatt die News-Logik in die Handelsfunktionen zu integrieren, verwenden wir eine einzige Gate-Bedingung, bevor wir eine neue Position eröffnen.
Dadurch bleibt die Handelslogik übersichtlich und gut lesbar.
//=================================================================== // Check if new trades are allowed (Main Filter Gate) //=================================================================== bool CanOpenNewTrade(string symbol) { if(!EnableNewsFilter) return true; if(!RestrictNewTradesDuringNews) return true; if(IsNewsTime(symbol)) { return false; // Block trade } return true; }
Diese Funktion beantwortet eine einfache Frage:
- Ist es derzeit sicher, eine neue Position zu eröffnen?
Anwendung dieser Sperrprüfung in der Handelslogik
Wo auch immer Ihr EA normalerweise Trades eröffnet, fügen Sie einfach diesen Check ganz oben ein, zum Beispiel:
if(!CanOpenNewTrade(_Symbol)) { // News window active — do not open new trades return; } // Normal trade entry logic continues here
Durch diese Überprüfung bleibt die Logik für den Handelseinstieg übersichtlich und zentralisiert.
Optional: Alle Trades vor dem Nachrichtenfenster schließen
Der folgende Codeausschnitt ermöglicht es dem Expert Advisor, alle Trades für das Symbol zu schließen, sobald das Sperrfenster vor der Veröffentlichung von Nachrichten beginnt.
Der Codeausschnitt nutzt dieselbe Erkennungslogik, die bereits implementiert wurde.
Die Eingabe dieser Funktion ist bereits in den oben angegebenen Eingaben enthalten.
//=================================================================== // CloseAllTradesForSymbol // Implements safe reverse iteration and CTrade closing //=================================================================== void CloseAllTradesForSymbol(string symbol) { // Iterate backward to safely close multiple positions for(int i = PositionsTotal() - 1; i >= 0; i--) { ulong ticket = PositionGetTicket(i); if(ticket == 0) continue; if(!PositionSelectByTicket(ticket)) continue; // Filter by symbol if(PositionGetString(POSITION_SYMBOL) != symbol) continue; // Close Logic bool closed = trade.PositionClose(ticket); if(closed) { PrintFormat("Closed position #%d on %s due to news.", ticket, symbol); } else { PrintFormat("Failed to close #%d. Error: %d", ticket, GetLastError()); } } }
Trigger-Logik [innerhalb von onTick()]
//=================================================================== // OnTick //=================================================================== void OnTick() { // Static latch to ensure we don't try to close trades multiple times per window static bool tradesClosedForThisNewsWindow = false; // 2. Main News Logic if(EnableNewsFilter) { bool isNews = IsNewsTime(_Symbol); // Feature: Close open trades before news if enabled if(CloseOpenTradesBeforeHighImpactNews && isNews) { if(!tradesClosedForThisNewsWindow) { Print("News window started -> Closing open trades."); CloseAllTradesForSymbol(_Symbol); tradesClosedForThisNewsWindow = true; // Latch } } else if(!isNews) { // Reset latch when we are out of the news window tradesClosedForThisNewsWindow = false; } } }
Was das bringt
- Schließt Positionen, bevor die Volatilität zunimmt.
- Es wird die vorhandene Erkennungslogik genutzt.
- Wird einmal pro Nachrichtenfenster ausgelöst.
- Völlig optional [Eingabe auf true oder false setzen].
- Für Prop-Firmen geeignet.
- In Teil 2 werden wir eine vorübergehende Deaktivierung und Reaktivierung von Stop-Loss- und Take-Profit-Aufträgen rund um ein eingeschränktes Nachrichtenfenster implementieren, um den strategischen Vorteil zu bewahren und vorzeitige Ausstiege zu vermeiden.
Ende von Teil 1
Zu diesem Zeitpunkt haben wir einen funktionierenden Nachrichtenfilter entwickelt, der effizient, symbolorientiert, entsprechend der Vorgaben von Prop-Firmen, und einsteigerfreundlich ist sowie bereit ist, Einstiege zu blockieren und Positionen zu schließen.
Teil 1 kann völlig für sich allein stehen.
Schlussfolgerung
In diesem Artikel haben wir ein vollständiges und funktionsfähiges Nachrichtenfiltersystem in MQL5 entwickelt – angefangen bei den Grundlagen bis hin zu einer praktischen Lösung.
Anstatt sich auf fest programmierte Zeiten oder eine Nachrichtenfilterung auf Basis von Webanfragen zu stützen, wurde das System auf der Grundlage des MQL5-Wirtschaftskalenders entwickelt, wobei besonderes Augenmerk auf Leistung, Relevanz und Übersichtlichkeit gelegt wurde. Kalenderereignisse werden effizient geladen, logisch zwischengespeichert, nach Wichtigkeit gefiltert und nur mit Währungen abgeglichen, die tatsächlich Auswirkungen auf das gehandelte Symbol haben.
Durch die Trennung der Erkennung von Nachrichten von der Durchsetzung der Handelsregeln bleibt die Logik leicht verständlich, leicht zu testen und leicht zu erweitern. Das Endergebnis ist ein übersichtlicher Mechanismus zur Handelssperre, der neue Trades während konfigurierbarer Zeitfenster vor und nach der Veröffentlichung von Nachrichten verhindert, mit einer optionalen Regel zum Schließen offener Positionen, bevor die durch die Nachrichten ausgelöste Volatilität einsetzt.
Dieser Ansatz eignet sich besonders gut für Handelsumgebungen von Prop-Firmen, in denen die häufigste Anforderung darin besteht, während Zeiträumen mit Nachrichtenbeschränkungen einfach keine Positionen zu eröffnen. Ohne offene Positionen zu ändern oder in das Handelsmanagement einzugreifen – und genau deshalb arbeiten wir in Teil 2 daran, Stopps nur während des Zeitfensters für Nachrichten vorübergehend zu entfernen, damit sie während der Nachrichtenzeit nicht ausgelöst oder verändert werden und somit gegen eine Regel verstoßen; selbst das vorzeitige Schließen von Trades kann den Ablauf der Strategie stören. Insgesamt gewährleistet das System die Einhaltung von Vorschriften und bietet Schutz, unabhängig von der jeweiligen Strategie.
Noch wichtiger ist, dass alles, was ich in diesem Artikel umgesetzt habe, für sich genommen voll funktionsfähig ist. Teil 1 bietet einen umfassenden Nachrichtenfilter, der in jeden Expert Advisor integriert und sofort zur Durchsetzung von nachrichtenbasierten Handelsbeschränkungen genutzt werden kann.
Im nächsten Teil dieser Reihe werden wir auf dieser Grundlage aufbauen und fortgeschrittenere Verhaltensweisen bei Nachrichtenereignissen untersuchen, wie beispielsweise die Steuerung des Handelsmanagements und zusätzliche Schutzmechanismen.
Das hier vorgestellte System löst das Kernproblem bereits auf elegante Weise.
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/21235
Warnung: Alle Rechte sind von MetaQuotes Ltd. vorbehalten. Kopieren oder Vervielfältigen untersagt.
Dieser Artikel wurde von einem Nutzer der Website verfasst und gibt dessen persönliche Meinung wieder. MetaQuotes Ltd übernimmt keine Verantwortung für die Richtigkeit der dargestellten Informationen oder für Folgen, die sich aus der Anwendung der beschriebenen Lösungen, Strategien oder Empfehlungen ergeben.
Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
MetaTrader 5 – Blaupause für maschinelles Lernen (Teil 7): Von verstreuten Experimenten zu reproduzierbaren Ergebnissen
Eine alternative Log-datei mit der Verwendung der HTML und CSS
Bivariate Copulas in MQL5 (Teil 3): Implementierung und Optimierung von Mixed-Copula-Modellen in MQL5
- 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.
Bitte beantwortet Fragen zu diesem Artikel hier und nicht in privaten Nachrichten. Genau dafür ist dieses Thema gedacht.
Natürlich hat er zuerst privat gefragt, und ich dachte, ich würde dort auch antworten.
Jamshid fragte, warum die in diesem Bild abgedruckten und gezeigten bevorstehenden Nachrichtenereignisse nicht mit den aktuellen Nachrichtenereignissen von Forex Factory übereinstimmen.
Meine Antwort:
Diese Ausgabe entsprach dem aktuellen Wirtschaftskalender zum Zeitpunkt meiner Erstellung des Beitrags. Ich habe zu Debugging-Zwecken einige Nachrichten aus dem zwischengespeicherten Kalender ausgedruckt, um zu überprüfen, ob mein zwischengespeicherter Kalender korrekt ist und funktioniert:Wenn Sie den Code selbst kompilieren und den Expert Advisor auf Ihr Chart ziehen, werden Ihnen auf der Registerkarte „Expert“ ebenfalls etwa 5 aktuelle bevorstehende Nachrichtenereignisse angezeigt, damit Sie sehen können, dass die zwischengespeicherten Ereignisse funktionieren.
Natürlich wird es Unterschiede geben, da sich die Zeit zum Zeitpunkt des Verfassens dieses Beitrags und zu jedem späteren Zeitpunkt ändern wird!
Ein weiterer Grund für mögliche Abweichungen ist, dass Forex Factory und MQL5 nicht exakt identisch sind; es gibt einige Unterschiede hinsichtlich der Wichtigkeitsstufe, und manchmal weist MQL5 eine etwas größere Anzahl von Nachrichten mit geringer oder mittlerer Auswirkung auf.
Tolle Arbeit.
Eine großartige Artikelserie.
Genau das, was alle Algo-Trader, die bei Eval-Prop-Firmen handeln, für ihre Expert Advisors brauchen.
Ich hoffe, dass jeder, der davon Gebrauch macht, zumindest einen Kommentar hinterlässt.
Ein weiterer Grund, warum es Unterschiede geben könnte, ist, dass Forex Factory und MQL5 nicht genau identisch sind; es gibt einige Unterschiede hinsichtlich der Einstufung der Nachrichten nach ihrer Bedeutung, und manchmal gibt es auf MQL5 etwas mehr Nachrichten mit geringer oder mittlerer Auswirkung
Forum zu Trading, automatisierten Handelssystemen und dem Testen von Handelsstrategien
Bibliotheken: Kalender
fxsaber, 21.03.2024, 09:49 Uhr
Leider kann man dem aktuellen Kalender nicht trauen.
Hier ist das Fehlen einer wichtigen CHF-Nachricht in der Liste der Ereignisse und die entsprechende Marktreaktion darauf.
Und hier ist ein anderer Kalender, in dem diese Nachricht aufgeführt ist.
Ich hoffe, dass jeder, der sie nutzt, zumindest einen Kommentar hinterlässt.