Home/Blog/Development
Development2024-11-0110 min read

How to Implement a News Filter in Your EA (Step-by-Step Guide)

Why Filter News Events

High-impact news events can wreak havoc on automated trading strategies:

What happens during news:

  • Spreads widen 5-20x normal
  • Slippage increases dramatically
  • Price gaps occur (stops skipped)
  • Volatility spikes unpredictably
  • Technical levels become meaningless
  • Real example:

  • Normal EURUSD spread: 0.8 pips
  • During NFP: 8-15 pips
  • Your scalper expecting 5 pip profit now faces 15 pip spread
  • 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:

  • Fewer trades (as expected)
  • Higher profit factor (news trades were hurting)
  • Lower drawdown (avoided news volatility)
  • 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

  • 1. Add news events for current week (Sunday task)
  • 2. Set appropriate filter windows for your strategy
  • 3. Configure spread threshold for your pair
  • 4. Test on demo before live deployment
  • 5. Monitor logs to verify filter activates correctly
  • Need help implementing a news filter? Contact us or get a free strategy audit to review your EA's risk management.

    🧑‍💻

    TradeMetrics Pro Team

    Expert EA developers with 10+ years of experience in automated trading systems.

    Need Help With Your EA Project?

    Get expert assistance with strategy conversion, EA development, or optimization.