# News Filter Modules for MQL5

This folder contains two reusable MQL5 economic-calendar filter modules:

- `NewsFilter_Simple.mqh`
- `NewsFilter_Advanced.mqh`

Both read the MT5 built-in economic calendar, cache the high-impact events, and tell your EA whether a symbol is inside a news window. The simple version stops there and lets you decide what to do. The advanced version also closes open positions before a release and cancels resting pending orders.

The goal is to stop your EA opening a fresh position seconds before a number that has nothing to do with your edge. The trade-off is that you will sit out some genuinely good entries, because a filter cannot tell the difference in advance.

## Which Version Should You Use?

### Simple Version

Use `NewsFilter_Simple.mqh` when:

- you want entries blocked around news and nothing else
- you would rather manage open positions with your own stop
- you want the smallest possible change to your EA
- you want to read the whole module in one sitting

This is the best version for most people, and it is one function call in your entry path.

It includes:

- cached calendar reads, so no calendar API calls in the hot path
- symbol-to-currency derivation from the broker's own base and profit currencies
- a manual override map for index CFDs that MT5 cannot map
- an event-name exclusion list
- fail-open behaviour on a calendar outage, switchable to fail-closed
- throttled logging

### Advanced Version

Use `NewsFilter_Advanced.mqh` when:

- you want open positions closed before a release
- you want resting pending orders cancelled during the window
- you are comfortable calling one extra function every tick

It includes everything in the simple version, plus:

- a position flatten sweep with broker-aware filling mode
- a pending-order cancel sweep
- magic-number scoping, so it can only ever touch this EA's trades
- a flatten window that stops at the release time
- a flatten lead clamped to the block window

The advanced version does more, so there is more to get wrong. Start simple.

## The Split Between Deciding And Acting

This matters more than anything else in this README.

`NewsFilter_Simple.mqh` is a decision layer. It answers "is this symbol in a news window right now" and returns true or false. It never sends an order. If you enable it and expect your open positions to close, nothing will happen, and the module is working correctly.

`NewsFilter_Advanced.mqh` adds the action layer through `NFA_Manage(magic)`. That function is what closes positions and cancels orders. If you do not call it every tick, the advanced version behaves exactly like the simple one.

## Important Assumptions

These modules are designed for:

- MQL5 Expert Advisors
- a broker whose terminal actually serves the economic calendar
- live or demo running, because Strategy Tester calendar replay is unconfirmed
- an EA that knows its own magic number, for the advanced version

The calendar is a terminal feature, not a broker feed you can assume is present. Check the init log line before you rely on any of this.

## What The Inputs Mean

The simple version uses `NF_` input names. The advanced version uses `NFA_` names. Everything below applies to both unless stated.

Core:

- `UseNewsFilter`: master switch. Off means the module is a complete no-op, so you can install it without changing behaviour and turn it on later.
- `BlockMinutesBefore`: how long before a release entries stop. Default 30.
- `BlockMinutesAfter`: how long after a release entries stay blocked. Default 15.
- `FailClosed`: what happens when the calendar is unavailable. False (default) trades on as if the filter were off. True blocks everything.

What counts as news:

- `Currencies`: the currencies you care about, comma separated. An event only matters if its country's currency is on this list.
- `ExcludeEvents`: comma-separated substrings. Any event whose name contains one is dropped before it can block anything. This is how you stop US crude oil inventories blocking your EURUSD trades, and you will want it.
- `SymbolOverrides`: a manual `SYMBOL=CCY` map for instruments MT5 cannot map itself. Almost every index CFD needs an entry here. Edit this first.

Advanced only:

- `FlattenPositions`: close open positions before a release. Off by default.
- `FlattenLeadMinutes`: how long before the release closing starts. Clamped to `BlockMinutesBefore`.
- `CancelPendings`: cancel resting pending orders during the block window. On by default.
- `SlippagePoints`: deviation allowed on the flatten close.

## How It Works Behind The Scenes

1. On init, and every four hours after that, the module pulls three days of calendar events with `CalendarValueHistory`.
2. Each event is kept only if `CalendarEventById` reports it as `CALENDAR_IMPORTANCE_HIGH`, its country currency is on your `Currencies` list, and its name does not match `ExcludeEvents`.
3. Survivors go into a small in-memory array. Nothing else touches the calendar API, so the per-tick cost is an array scan.
4. For each symbol, the watched currencies are derived once from `SYMBOL_CURRENCY_BASE` and `SYMBOL_CURRENCY_PROFIT`, filtered to your list, plus the override map. The result is cached per symbol.
5. A gate is a time comparison: is now inside the window around a cached event for one of this symbol's currencies.

A failed currency lookup is deliberately not cached. Caching it would leave that symbol unprotected for the life of the EA, and you would never see why.

## Manual Installation: Simple Version

### 1. Add the include

Put `NewsFilter_Simple.mqh` next to your EA, then at the top of your `.mq5`:

```mql5
#include "NewsFilter_Simple.mqh"
```

### 2. Initialise the module

```mql5
int OnInit()
{
   NF_Init();
   return INIT_SUCCEEDED;
}
```

### 3. Gate every entry

```mql5
if (!NF_EntryAllowed(Symbol()))
   return;

// your existing entry logic
```

Put this at every point your EA sends an entry order. If your EA has a long path and a short path, that is two call sites. If it trades several symbols, pass the symbol you are about to trade rather than `Symbol()`.

One missed call site leaves that path unprotected, and nothing in the log will tell you.

## Manual Installation: Advanced Version

### 1. Add the include

```mql5
#include "NewsFilter_Advanced.mqh"
```

### 2. Initialise the module

```mql5
int OnInit()
{
   NFA_Init();
   return INIT_SUCCEEDED;
}
```

### 3. Run the manager every tick

```mql5
void OnTick()
{
   NFA_Manage(MyMagicNumber);

   if (!NFA_EntryAllowed(Symbol()))
      return;

   // your existing entry logic
}
```

Call `NFA_Manage` before your entry logic and outside any "new bar only" guard. Closes and cancels should run every tick; entries can be as selective as you like.

Pass your EA's magic number. The sweep only touches positions and orders carrying it, so another EA's trades and your manual trades are safe. Passing 0 acts on everything in the account, so only do that if this EA is the only thing trading it.

## Adding It With An AI Agent

If you use Claude Code, Cursor, or similar, this prompt works well:

```text
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.
```

Ask it to confirm the number of entry call sites. That is the step people get wrong.

## Two Things That Will Confuse You

I lost an hour to both of these. They are not bugs.

### 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. The module reads the API, so the tab will mislead you.

The module prints the authoritative list every time it refreshes:

```text
[NewsFilter] cached 4 event(s) (raw=150, name-excluded=2) | 2026.08.26 17:30 USD ...
```

That line is everything the filter can act on. Trust it over the tab.

### Log timestamps and calendar times are different clocks

Your Experts-tab log 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 is consistent whatever your broker's offset.

## Pros

- Stops entries into a print your model never saw in backtest
- Costs one function call per entry path
- Cached, so no calendar API work per tick
- Master switch off means a genuine no-op, safe to install ahead of time
- Magic scoping in the advanced version keeps other EAs safe

## Cons

- The MT5 calendar rates some second-tier releases as high impact. You will need `ExcludeEvents`.
- Currency matching is blunt. A US energy release applies to every USD instrument, whether or not it is related.
- Index CFDs need a manual entry in `SymbolOverrides` or they are not covered at all.
- Strategy Tester calendar replay is unconfirmed, so backtests may not reflect live behaviour.
- Blocking entries around news changes your trade distribution. Your backtest no longer describes what you are running.

That last point is the real cost. Measure it before you leave it on.

## Safety Notes

- Test on a demo account first. Every time.
- Turn `FlattenPositions` on only once you have watched the entry blocking behave for a while.
- The flatten sweep will close positions at market. Understand that before enabling it.
- Fail-open is the default. If your calendar feed dies, the filter stops protecting you and says so in the log. Nothing alerts you beyond that line.
- This is educational tooling, not trading advice and not a signal service.
- No warranty of any kind. Use at your own risk. Trading carries risk of loss.

## Compile Status

Both modules compile standalone against a minimal host EA:

```text
Compile_NewsFilter_Simple.mq5     0 errors, 0 warnings
Compile_NewsFilter_Advanced.mq5   0 errors, 0 warnings
```

MetaEditor build 5.0.0.6140.
