So baust du einen News-Filter in deinen MT4-Expert-Advisor ein
Ein Expert Advisor, der mitten in den US-Arbeitsmarktbericht (Non-Farm Payrolls) oder einen Zinsentscheid hinein handelt, folgt nicht mehr seiner Strategie: Er wirft eine Münze, und das bei breitem Spread. Ein News-Filter verhindert das. Er setzt neue Einstiege einige Minuten vor und nach den Veröffentlichungen aus, die den Markt bewegen, und lässt die Strategie den Rest der Zeit ungestört arbeiten.
MetaTrader 5 hat einen Kalender eingebaut. MetaTrader 4 nicht, der EA muss sich die News also selbst besorgen. Diese Anleitung nutzt die kostenlose Wirtschaftskalender-API von ShowMyTrades: kein Konto, kein API-Schlüssel, eine einzige URL, die du im Terminal freigibst, und eine Include-Datei, die in jeden EA passt.
🧭 Das baust du
alle 15 Minuten bei jedem Tick
┌──────────────────────┐ ┌─────────────────────────────────┐
│ News der nächsten │ ──► │ Liegt eine Veröffentlichung │
│ 2 Tage herunterladen │ │ im Fenster [-30 Min., +30 Min.] │
│ (CSV, eine Anfrage) │ │ um den aktuellen Zeitpunkt? │
└──────────────────────┘ │ ja → keine neuen Einstiege │
│ nein → Strategie ausführen │
└─────────────────────────────────┘
| Entscheidung | Standard im Code | Warum |
|---|---|---|
| Welche Währungen | EUR,USD | Die beiden Seiten des Paars, das du handelst. Leer heißt: alle neun Hauptwährungen |
| Welche Wichtigkeit | high | high,medium für einen vorsichtigeren Filter |
| Pause davor | 30 Minuten | Vor der Zahl weiten sich die Spreads, und die Liquidität dünnt aus |
| Pause danach | 30 Minuten | In diese Zeit fallen die erste Reaktion und die Gegenbewegung |
| Download-Intervall | 15 Minuten | Der Kalender ändert sich nur wenige Male am Tag, und die API speichert ohnehin 15 Minuten zwischen |
🔑 Schritt 1: Die Adresse in MetaTrader freigeben
WebRequest(), die MQL4-Funktion für Downloads aus dem Internet, spricht nur mit Adressen, die du freigegeben hast. Öffne im Terminal Extras → Optionen → Expert Advisors (Tools → Options → Expert Advisors), setze den Haken bei WebRequest für die aufgeführten URLs erlauben (Allow WebRequest for listed URL) und trage ein:
https://showmytrades.com
Fehlt dieser Schritt, liefert der Download -1 mit Fehler 4060. Die Include-Datei schreibt dann einen Hinweis in den Reiter „Experten“ (Experts), damit du nicht rätseln musst, warum der Filter stumm bleibt.
📄 Schritt 2: Die Include-Datei speichern
Speichere den folgenden Code als SMT_NewsFilter.mqh im Ordner MQL4\Include deines Terminals. Den Ordner öffnest du über Datei → Dateiordner öffnen (File → Open Data Folder). Es ist dieselbe Datei wie in der API-Referenz, und sie lässt sich auch in MQL5 ohne jede Änderung kompilieren.
//+------------------------------------------------------------------+
//| SMT_NewsFilter.mqh - News-Filter für MT4 und MT5 |
//| Daten: https://showmytrades.com/api/public/calendar/v1 (gratis) |
//| Doku: https://showmytrades.com/docs/api/economic-calendar |
//| Setup: Extras > Optionen > Expert Advisors > WebRequest für |
//| https://showmytrades.com erlauben |
//+------------------------------------------------------------------+
#property strict
input string SMT_Currencies = "EUR,USD"; // News: Währungen (kommagetrennt, leer = alle)
input string SMT_Impact = "high"; // News: Wichtigkeit (high | high,medium | all)
input int SMT_MinutesBefore = 30; // News: Pause vor einer Veröffentlichung (Minuten)
input int SMT_MinutesAfter = 30; // News: Pause nach einer Veröffentlichung (Minuten)
input int SMT_RefreshMinutes = 15; // News: Download-Intervall (Minuten, min. 15)
datetime smt_eventTime[];
string smt_eventTitle[];
datetime smt_nextDownload = 0;
long smt_serverTime = 0; // UTC-Zeit des Servers (Unix-Sekunden) beim letzten Download
uint smt_syncTick = 0; // GetTickCount() im selben Moment
bool smt_clockSynced = false;
//--- die echte UTC-Zeit: die Uhr des Servers plus die seit dem Download vergangenen
//--- Millisekunden, gezählt mit GetTickCount(). Der Zähler kennt keine Zeitzonen, keine
//--- Sommerzeit und keine Uhrkorrekturen auf dem Rechner (die uint-Subtraktion übersteht
//--- auch seinen Überlauf). Vor dem ersten Download dient TimeGMT() als Ersatz. Nie
//--- TimeCurrent(): Der GMT-Offset des Brokers ist unbekannt und springt mit der Sommerzeit.
datetime SMT_Now()
{
if(!smt_clockSynced) return TimeGMT();
uint elapsedMs = GetTickCount() - smt_syncTick;
return (datetime)(smt_serverTime + elapsedMs / 1000);
}
//--- Abstand der Broker-Uhr zu UTC in Sekunden (7200 = GMT+2). Auch für sich allein
//--- nützlich: Die meisten EAs kennen diesen Wert nie. TimeCurrent() ist die Zeit des
//--- letzten Ticks, also bei geöffnetem Markt auslesen, nicht am Wochenende.
int SMT_BrokerGmtOffsetSeconds()
{
return (int)(TimeCurrent() - SMT_Now());
}
//--- alles nach dem n-ten Komma (der CSV-Titel, der selbst Kommas enthalten kann)
string SMT_AfterComma(const string line, const int n)
{
int pos = -1;
for(int i = 0; i < n; i++)
{
pos = StringFind(line, ",", pos + 1);
if(pos < 0) return "";
}
string rest = StringSubstr(line, pos + 1);
StringReplace(rest, "\"\"", "\"");
if(StringLen(rest) >= 2 && StringGetCharacter(rest, 0) == '"')
rest = StringSubstr(rest, 1, StringLen(rest) - 2);
return rest;
}
//--- lädt die nächsten 2 Tage herunter (das Fenster deckt auch die letzten 6 Stunden ab)
bool SMT_Download()
{
string url = "https://showmytrades.com/api/public/calendar/v1?format=csv&days=2&impact=" + SMT_Impact;
if(StringLen(SMT_Currencies) > 0) url += "¤cy=" + SMT_Currencies;
char post[], result[];
string headers;
ResetLastError();
int status = WebRequest("GET", url, "", NULL, 10000, post, 0, result, headers);
if(status != 200)
{
Print("[SMT] calendar download failed: HTTP ", status, ", error ", GetLastError(),
". Is https://showmytrades.com in Tools > Options > Expert Advisors > Allow WebRequest?");
smt_nextDownload = TimeCurrent() + 60; // neuer Versuch in einer Minute
return false;
}
string body = CharArrayToString(result, 0, WHOLE_ARRAY, CP_UTF8);
string lines[];
int n = StringSplit(body, '\n', lines);
ArrayResize(smt_eventTime, 0);
ArrayResize(smt_eventTitle, 0);
for(int i = 1; i < n; i++) // Zeile 0 ist die Kopfzeile
{
// letzte Zeile "# server_time=1760702400 server_time_iso=...": die UTC-Uhr des Servers
if(StringFind(lines[i], "# server_time=") == 0)
{
long serverTime = StringToInteger(StringSubstr(lines[i], 14, 10));
if(serverTime > 0)
{
smt_serverTime = serverTime;
smt_syncTick = GetTickCount();
smt_clockSynced = true;
}
continue;
}
string f[];
if(StringSplit(lines[i], ',', f) < 8) continue;
int k = ArraySize(smt_eventTime);
ArrayResize(smt_eventTime, k + 1);
ArrayResize(smt_eventTitle, k + 1);
smt_eventTime[k] = (datetime)StringToInteger(f[0]); // Unix-Sekunden, UTC
smt_eventTitle[k] = f[2] + " " + f[3] + ": " + SMT_AfterComma(lines[i], 7);
}
smt_nextDownload = TimeCurrent() + MathMax(SMT_RefreshMinutes, 15) * 60;
Print("[SMT] calendar: ", ArraySize(smt_eventTime), " events loaded. UTC now ",
TimeToString(SMT_Now(), TIME_DATE|TIME_MINUTES), ", broker clock is GMT",
(SMT_BrokerGmtOffsetSeconds() >= 0 ? "+" : ""), DoubleToString(SMT_BrokerGmtOffsetSeconds() / 3600.0, 1));
return true;
}
//--- true, solange eine Veröffentlichung im Pausenfenster liegt; reason sagt, welche
bool SMT_IsNewsTime(string &reason)
{
reason = "";
if(MQLInfoInteger(MQL_TESTER)) return false; // kein Netzwerk im Tester
if(TimeCurrent() >= smt_nextDownload) SMT_Download();
datetime now = SMT_Now();
for(int i = 0; i < ArraySize(smt_eventTime); i++)
{
if(now >= smt_eventTime[i] - SMT_MinutesBefore * 60 && now <= smt_eventTime[i] + SMT_MinutesAfter * 60)
{
reason = smt_eventTitle[i];
return true;
}
}
return false;
}
Was die Datei der Reihe nach tut: Sie baut die Anfrage aus den Eingabeparametern zusammen, lädt die CSV-Datei herunter, merkt sich pro Termin einen Zeitstempel und eine Bezeichnung und beantwortet die einzige Frage, die den EA interessiert: Liegt gerade eine Veröffentlichung im Fenster?
🔌 Schritt 3: Vor jedem Einstieg abfragen
Binde die Datei in deinen EA ein und lass ihn nachfragen, bevor er eine Position eröffnet:
#include <SMT_NewsFilter.mqh>
void OnTick()
{
string news;
if(SMT_IsNewsTime(news))
{
Comment("News filter active: ", news);
return; // keine neuen Einstiege im News-Fenster
}
Comment("");
// ... deine Einstiegslogik ...
}
Die fünf Eingabeparameter (SMT_Currencies, SMT_Impact und die drei Minutenwerte) erscheinen wie jede andere Einstellung im Eingabedialog des EA. Jeder Chart kann also eigene Werte haben.
Kompiliere neu, zieh den EA auf den Chart und sieh im Reiter „Experten“ nach: Die erste Zeile sollte [SMT] calendar: N events loaded lauten. An einem ruhigen Tag kann N null sein. Das ist richtig so und kein Fehler.
⏱️ Zeiten, Uhren und der Strategietester
Ob der Filter zur richtigen Minute greift, hängt an drei Details.
| Die API rechnet in UTC und sagt, wie spät es ist | ts ist Unix-Zeit in Sekunden, UTC. Jeder Download endet mit der Uhrzeit des Servers (# server_time=…), und SMT_Now() schreibt sie mit dem Tick-Zähler des Rechners fort, der weder Zeitzonen noch Sommerzeit kennt. Nichts hängt von der Zeitzone des Brokers ab, von irgendeiner Sommerzeitumstellung oder davon, ob auf dem VPS die richtige Zeitzone eingestellt ist |
Niemals TimeCurrent() | Die Broker-Zeit weicht von UTC um einen Betrag ab, den der EA nicht kennen kann und der sich zweimal im Jahr ändert. SMT_BrokerGmtOffsetSeconds() misst ihn für dich, was schon für sich nützlich ist; der Filter selbst verlässt sich nie darauf |
| Der Strategietester hat kein Internet | WebRequest() ist dort deaktiviert, im Backtest meldet die Funktion also „keine News“. Wer einen News-Filter auf historischen Daten testen will, braucht eine lokale Datei mit vergangenen Terminen, und das ist ein eigenes Projekt |
🎛️ Feinabstimmung
- Offene Positionen. Der Code sperrt nur neue Einstiege. Ob du vor einer Veröffentlichung schließt, die Stops enger ziehst oder weiter setzt, ist eine Frage der Strategie; wann es so weit ist, sagt dir dasselbe
SMT_IsNewsTime(). - Nur eine Seite des Paars. Setze
SMT_CurrenciesaufUSD, wenn für dich nur Dollar-News zählen. - Auch mittlere Wichtigkeit. Mit
SMT_Impact = "high,medium"kommen ungefähr dreimal so viele Termine zusammen. Gut für Scalper, für Swing-Systeme oft zu viel. - Feiertage.
impact=allenthält Handelsfeiertage als ganztägige Termine. Die meisten Filter wollen sie nicht, deshalb lässt die Standardeinstellung sie weg.
🔍 Die Daten prüfen
Denselben Kalender kannst du auch als Seite lesen: Wirtschaftskalender. Meldet der EA, dass er wegen „USD high: Nonfarm Payrolls“ pausiert hat, findest du den Termin dort mit der Prognose und, nach der Veröffentlichung, mit dem tatsächlichen Wert.
❓ Häufige Fragen
Brauche ich dafür ein ShowMyTrades-Konto? Nein. Die Kalender-API ist kostenlos und offen, ganz ohne Schlüssel. Wenn du die verifizierte öffentliche Seite haben willst, verfolge dein Konto auf ShowMyTrades; der News-Filter hängt aber nicht davon ab.
Wie viel Datenverkehr entsteht? Eine Anfrage alle 15 Minuten pro Chart, jeweils ein paar Kilobyte. Zehn EAs auf einem Terminal kommen auf 40 Anfragen pro Stunde. Das Limit liegt bei 600 pro Minute und IP-Adresse.
Warum nicht direkt Forex Factory auslesen?
Das geht, und viele EAs machen es so. Die Wochendatei von Forex Factory erlaubt aber nur zwei Downloads alle fünf Minuten pro IP-Adresse. Auf einem VPS mit vielen Terminals reicht das nicht, und actual-Werte enthält die Datei auch nicht. Der Endpunkt von ShowMyTrades filtert schon auf dem Server nach Währung und Wichtigkeit, liefert ein paar Kilobyte und ist für regelmäßiges Abfragen gebaut.
Die Uhr oder die Zeitzone meines VPS stimmt nicht. Greift der Filter trotzdem zur richtigen Minute? Ja. Der Server teilt dem EA bei jedem Download die aktuelle UTC-Zeit mit, und der EA lässt diese Uhr mit seiner eigenen weiterlaufen. Eine falsch eingestellte Zeitzone auf dem VPS oder eine Uhr, die ein paar Minuten danebenliegt, ändert nichts. Nicht einmal eine Sommerzeitumstellung auf dem VPS: Der EA misst die vergangene Zeit mit dem Tick-Zähler, nicht mit der Uhr.
Was passiert, wenn der Download fehlschlägt?
Der Filter behält den zuletzt geladenen Kalender und versucht es nach einer Minute erneut. Hat er noch nie einen geladen (gerade gestartet, kein Internet), meldet er „keine News“, und der EA handelt. Wenn du das nicht willst, prüfe ArraySize(smt_eventTime) == 0 und entscheide selbst.
Funktioniert dieselbe Datei in MT5? Ja, ohne Änderung. MT5 hat außerdem einen eigenen Kalender. Nimm, was besser zu dir passt.
🔗 Weiterführende Artikel
- Referenz der Wirtschaftskalender-API: alle Parameter, das JSON-Format, der WebSocket für cTrader
- News-Filter in MT5: eingebauter Kalender oder API
- News-Filter in einen cTrader-cBot einbauen: dieselbe Idee, wo kein HTTP zur Verfügung steht
- So zeigst du Live-Ergebnisse deines EA auf der Verkaufsseite: Sobald der EA gut handelt, zeig es
Der Filter ist eine Seite Code und eine URL. Wenn dein EA schon auf ShowMyTrades verfolgt wird, zeigen sich die Trades, die er rund um die News auslässt, als Drawdown, der ausgeblieben ist.
So zeigst du mehrere Handelskonten auf einer Seite
Mehrere Konten, mehrere EAs oder mehrere Broker auf einer einzigen Webseite: eine Live-Vergleichstabelle mit einer Zeile pro Konto, Charts nebeneinander oder eine gemeinsame Kurve. Mit Code.
News-Filter in MT5: eingebauter Kalender oder API?
MetaTrader 5 bringt einen Wirtschaftskalender mit, den Expert Advisors ohne Download auslesen können. Wann er reicht, wann nicht und wie du stattdessen eine kostenlose Kalender-API nutzt, mit MQL5-Code für beide Wege.