Two reusable MetaTrader 5 include modules that read the built-in economic calendar and stop your EA entering seconds before a high-impact release. The simple version gates entries. The advanced version also closes open positions and cancels resting pending orders ahead of the print.
Deciding and acting are separate. The simple module answers whether a symbol is inside a news window and returns true or false. It never sends an order. If you turn it on expecting your open positions to close, nothing will happen, and the module is working correctly. Closing positions is what the advanced module adds.
Start here
Simple
Use this when you want entries blocked around news and nothing else, and you would rather manage open positions with your own stop. It is one function call in your entry path.
Cached calendar reads, no API calls per tick.
Currency derived from the broker's own symbol data.
Manual override map for index CFDs.
Event-name exclusion list.
Does more
Advanced
Use this when you want open positions closed before a release and resting pending orders cancelled during the window. One extra call every tick.
Position flatten with broker-aware filling mode.
Pending-order cancel sweep.
Magic-number scoped, so other EAs stay untouched.
Flatten window stops at the release time.
Manual install
Include the file, initialise it in OnInit(), then gate every entry. The advanced version adds one manager call at the top of OnTick(). Both modules ship with the master switch off, so you can install them without changing behaviour and enable them when you are ready.
Simple entry-gate integration
#include "NewsFilter_Simple.mqh"
int OnInit()
{
NF_Init();
return INIT_SUCCEEDED;
}
void OnTick()
{
if(!NF_EntryAllowed(Symbol()))
return; // inside a news window, skip this pass
// your existing entry logic
}
Advanced integration with flatten and cancel
#include "NewsFilter_Advanced.mqh"
input ulong MyMagicNumber = 11111;
int OnInit()
{
NFA_Init();
return INIT_SUCCEEDED;
}
void OnTick()
{
// Closes and cancels. Run every tick, outside any new-bar guard.
NFA_Manage(MyMagicNumber);
if(!NFA_EntryAllowed(Symbol()))
return;
// your existing entry logic
}
Put the include file beside your EA, or inside your MetaTrader MQL5/Include folder.
Gate every entry call site. If your EA has a long path and a short path, that is two gates. One missed call site leaves that path unprotected, and nothing in the log will tell you.
Edit the symbol override map first. Index CFDs rarely carry usable base and profit currencies, so NDX, GER40 and friends need a manual entry or they are not covered at all.
Pass your own magic number to NFA_Manage(). The sweep only touches trades carrying it, so another EA and your manual positions stay safe.
Compile and demo test the final EA. A clean module compile does not prove your integration is correct.
Adding it with an AI agent
The public surface area is small, which makes this a good fit for an AI coding agent. Ask it to report how many entry call sites it found. That is the step people get wrong.
Prompt for an AI coding agent
Add the news filter in NewsFilter_Simple.mqh to my EA.
1. Include the module at the top of the .mq5.
2. Call NF_Init() in OnInit().
3. Find EVERY place the EA sends an entry order. For each one, gate it with
NF_EntryAllowed(<the symbol being traded>) and skip the entry if it
returns false. List the call sites you found and confirm the count.
4. Do not change my strategy logic, lot sizing, stops, or targets.
5. Leave NF_UseNewsFilter at false so behaviour is unchanged until I enable it.
Then compile in MetaEditor and report the result.
Two things that confuse people
I lost an hour to both of these while testing my own build. Neither is a bug.
The MT5 Calendar tab is not what the filter reads
The terminal's Calendar tab does not always display everything the calendar API returns. An event the API reports as high impact can be missing from the tab entirely, which makes a correctly working filter look like it invented a release out of nowhere.
The module prints the authoritative list every time it refreshes. That line is everything the filter can act on, and it is worth more than the tab:
Log timestamps and calendar times are different clocks
Your Experts-tab timestamps are in local PC time. TimeCurrent() and the calendar's event times are both in server time. On a UTC+3 broker viewed from a UTC+1 machine, a block that fired correctly twelve minutes before a release looks like it fired two hours and twelve minutes early.
Convert before you conclude the window is broken. Inside the module both sides of the comparison are server time, so it stays consistent whatever your broker's offset happens to be.
Safety notes
The trade-off: filtering entries around news keeps your EA out of prints your model never saw in testing, and it also means you sit out some genuinely good entries. A filter cannot tell the difference in advance. Measure the cost before you leave it on.
Test on a demo account before using live.
Confirm your terminal actually serves the calendar. The init log line reports how many events were cached, and zero means you have no protection.
Enable FlattenPositions only after you have watched the entry blocking behave for a while. It closes at market.
Fail-open is the default. If the calendar feed dies the filter stops protecting you and says so in the log, and nothing else alerts you.
Expect to edit ExcludeEvents. The MT5 calendar rates some second-tier releases as high impact, and sector-specific numbers like crude oil inventories will otherwise block every instrument in that currency.
Strategy Tester calendar replay is unconfirmed, so your backtest may not reflect live behaviour.
Blocking entries changes your trade distribution. Your original backtest no longer describes what you are running.
Personal commentary and education, not investment advice or a solicitation. Code is provided as-is, with no warranty. Test on demo before using live. Capital at risk. Past performance is not indicative of future results.