preview
Using the MQL5 Economic Calendar for News Filtering (Part 1): Implementing Pre- and Post-News Windows in MQL5

Using the MQL5 Economic Calendar for News Filtering (Part 1): Implementing Pre- and Post-News Windows in MQL5

MetaTrader 5Trading |
163 0
Solomon Anietie Sunday
Solomon Anietie Sunday

Common and Uncommon Problems

Most news filters for trading robots do only one thing — block new trades during news releases. That is not enough.

During major economic releases, the market often experiences:

  • sudden price spikes,
  • spread expansion,
  • slippage,
  • stop-loss hunting wicks.

Open positions remain exposed, which can completely destroy a strategy’s statistical edge.

Additional issues include:

  • Prop firm compliance — strict time windows before and after specific news events must be respected.
  • Currency relevance — not all news affects all symbols; filtering must be currency-aware.
  • Strategy instability during news — stops are often triggered by spread widening rather than real price movement.
  • State loss after EA or VPS restart — many implementations fail to preserve trade logic during interruptions.
  • No testing mode — difficult to validate behavior without live news events.

The Solution

The solution is to build a structured news filter using the native MQL5 Economic Calendar.

The system:

  • evaluates news relevance based on the symbol’s currencies,
  • filters by importance level,
  • applies configurable pre- and post-news buffers,
  • blocks new trade entries during active news windows,
  • optionally closes positions before high-impact events,
  • correctly detects news window start and end transitions.

Instead of a simple on/off switch, this becomes a risk-aware mechanism.


Article Scope

This is Part 1 of a news-aware trading system for MQL5.

This article covers:

  • detecting news by importance level,
  • mapping events to symbols based on currency logic,
  • defining pre- and post-news windows,
  • blocking new trade entries,
  • closing positions before high-impact events.

Advanced stop-management and state recovery mechanisms will be covered separately to keep the implementation focused and practical.

Below is a workflow diagram that summarizes how the news filter behaves in this article.

Workflow diagram

The MQL5 Calendar: The approach used in this article and why it is necessary

In the past, traders have had to rely on web requests to external websites for services to get news data. this is slow, unreliable, and difficult to backtest accurately. Today MQL5 offers the MqlCalendar functions, allowing us to pull economic data directly from the terminal.

This method is superior for speed since there are no HTTP requests; data is fetched from a local cache, backtesting the news events can be simulated to trigger manually and more accurately for testing on past data than an external service, and reliability since there are no broken links or API changes and other issues to worry about.


Limitations and Design Considerations

This implementation is designed to be lightweight, deterministic, and compatible with the MQL5 native economic calendar. As a result, several limitations and assumptions must be clearly stated.
  1. The news filter loads calendar events within a rolling 24-hour window. This design minimizes repeated calendar queries and improves runtime performance, but it also means that events beyond the next 24 hours are not preloaded; the calendar cache must be refreshed periodically to remain accurate.
  2. Exploratory symbol-to-currency mapping. Symbol relevance is determined using heuristic rules such as base and quote currency extraction for FX symbols and keyword-based detection for indices, metals, and commodities. While this works for standard broker naming conventions, it is not guaranteed to cover all custom symbols. For this reason, a manual currency override input is provided to handle edge cases or proprietary symbol formats.
  3. All time comparisons are performed using the trading server's current time. The MQL5 economic calendar events are also time-stamped relative to the server environment, but discrepancies may still occur due to broker server time-zone differences, daylight saving transitions, and historical testing conditions. For this reason, pre- and post-news buffer windows are configurable rather than fixed.
  4. This implementation relies entirely on the broker-provided MQL5 economic calendar. If the broker does not provide certain events, countries, or importance levels accurately, those events cannot be detected by the filter. The system is therefore only as complete as the underlying calendar data provided by the broker.

    Understanding Time Windows

    The news filter does not react only to the exact release time of an event. Instead, it defines a configurable buffer window around the event to account for pre-release volatility and post-release market instability. The window consists of a pre-news buffer (minutes before the event), the actual news event release time, and a post-news buffer (minutes after the event). Any time that falls within this combined window is treated as an active news period.

    Below is an image showing how the news window works.

    News window imagery explanation



      Implementation

      Step 1: Defining the core structures

      Before we can detect or react to economic news, we must first decide how news data will be stored and how the system will track whether a news window is active.

      Many beginner implementations attempt to check for news events directly on every tick without organizing the data properly which quickly leads to unnecessary CPU usage, repeated calculations, and confusing logic that becomes difficult to maintain or extend. To avoid these issues, we begin by defining simple and well-scoped data structures that serve two fundamental purposes:
      1. Storing economic calendar events retrieved from MetaTrader
      2. Tracking whether the trading system is currently inside a news-restricted period
      At this stage, no trading behavior is modified; we are only building the foundation that later logic will rely on. 

      Using the MQL5 Economic Calendar Structure

      MetaTrader 5 provides a built-in structure called MqlCalendarValue.

      This structure contains all essential information related to an economic event, including the scheduled time of the event, the associated currency, the impact level (low, moderate, or high), and the actual, forecast, and previous values.

      Rather than defining a custom structure for economic events, we rely on this built-in type to ensure compatibility with the MQL5 Economic Calendar and to reduce the risk of implementation errors.

      We store calendar data in an array that will later represent all relevant events for the current trading day.

      News Events example

      Scenarios and expected behavior

      The following illustrates how the news filter is expected to behave across different symbols and economic events. This assumes that the economic calendar contains a matching event and the configured time window is active. The below illustrations are examples and do not show every possible scenario that covers what the filter does.

      Symbol Event Currency Event Importance Within News Window Expected Result
      EURUSD EUR or USD High (Red) Yes New trades blocked
      EURUSD EUR or USD  High No Trading allowed 
      EURUSD EUR or USD Low (Grey) Yes If low is not enabled, trading blocked if not trading allowed
      EURUSD GBP High or Low or Moderate Yes Trading allowed
      GOLD USD High Yes New trades blocked
      US100 USD Moderate(Yellow) Yes News trades blocked(if moderate enabled)
      GBPJPY GBP or JPY High No Trading allowed
      AUDUSD AUD or USD  High After Window Trading allowed

      In each case the decision is based solely on currency relevance and time-window alignment. If any event currency matches the symbol's relevant currencies and the current time falls within the configured buffer window, the news filter enters an active state.

      For strategy tester manual validation, the testing inputs can be used to simulate specific event times. This allows the news window to be triggered deterministically without relying on live calendar data.

      Understanding Symbol Currency Relevance

      Economic news events are linked to currencies, not to tradable symbols. To determine whether a given event is relevant, the system derives a set of currencies associated with the currently traded symbol and compares them against the event's reported currency.

      For the standard FX symbols, the base and quote currencies are extracted differently from the symbol name (for example, EURUSD is EUR and USD).

      For indices, metals, and commodities, predetermined keyword heuristics are used to associate the symbol with its most influential currency (for example, GOLD is USD, and GER40 is EUR).

      If a symbol does not match any known pattern, a manual currency override can be provided in the inputs to explicitly define which currency should be monitored. An economic event is considered relevant if its currency matches at least one of the symbol's associated currencies.

      Practical step

      Tracking the News State

      A news filter should not repeatedly re-evaluate the same information on every tick.

      To prevent this, we introduce a simple state flag that allows the system to remember whether it is currently operating inside a news-restricted window.

      In addition, a timestamp is used to track when calendar data was last loaded. This makes it possible to refresh calendar information only when necessary, instead of querying it continuously.

      This approach helps to reduce CPU usage, improve execution efficiency, keep the logic predictable and easy to follow, and provide clear logging and debugging.

      At the end of this step, the Expert Advisor has no functional news logic yet, but it has a clean and scalable structure that future steps will build upon.

      //+------------------------------------------------------------------+
      //|                                      News Filter Integration.mq5 |
      //|                                                    soloharbinger |
      //+------------------------------------------------------------------+
      #property copyright "soloharbinger"
      #property link      ""
      #property version   "1.01"
      
      #include <Trade/Trade.mqh>
      
      //===================================================================
      // GLOBAL VARIABLES                                                 |
      //===================================================================
      MqlCalendarValue TodayEvents[];    // Stores calendar events for the trading day
      
      datetime lastCalendarLoad = 0;     // TimeStamp of the last calendar update into our above value
      
      CTrade trade;                      // Ctrade instance for order management 
      
      //+------------------------------------------------------------------+
      //| Expert initialization function                                   |
      //+------------------------------------------------------------------+
      int OnInit()
        {
      //---
         Print("News Filter Demo initialized");
      //---
         return(INIT_SUCCEEDED);
        }
      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      void OnDeinit(const int reason)
        {
      //---
        }
      //+------------------------------------------------------------------+
      //| Expert tick function                                             |
      //+------------------------------------------------------------------+
      void OnTick()
        {
      //---
      // News detection logics will be implemented in the next steps
        }
      //+------------------------------------------------------------------+

      Step 2: Loading and Caching Economic Calendar Events

      Once the basic data structures are in place, the next challenge is how to obtain economic news data efficiently.

      The MQL5 Economic Calendar contains thousands of events spanning multiple years. Searching through the entire calendar on every tick would be extremely inefficient and unnecessary. Such an approach wastes CPU resources and can slow down an Expert Advisor significantly, especially when running multiple instances.

      To avoid this, we introduce a controlled loading mechanism that retrieves only the events we actually need.

      Why caching is necessary

      Economic news events do not change every second; they are scheduled in advance, and they can be reused across many ticks. Because of this, it makes no sense to repeatedly query the calendar data on every price update.

      Instead, we load calendar events once during initialization and periodically, after a defined time interval, to account for sudden changes in market data releases or events.

      The retrieved data is stored in the TodayEvents[] array, where it can be reused by later logic without additional overhead.

      Defining the Event Loading Period

      For this article, we define a rolling 24-hour period, which is from the current server time to 24 hours into the future.

      This window is wide enough to capture pre-session news, intraday events, and late-session or overnight releases. The exact window length can be adjusted, but 24 hours provides a clear and beginner-friendly starting point.

      The Load Calendar Event Function

      We encapsulate the calendar retrieval logic inside a dedicated function.

      This keeps the code organized and prevents calendar logic from being scattered throughout the EA.

      The function checks whether the calendar was recently loaded, skips reloading if the cached data is still valid, queries the Economic Calendar for the defined time range, and stores the results in the TodayEvents[] array.

      At this stage, no filtering is applied yet. We are only collecting raw event data.

      //===================================================================
      // Load calendar (24-hour horizon)
      //===================================================================
      void LoadTodayCalendarEvents()
        {
         datetime now = TimeCurrent();
         datetime fromTime = now;
         datetime toTime = now + 24 * 3600;    // Load next 24 hours
      
      
         ArrayFree(TodayEvents);
         int count = CalendarValueHistory(TodayEvents, fromTime, toTime);
         PrintFormat("Loaded %d calendar records for the next 24 hours.", count);
      
      
         if(count <= 0)
           {
            // Still update timestamp to prevent constant reloading attempts
            lastCalendarLoad = now;
            return;
           }
      
      // Debug: print first few events for verification
         for(int i = 0; i < MathMin(count, 5); i++)
           {
            MqlCalendarEvent ev;
            if(CalendarEventById(TodayEvents[i].event_id, ev))
              {
               PrintFormat("Event %d: %s | Time: %s | Importance: %d",
                           i, ev.name, TimeToString(TodayEvents[i].time), ev.importance);
              }
           }
      
         lastCalendarLoad = now;
        }
      

      Example of Loaded/Cached upcoming News event in experts

      Step 3: Smart Currency Filtering

      A common frustration with basic news filters is irrelevant blocking.

      For example, if an Expert Advisor is trading EURUSD, it should not stop trading simply because there is a high-impact news release related to the Australian Dollar (AUD). Unfortunately, many simplistic implementations treat all news as equally dangerous, which results in missed trading opportunities and unnecessary downtime.

      To solve this, we introduce smart currency filtering.

      The goal of this step is simple: Only react to news events that are actually relevant to the symbol being traded.

      Why Currency Filtering Matters

      Every economic news event is associated with a specific country and currency.

      At the same time, every trading symbol is affected by one or more underlying currencies.

      If we do not match these two correctly:

      • The EA may pause trading when it should not, or worse, ignore news that actually affects the symbol.

      A news filter must therefore answer two questions:

      • which currencies does this trading symbol depend on, and which currency does this news event belong to?

      Only when both match should the event be considered relevant.

      Extracting Relevant Currencies From the Trading Symbol

      We start by determining which currencies affect the current symbol.

      For standard Forex pairs, this is straightforward; the first three letters represent the base currency, and the next three letters represent the quote currency.

      For example:

      • EURUSD → EUR and USD, or GBPJPY → GBP and JPY.

      However, not all instruments follow this format.

      Indices, metals, and commodities often require special handling.

      To keep the system flexible, we encapsulate this logic inside a function called GetRelevantCurrencies().

      This function automatically extracts base and quote currencies for forex pairs, applies simple keyword detection for indices and commodities, allows a manual override when automatic detection is not sufficient, and the function returns a comma-separated list of currencies relevant to the symbol.

      //===================================================================
      // Helper: Return CSV list of relevant currencies for symbol
      //===================================================================
      string GetRelevantCurrencies(string symbol)
        {
      // 1. Check Manual Override
         if(StringLen(SymbolCurrencyOverride) > 0)
           {
            return SymbolCurrencyOverride;
           }
      
         string upper = symbol;
         StringToUpper(upper);
      
      
      // 2. Standard Forex Pair Logic (e.g. EURUSD -> EUR,USD)
         if(StringLen(symbol) == 6)
           {
            string baseCurr = StringSubstr(upper, 0, 3);
            string quoteCurr = StringSubstr(upper, 3, 3);
            return baseCurr + "," + quoteCurr;
           }
      
      // 3. Heuristics for Indices/Commodities
         if(StringFind(upper, "GER") != -1 || StringFind(upper, "DE40") != -1 || StringFind(upper, "DAX") != -1)
            return "EUR";
         if(StringFind(upper, "UK") != -1 || StringFind(upper, "FTSE") != -1)
            return "GBP";
         if(StringFind(upper, "US30") != -1 || StringFind(upper, "DJ") != -1)
            return "USD";
         if(StringFind(upper, "SPX") != -1 || StringFind(upper, "US500") != -1)
            return "USD";
         if(StringFind(upper, "NAS") != -1 || StringFind(upper, "US100") != -1)
            return "USD";
         if(StringFind(upper, "XAU") != -1 || StringFind(upper, "GOLD") != -1)
            return "USD";
         if(StringFind(upper, "XAG") != -1 || StringFind(upper, "SILVER") != -1)
            return "USD";
         if(StringFind(upper, "OIL") != -1 || StringFind(upper, "WTI") != -1 || StringFind(upper, "BRENT") != -1)
            return "USD";
         if(StringFind(upper, "JPN") != -1 || StringFind(upper, "NIK") != -1)
            return "JPY";
         if(StringFind(upper, "AUD") != -1)
            return "AUD";
         if(StringFind(upper, "CAD") != -1)
            return "CAD";
         if(StringFind(upper, "NZD") != -1)
            return "NZD";
         if(StringFind(upper, "CHF") != -1)
            return "CHF";
         if(StringFind(upper, "EUR") != -1)
            return "EUR";
         if(StringFind(upper, "GBP") != -1)
            return "GBP";
         if(StringFind(upper, "JPY") != -1)
            return "JPY";
      
      // Fallback: if we can't guess, return nothing (safe mode)
         return "";
        }

      At this point, the EA knows which currencies matter for the current symbol, but it still does not know which currency a news event belongs to.

      We solve this next.

      Determining the Currency of a News Event.

      Economic calendar entries do not directly store a currency code such as “USD” or “EUR”; instead, each event is linked to a country ID. To obtain the event’s currency, we must retrieve the event’s country information and read the currency associated with that country.

      MQL5 provides a direct and reliable way to do this using CalendarCountryById().

      We encapsulate this logic in a helper function called GetCurrencyFromEventDirect().

      //===================================================================
      // Utility: Get currency from calendar event (via Country ID)
      //===================================================================
      string GetCurrencyFromEventDirect(const MqlCalendarEvent &ev)
        {
         MqlCalendarCountry country;
         if(CalendarCountryById(ev.country_id, country))
           {
            return country.currency; // Returns "USD", "EUR", etc.
           }
         return "";
        }
      

      This function allows us to convert

      a calendar event into a concrete currency code such as USD, EUR, or GBP.

      What We Have Achieved So Far

      By the end of this step, the EA can determine which currencies affect the current symbol, the EA can determine which currency a news event belongs to, and the foundation is in place to ignore irrelevant news events.

      No trade-blocking logic has been applied yet.

      At this stage, the system still does nothing disruptive; it simply understands relevance, which is important for any intelligent news filter. 

      Next we combine cached calendar events (Step 2) and relevant symbol currencies (Step 3) to detect whether a relevant event is currently active. This is when we create time windows and impact filtering.

      Step 4: Detecting and Avoiding Relevant News Events

      Now that we can load and cache economic calendar events (Step 2) and identify which currencies are relevant for the trading symbol (Step 3), we can then ask if there is relevant economic news affecting this symbol right now. At this stage, the Expert Advisor only detects news and the minutes to avoid around news time.

      High-Level Detection Rules

      A news event is considered relevant only if the event occurs within the cached calendar data, the event’s importance level matches our filter settings, the event’s currency matches one of the symbol’s relevant currencies, and the current time falls inside the defined pre-news and post-news window.

      Only when all four conditions are true does the function report that news is active.

      Reloading Calendar Data Safely

      Before scanning events, we ensure the calendar data is still valid.

      Calendar data is reloaded only when it has never been loaded before or the cached data is older than a defined interval (for example, 6 hours).

      This prevents unnecessary calls to the calendar functions on every tick and missing a new update to the news.

      Detection function below

      //===================================================================
      // Core Detection Logic
      // Returns true if 'now' is inside a news window for the specific symbol
      //===================================================================
      bool isUpcomingNews(const string symbol)
        {
         datetime now = TimeCurrent();
      
      // A. Cache Management
         if(lastCalendarLoad == 0 || (now - lastCalendarLoad) > (datetime)CacheReloadHours * 3600)
           {
            LoadTodayCalendarEvents();
           }
      
         if(ArraySize(TodayEvents) == 0)
            return false;
      
      
      // B. Testing Simulation
         if(EnableNewsTesting)
           {
            if(TestNewsNow)
               return true;
            datetime t = StringToTime(TestNewsTime);
            if(t > 0)
              {
               datetime start = t - TestNewsDuration * 60;
               datetime end   = t + TestNewsDuration * 60;
               if(now >= start && now <= end)
                  return true;
              }
           }
      
      // C. Optimization: Prepare Currency List OUTSIDE the loop
         string relevant = GetRelevantCurrencies(symbol);
         if(StringLen(relevant) == 0)
            return false;
      
         string currencyArray[];
         int currencyCount = StringSplit(relevant, ',', currencyArray);
         for(int k = 0; k < currencyCount; k++)
           {
            StringTrimLeft(currencyArray[k]);
            StringTrimRight(currencyArray[k]);
            StringToUpper(currencyArray[k]);
           }
      
      // D. Event Scan
         for(int i = 0; i < ArraySize(TodayEvents); i++)
           {
            MqlCalendarEvent ev;
            // Retrieve event details from ID
            if(!CalendarEventById(TodayEvents[i].event_id, ev))
               continue;
      
            // 1. Importance Filter
            bool okImportance = false;
            switch(NewsImportanceMode)
              {
               case NEWS_HIGH_ONLY:
                  okImportance = (ev.importance == CALENDAR_IMPORTANCE_HIGH);
                  break;
               case NEWS_MODERATE_ONLY:
                  okImportance = (ev.importance == CALENDAR_IMPORTANCE_MODERATE);
                  break;
               case NEWS_HIGH_AND_MODERATE:
                  okImportance = (ev.importance == CALENDAR_IMPORTANCE_HIGH || ev.importance == CALENDAR_IMPORTANCE_MODERATE);
                  break;
              }
            if(!okImportance)
               continue;
      
            // 2. Currency Relevance Filter
            string eventCurrency = GetCurrencyFromEventDirect(ev);
            if(StringLen(eventCurrency) == 0)
               continue;
      
            bool affect = false;
            for(int j = 0; j < currencyCount; j++)
              {
               if(eventCurrency == currencyArray[j])
                 {
                  affect = true;
                  break;
                 }
              }
            if(!affect)
               continue;
      
            // 3. Time Window Check
            datetime eventTime = TodayEvents[i].time;
            datetime windowStart = eventTime - (NewsMinutesBefore * 60);
            datetime windowEnd   = eventTime + (NewsMinutesAfter * 60);
      
            if(now >= windowStart && now <= windowEnd)
              {
               // Optional: Print once per detection to avoid log spam
               static string lastDetectedKey = "";
               string key = ev.name + "|" + TimeToString(eventTime);
               if(key != lastDetectedKey)
                 {
                  PrintFormat("NEWS: %s | Time: %s | Currency: %s", ev.name, TimeToString(eventTime), eventCurrency);
                  lastDetectedKey = key;
                 }
               return true;
              }
           }
      
         return false;
        }

      Simplifying Detection for the EA

      To keep the rest of the whole Expert Advisor clean and readable, we wrap the detection logic in a simple interface function.

      This ensures that detection logic remains centralized.

      // Wrapper for external calls
      bool IsNewsTime(string symbol)
        {
         return isUpcomingNews(symbol);
        }
      

      At this stage, other parts of EA that the news filter is needed, we can safely do something like

      if(IsNewsTime(_Symbol))

      {

          // Detect News

      }

      Step 5: Blocking Trade Entries During News Windows

      At this stage, the Expert Advisor can already detect relevant economic news events accurately. The final step of Part 1 is to use this detection logic to block new trade entries during a defined time window before and after news events. 

      This approach aligns perfectly with prop firm requirements, where the most common restriction is “No new trades may be opened during high-impact news.” 

      Importantly, existing trades are not modified in any way; the system simply prevents new entries while the new conditions are active.

      Why We Block Entries Only (For Part 1)

      Blocking trade entries is the simplest and safest form of news protection, easy to understand for beginners, compatible with prop firm rules, and non-invasive to existing strategies.

      By limiting Part 1 to entry blocking only, we ensure that there are no unintended side effects, no trade corruption, and a clean foundation for more advanced behavior later.

      Important: Required Inputs for a Complete News Filter

      To make the news filter configurable and usable across different trading styles and prop firms, we introduce a small set of inputs.

      These inputs control whether the news filter is enabled, which news importance levels are considered, and how many minutes before and after news trading should be blocked.

      //===================================================================
      // INPUTS
      //===================================================================
      input group "News Filter Configuration"
      input bool   EnableNewsFilter = false;                           // Enable Economic News Filter
      input int    NewsMinutesBefore = 5;                              // Minutes before news to restrict
      input int    NewsMinutesAfter = 5;                               // Minutes after news to restrict
      input bool   RestrictNewTradesDuringNews = true;                 // Block new trades during news window
      input bool   CloseOpenTradesBeforeHighImpactNews = false;        // Close all trades before news
      input string SymbolCurrencyOverride = "";                        // Manual currency override e.g. "USD,JPY"
      enum ENUM_NEWS_IMPORTANCE_MODE
        {
         NEWS_HIGH_ONLY = 0,
         NEWS_MODERATE_ONLY,
         NEWS_HIGH_AND_MODERATE
        };
      input ENUM_NEWS_IMPORTANCE_MODE NewsImportanceMode = NEWS_HIGH_ONLY; // Importance levels
      
      // Cache reload interval
      input int CacheReloadHours = 6;                                  // Reload calendar cache (hours)
      
      
      // News Testing helpers (Simple simulation for Part 1 demonstration)
      input group "Testing Parameters"
      input bool EnableNewsTesting = false;                             // Enable news testing simulation with Current symbol
      input string TestNewsTime = "2025.12.15 14:30:00";                // Simulated news time (yyyy.MM.dd HH:mm:ss)
      input int TestNewsDuration = 10;                                  // Simulated window length (minutes)
      input bool TestNewsNow = false;                                   // Manual immediate trigger
      

      These inputs allow the EA to adapt easily to different prop firm rules, conservative or aggressive trading styles, and broker-specific volatility behavior.

      screenshot of input parameters

      Inputs Name Uses/ Purposes
      Enable Economic News Filter Enables or disables the news filter for the EA entirely
      Minutes before News to restrict  Defines how many minutes before the news event the filter becomes active
      Minutes after News to restrict Defines how many minutes after the news event the filter remains active
      Block new trades during news window Block opening new trades while the news window is active
      Close all trades before news Close existing position when a relevant news window begins
      Manual currency override Manually specifies currency to monitor when automatic detection is insufficient (leave blank when automatic detection is working)
      Importance level Select which news importance levels are considered (High, Moderate or both)
      Reload Calendar Cache Controls how often calendar data is refreshed
      Enable News testing simulation Enables manual news trigger only
      Simulated News time Specifies the simulated news event time in any yyyy/mm/dd  hh/mm/ss in the past
      Simulated news window length [minutes] Defines the active window length for simulated news event
      Manual immediate trigger  Immediately triggers a simulated news window for testing

      Using Detection Logic to Block Trades

      With detection already implemented in Step 4, blocking trades becomes trivial. Instead of embedding the news logic inside trade functions, we use a single gate condition before opening any new position.

      This keeps the trading logic clean and readable.

      //===================================================================
      // Check if new trades are allowed (Main Filter Gate)
      //===================================================================
      bool CanOpenNewTrade(string symbol)
        {
         if(!EnableNewsFilter)
            return true;
         if(!RestrictNewTradesDuringNews)
            return true;
      
         if(IsNewsTime(symbol))
           {
            return false; // Block trade
           }
      
         return true;
        }
      

      This function answers one simple question:

      • Is it safe to open a new trade right now?

      Applying the Gate in Trade Logic

      Wherever your EA normally opens trades, you simply add this check at the top, for example:

      if(!CanOpenNewTrade(_Symbol))
      {
         // News window active — do not open new trades
         return;
      }
      
      // Normal trade entry logic continues here

      With this check in place, trade entry logic remains clean and centralized.

      Optional: Close All Trades Before News Window

      This below snippet allows the Expert Advisor to close all trades for the symbol once the pre-news restriction window begins.

      The snippet makes use of the same detection logic already implemented.

      The input of this function is already in the above-provided inputs.

      //===================================================================
      // CloseAllTradesForSymbol
      // Implements safe reverse iteration and CTrade closing
      //===================================================================
      void CloseAllTradesForSymbol(string symbol)
        {
      // Iterate backward to safely close multiple positions
         for(int i = PositionsTotal() - 1; i >= 0; i--)
           {
            ulong ticket = PositionGetTicket(i);
            if(ticket == 0)
               continue;
      
            if(!PositionSelectByTicket(ticket))
               continue;
      
            // Filter by symbol
            if(PositionGetString(POSITION_SYMBOL) != symbol)
               continue;
      
            // Close Logic
            bool closed = trade.PositionClose(ticket);
      
            if(closed)
              {
               PrintFormat("Closed position #%d on %s due to news.", ticket, symbol);
              }
            else
              {
               PrintFormat("Failed to close #%d. Error: %d", ticket, GetLastError());
              }
           }
        }

      Trigger Logic [inside onTick()]

      //===================================================================
      // OnTick
      //===================================================================
      void OnTick()
        {
      // Static latch to ensure we don't try to close trades multiple times per window
         static bool tradesClosedForThisNewsWindow = false;
      
      // 2. Main News Logic
         if(EnableNewsFilter)
           {
            bool isNews = IsNewsTime(_Symbol);
      
            // Feature: Close open trades before news if enabled
            if(CloseOpenTradesBeforeHighImpactNews && isNews)
              {
               if(!tradesClosedForThisNewsWindow)
                 {
                  Print("News window started -> Closing open trades.");
                  CloseAllTradesForSymbol(_Symbol);
                  tradesClosedForThisNewsWindow = true; // Latch
                 }
              }
            else
               if(!isNews)
                 {
                  // Reset latch when we are out of the news window
                  tradesClosedForThisNewsWindow = false;
                 }
           }
        }

      What this adds

      • Closes trades before volatility hits.
      • It uses existing detection logic.
      • Fires once per news window.
      • Fully optional [set input to true or false].
      • Prop firm friendly.
      • In part 2 we will implement a stop-loss and take-profit temporary removal and placement around a restricted news window to preserve strategy edge and avoid premature exits.

      Closing Part 1

      At this point, we have built a working news filter that is efficient, symbol-aware, prop-firm compliant, beginner-friendly, ready for blocking entries, and ready for trade closure.

      Part 1 can stand entirely on its own.


      Conclusion

      In this article, we built a complete and functional news filter system in MQL5, starting from first principles and ending with a practical solution.

      Rather than relying on hard-coded times or web request-based news blocking, the system was designed around the MQL5 Economic Calendar, with careful attention to performance, relevance, and clarity. Calendar events are loaded efficiently, cached logically, filtered by importance, and matched only to currencies that actually affect the traded symbol.

      By separating news detection from trade enforcement, the logic remains easy to understand, easy to test, and easy to extend. The final result is a clean entry-blocking mechanism that prevents new trades during configurable pre-news and post-news windows, with an optional rule to close open positions before news volatility begins.

      This approach is especially well-suited for prop firm trading environments, where the most common requirement is simply to avoid opening trades during restricted news periods. Without modifying open positions or interfering with trade management, and this is why in part 2 we work on temporarily removing stops only on the news restriction window so that they don't get tapped or modified during news time, hence breaking a rule, and even closing trades early can disrupt strategy flow. Overall, the system provides compliance and protection while remaining strategy agnostic.

      More importantly, everything I have implemented in this article is fully usable on its own. Part 1 delivers a complete news filter that can be dropped into any Expert Advisor and immediately used to enforce news-based trade restrictions.

      In the next part of this series, we will build on this foundation to explore more advanced behavior during news events, such as trade management control and additional protection mechanisms.

      The system presented here already solves the core problem in a clean way.


      Market Simulation (Part 13): Sockets (VII) Market Simulation (Part 13): Sockets (VII)
      When we develop something in xlwings or any other package that allows reading and writing directly to Excel, we must note that all programs, functions, or procedures execute and then complete their task. They do not remain in a loop, no matter how hard we try to do things differently.
      Market Simulation (Part 12): Sockets (VI) Market Simulation (Part 12): Sockets (VI)
      In this article, we will look at how to solve certain problems and issues that arise when using Python code within other programs. More specifically, we will demonstrate a common issue encountered when using Excel in conjunction with MetaTrader 5, although we will be using Python to facilitate this interaction. However, this implementation has a minor drawback. It does not occur in all cases, but only in certain specific situations. When it does happen, it is necessary to understand the cause. In today’s article, we will begin explaining how to resolve this issue.
      Features of Experts Advisors Features of Experts Advisors
      Creation of expert advisors in the MetaTrader trading system has a number of features.
      Risk Management (Part 5): Integrating the Risk Management System into an Expert Advisor Risk Management (Part 5): Integrating the Risk Management System into an Expert Advisor
      In this article, we will implement the risk management system developed in previous publications and add the Order Blocks indicator described in other articles. In addition, we will run a backtest so we can compare results with the risk management system enabled and evaluate the impact of dynamic risk.