How to Add a News Filter to Your MT4 Expert Advisor
An Expert Advisor that trades through Non-Farm Payrolls or a rate decision is not trading its strategy: it is flipping a coin with a wide spread. A news filter fixes that. It pauses new entries for a few minutes before and after the releases that move the market, and lets the strategy do its job the rest of the time.
MetaTrader 5 has a calendar built in. MetaTrader 4 does not, so the EA has to fetch the news from somewhere. This guide uses the free ShowMyTrades economic calendar API: no account, no API key, one URL to allow in the terminal, and an include file you can paste into any EA.
๐งญ What You Are Building
every 15 minutes every tick
โโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ download the next โ โโโบ โ is a release within โ
โ 2 days of news โ โ [-30 min, +30 min] of now? โ
โ (CSV, one request)โ โ yes โ no new entries โ
โโโโโโโโโโโโโโโโโโโโโ โ no โ run the strategy โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
| Decision | Default in the code | Why |
|---|---|---|
| Which currencies | EUR,USD | The two sides of the pair you trade. Empty means all nine majors |
| Which impact | high | high,medium for a more cautious filter |
| Pause before | 30 minutes | Spreads widen and liquidity thins before the number |
| Pause after | 30 minutes | The first reaction and the reversal both happen here |
| Download interval | 15 minutes | The calendar changes a few times a day; the API caches for 15 minutes anyway |
๐ Step 1: Allow the Address in MetaTrader
WebRequest(), the MQL4 function that downloads from the internet, only talks to addresses you have approved. In the terminal open Tools โ Options โ Expert Advisors, tick Allow WebRequest for listed URL and add:
https://showmytrades.com
Skip this and the download returns -1 with error 4060. The include file prints a reminder in the Experts tab when that happens, so you will not wonder why the filter is silent.
๐ Step 2: Save the Include File
Save the following as SMT_NewsFilter.mqh in the MQL4\Include folder of your terminal (File โ Open Data Folder). It is the same file documented in the API reference, and it also compiles in MQL5 unchanged.
//+------------------------------------------------------------------+
//| SMT_NewsFilter.mqh - news filter for MT4 and MT5 |
//| Data: https://showmytrades.com/api/public/calendar/v1 (free) |
//| Docs: https://showmytrades.com/docs/api/economic-calendar |
//| Setup: Tools > Options > Expert Advisors > Allow WebRequest for |
//| https://showmytrades.com |
//+------------------------------------------------------------------+
#property strict
input string SMT_Currencies = "EUR,USD"; // News: currencies (comma-separated, empty = all)
input string SMT_Impact = "high"; // News: impact (high | high,medium | all)
input int SMT_MinutesBefore = 30; // News: pause before a release (minutes)
input int SMT_MinutesAfter = 30; // News: pause after a release (minutes)
input int SMT_RefreshMinutes = 15; // News: download interval (minutes, min 15)
datetime smt_eventTime[];
string smt_eventTitle[];
datetime smt_nextDownload = 0;
//--- everything after the n-th comma (the CSV title, which may itself contain commas)
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;
}
//--- downloads the next 2 days (the window also covers the last 6 hours)
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; // retry in a 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++) // line 0 is the header
{
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 seconds, 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");
return true;
}
//--- true while a release is within the pause window; reason tells which one
bool SMT_IsNewsTime(string &reason)
{
reason = "";
if(MQLInfoInteger(MQL_TESTER)) return false; // no network in the tester
if(TimeCurrent() >= smt_nextDownload) SMT_Download();
datetime now = TimeGMT();
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;
}
What it does, in order: builds the request from the inputs, downloads the CSV, keeps one timestamp and one label per event, and answers the only question the EA cares about: is a release within the window right now?
๐ Step 3: Call It Before Every Entry
In your EA, include the file and ask before opening a position:
#include <SMT_NewsFilter.mqh>
void OnTick()
{
string news;
if(SMT_IsNewsTime(news))
{
Comment("News filter active: ", news);
return; // no new entries during the news window
}
Comment("");
// ... your entry logic ...
}
The five inputs (SMT_Currencies, SMT_Impact, and the three minute values) appear in the EA's input dialog like any other setting, so each chart can have its own.
Recompile, attach the EA, and look at the Experts tab: the first line should be [SMT] calendar: N events loaded. On a quiet day N can be zero, which is correct, not an error.
โฑ๏ธ Times, Clocks and the Tester
Three details decide whether the filter fires at the right minute.
| The API speaks UTC | ts is Unix time in seconds, UTC. The code compares it with TimeGMT(), the computer's clock in UTC. Nothing depends on the broker's time zone or on daylight saving |
| Keep the clock right | On a VPS, make sure Windows time synchronisation is on. A clock five minutes off shifts every window by five minutes |
| The strategy tester has no internet | WebRequest() is disabled there, so the function returns "no news" in backtests. Testing a news filter on history needs a local file of past events, which is a different project |
๐๏ธ Tuning It
- Open positions. The code only blocks new entries. Whether to close, tighten stops or widen them before a release is a strategy decision; the same
SMT_IsNewsTime()tells you when to do it. - One side of the pair only. Set
SMT_CurrenciestoUSDif only dollar news matters to you. - Medium impact too.
SMT_Impact = "high,medium"roughly triples the events. Good for scalpers, often too much for swing systems. - Holidays.
impact=allincludes market holidays as all-day events. Most filters do not want them; the default leaves them out.
๐ Checking the Data
The same calendar is a page you can read: economic calendar. When the EA says it paused for "USD high: Nonfarm Payrolls", you can see the event there with its forecast and, after the release, its actual.
โ FAQ
Does this need a ShowMyTrades account? No. The calendar API is free and open, with no key. Track your account on ShowMyTrades if you want the verified public page, but the news filter does not depend on it.
How much traffic does it generate? One request every 15 minutes per chart, a few kilobytes each. Ten EAs on one terminal are 40 requests an hour. The limit is 600 per minute per IP address.
Why not read Forex Factory directly?
You can, and many EAs do. Its weekly file allows two downloads every five minutes per IP address, which breaks on a VPS running many terminals, and it has no actual values. The ShowMyTrades endpoint filters by currency and impact on the server, returns a few kilobytes and is built for polling.
What if the download fails?
The filter keeps the last calendar it loaded and retries after a minute. If it never loaded one (fresh start, no internet) it reports "no news", so the EA trades: if that is not what you want, check ArraySize(smt_eventTime) == 0 and decide.
Does the same file work in MT5? Yes, unchanged. MT5 also has a calendar of its own; use whichever suits you.
๐ Related
- Economic calendar API reference: every parameter, the JSON format, the WebSocket for cTrader
- News filter in MT5: built-in calendar or API
- News filter for a cTrader cBot: the same idea where HTTP is not available
- Show live EA results on your sales page: once the EA trades well, show it
The filter is a page of code and a URL. If your EA is already tracked on ShowMyTrades, the trades it skips around the news will show up as the drawdown it did not take.
How to Show Multiple Trading Accounts on One Page
Several accounts, several EAs or several brokers on a single web page: a live comparison table with one row per account, side-by-side charts, or one combined curve. With the code.
News Filter in MT5: the Built-in Calendar or an API?
MetaTrader 5 ships an economic calendar that Expert Advisors can read with no download. When it is enough, when it is not, and how to use a free calendar API instead, with MQL5 code for both.