Why Filter News Events
High-impact news events can wreak havoc on automated trading strategies:
What happens during news:
Real example:
The solution: Stop trading before, during, and after high-impact news events.
News Data Sources
Option 1: MQL5 Economic Calendar (MT5 Only)
MT5 has a built-in economic calendar accessible via MQL5:
``mql5
MqlCalendarValue values[];
int count = CalendarValueHistory(values, startTime, endTime);
for(int i = 0; i < count; i++) { MqlCalendarEvent event; CalendarEventById(values[i].event_id, event);
Print("Event: ", event.name);
Print("Impact: ", event.importance); // Low, Medium, High
Print("Time: ", values[i].time);
}
`
Pros: Built-in, always up-to-date Cons: MT5 only
Option 2: External Calendar File
Download CSV from Forex Factory, Trading Economics, etc.
`csv
Date,Time,Currency,Impact,Event
2024-01-05,08:30,USD,High,Non-Farm Payrolls
2024-01-05,08:30,USD,High,Unemployment Rate
2024-01-10,08:30,USD,High,CPI m/m
`
Pros: Works on MT4, customizable Cons: Requires manual updates
Option 3: Web API
Use services like Forex Factory API, Investing.com API, or custom endpoints.
`mql4
string url = "https://nfs.faireconomy.media/ff_calendar_thisweek.json";
string response = WebRequest("GET", url, headers, timeout, data, result);
// Parse JSON response
``
Pros: Always current, automated Cons: Requires web request permissions, potential latency
Basic Implementation
Simple Time-Based Filter
``mql4
input int NewsMinutesBefore = 30; // Minutes before news to stop
input int NewsMinutesAfter = 30; // Minutes after news to resume
input bool FilterHighImpact = true;
input bool FilterMediumImpact = false;
// Define news times (update weekly) datetime newsEvents[] = { D'2024.01.05 13:30', // NFP D'2024.01.10 13:30', // CPI D'2024.01.17 13:30', // Retail Sales // Add more events... };
bool IsNewsTime() { datetime currentTime = TimeCurrent();
for(int i = 0; i < ArraySize(newsEvents); i++) { datetime newsTime = newsEvents[i]; datetime startFilter = newsTime - NewsMinutesBefore * 60; datetime endFilter = newsTime + NewsMinutesAfter * 60;
if(currentTime >= startFilter && currentTime <= endFilter) { return true; // We're in a news window } }
return false; }
void OnTick() { // Check news filter first if(IsNewsTime()) { Comment("Trading paused - News event nearby"); return; // Skip trading logic }
// Normal trading logic continues... } ``
Advanced Filtering
Currency-Specific Filtering
Only filter news for currencies your EA trades:
``mql4
struct NewsEvent {
datetime time;
string currency;
int impact; // 1=Low, 2=Medium, 3=High
string description;
};
NewsEvent events[];
bool ShouldFilter(string symbol) { string baseCurrency = StringSubstr(symbol, 0, 3); string quoteCurrency = StringSubstr(symbol, 3, 3);
datetime currentTime = TimeCurrent();
for(int i = 0; i < ArraySize(events); i++) { // Skip if wrong currency if(events[i].currency != baseCurrency && events[i].currency != quoteCurrency) continue;
// Skip if impact too low if(events[i].impact < MinImpactLevel) continue;
// Check time window datetime startFilter = events[i].time - NewsMinutesBefore * 60; datetime endFilter = events[i].time + NewsMinutesAfter * 60;
if(currentTime >= startFilter && currentTime <= endFilter) { return true; } }
return false;
}
`
Spread-Based Detection
Detect news indirectly by monitoring spread:
`mql4
input double MaxSpreadMultiplier = 2.0; // Close if spread > 2x normal
double normalSpread = 12; // Set based on your pair (in points)
bool IsSpreadTooHigh() { double currentSpread = MarketInfo(Symbol(), MODE_SPREAD);
if(currentSpread > normalSpread * MaxSpreadMultiplier) { Print("High spread detected: ", currentSpread, " (normal: ", normalSpread, ")"); return true; }
return false;
}
`
Volatility-Based Detection
Use ATR spike detection:
`mql4
double GetVolatilityRatio() {
double currentATR = iATR(Symbol(), PERIOD_M5, 14, 0);
double averageATR = iATR(Symbol(), PERIOD_H1, 14, 0);
return currentATR / averageATR; }
bool IsHighVolatility() { return GetVolatilityRatio() > 2.0; // 2x normal volatility } ``
Testing Your Filter
Backtest Verification
Test your EA with and without the news filter:
Test 1: No Filter
``
Total trades: 1000
Profit factor: 1.45
Max drawdown: 25%
Trades during news: 87
`
Test 2: With Filter
`
Total trades: 913
Profit factor: 1.62
Max drawdown: 18%
Trades during news: 0
`
Analysis:
Live Monitoring
Add logging to verify your filter works:
`mql4
void LogNewsFilter(string reason) {
string message = StringFormat(
"NEWS FILTER ACTIVE: %s | Time: %s | Spread: %.1f",
reason,
TimeToString(TimeCurrent()),
MarketInfo(Symbol(), MODE_SPREAD)
);
Print(message);
// Optional: Send notification // SendNotification(message); } ``
Complete Code Example
Full News Filter Class
``mql4
//+------------------------------------------------------------------+
//| NewsFilter.mqh - Comprehensive News Filter for MT4 |
//+------------------------------------------------------------------+
class CNewsFilter { private: int m_minutesBefore; int m_minutesAfter; int m_minImpact; double m_maxSpreadMultiplier; double m_normalSpread; datetime m_newsEvents[]; string m_newsCurrencies[]; int m_newsImpacts[];
public: CNewsFilter() { m_minutesBefore = 30; m_minutesAfter = 30; m_minImpact = 3; // High impact only m_maxSpreadMultiplier = 2.0; m_normalSpread = 12; }
void SetParameters(int before, int after, int impact) { m_minutesBefore = before; m_minutesAfter = after; m_minImpact = impact; }
void SetSpreadFilter(double multiplier, double normalSpread) { m_maxSpreadMultiplier = multiplier; m_normalSpread = normalSpread; }
void AddNewsEvent(datetime time, string currency, int impact) { int size = ArraySize(m_newsEvents); ArrayResize(m_newsEvents, size + 1); ArrayResize(m_newsCurrencies, size + 1); ArrayResize(m_newsImpacts, size + 1);
m_newsEvents[size] = time; m_newsCurrencies[size] = currency; m_newsImpacts[size] = impact; }
bool ShouldTrade(string symbol) { // Check spread first (fastest check) if(IsSpreadHigh()) { LogFilter("High spread detected"); return false; }
// Check news events if(IsNearNews(symbol)) { LogFilter("Near news event"); return false; }
return true; }
private: bool IsSpreadHigh() { double spread = MarketInfo(Symbol(), MODE_SPREAD); return spread > m_normalSpread * m_maxSpreadMultiplier; }
bool IsNearNews(string symbol) { string base = StringSubstr(symbol, 0, 3); string quote = StringSubstr(symbol, 3, 3); datetime now = TimeCurrent();
for(int i = 0; i < ArraySize(m_newsEvents); i++) { // Check currency match if(m_newsCurrencies[i] != base && m_newsCurrencies[i] != quote) continue;
// Check impact level if(m_newsImpacts[i] < m_minImpact) continue;
// Check time window datetime start = m_newsEvents[i] - m_minutesBefore * 60; datetime end = m_newsEvents[i] + m_minutesAfter * 60;
if(now >= start && now <= end) return true; }
return false; }
void LogFilter(string reason) { Print("NEWS FILTER: ", reason, " at ", TimeToString(TimeCurrent())); } };
//+------------------------------------------------------------------+ //| Example usage in EA | //+------------------------------------------------------------------+ CNewsFilter newsFilter;
int OnInit() { // Configure filter newsFilter.SetParameters(30, 30, 3); // 30 min before/after, high impact newsFilter.SetSpreadFilter(2.0, 12); // 2x normal spread of 12 points
// Add this week's news (update weekly) newsFilter.AddNewsEvent(D'2024.01.05 13:30', "USD", 3); // NFP newsFilter.AddNewsEvent(D'2024.01.10 13:30', "USD", 3); // CPI newsFilter.AddNewsEvent(D'2024.01.11 10:00', "EUR", 3); // ECB Speech
return INIT_SUCCEEDED; }
void OnTick() { // Check news filter first if(!newsFilter.ShouldTrade(Symbol())) { Comment("Trading paused - News filter active"); return; }
// Your normal trading logic here... } ``
Integration Checklist
Need help implementing a news filter? Contact us or get a free strategy audit to review your EA's risk management.