GW News Filter
- Libraries
- Jose Martinez Hernandez
- Version: 1.0
GW News Filter
Filter trading around high-impact news. Avoid entries/exits during risky time windows using MetaTrader’s Calendar API or your own CSV files.
Works in live, demo and Strategy Tester · Source: API or CSV · Per-currency files · Entry/Exit flags · Diagnostics (0–4)
Features
Works in real accounts, demo, and Strategy Tester
Choose between:
- 0 = Auto (API for live/demo, CSV for Strategy Tester)
- 1 = API (MetaTrader’s built-in calendar)
- 2 = CSV (per-currency files, e.g. EUR.csv, USD.csv, ALL.csv)
Configure:
- Minimum importance (Low, Moderate, High)
- Window seconds before/after news
- Include global “ALL” events
- Separate flags for filtering entries and filtering exits
- Lightweight wrapper class for easy integration
- Diagnostic logging (levels 0–4) for testing and debugging
Installation
- Copy MQL5/Libraries/GWNewsFilterLib.ex5
- Copy MQL5/Include/Greaterwaves/GWNewsFilterLib.mqh
- Include in your EA/indicator:
#include <Greaterwaves/GWNewsFilterLib.mqh>
Quick Start
Create the filter once (e.g. in OnInit). If testing with CSV, set the folder with SetCsvLocation() .
int OnInit() { if(!g.Create(_Symbol, InpFilterEntry, InpFilterExit, InpMinImp, InpIncludeAll, InpBefore, InpAfter, InpDiagLevel, InpSource)) { Print("GWNF: failed to create instance (Did you copy GWNewsFilterLib.ex5 into MQL5/Libraries/ ?)"); return(INIT_FAILED); } // If using CSV (or running in Tester), set the CSV location if(InpSource==1 || (int)MQLInfoInteger(MQL_TESTER)!=0) { if(!g.SetCsvLocation(InpCsvBaseRel, InpCsvUseCommon)) Print("GWNF: SetCsvLocation() failed."); } return(INIT_SUCCEEDED); }
Then rebuild the window once per bar and act on it:
void OnTick() { datetime bar = (datetime)iTime(_Symbol, _Period, 0); if(bar == g_last) return; g_last = bar; if(!g.RebuildWindow()) { Print("GWNF: RebuildWindow() returned false."); return; } const int active = g.GetFilteringEventsCount(); if(active > 0) { // Filter is active → skip entries / manage exits } else { // Filter is inactive → outside events window } }
CSV Preparation Guide
Each row in the CSV must contain the following 16 columns, in this exact order:
- VALUE_ID → Unique numeric ID for the value (use any integer, e.g. `10001`)
- EVENT_ID → Unique numeric ID for the event (e.g. `20001`)
- TIME → Event time in `YYYY.MM.DD HH:MM:SS` format
- PERIOD → Period string (may be left blank if not used)
- REVISION → Integer revision number (usually `0`)
- ACTUAL → Actual reported value (leave empty if unknown)
- PREVIOUS → Previous reported value (leave empty if unknown)
- REVISED_PREV → Revised previous value (leave empty if unknown)
- FORECAST → Forecasted value (leave empty if unknown)
- IMPACT_TYPE → Integer (0=none, 1=positive, 2=negative, 3=neutral). Can be `0` if not needed.
- CURRENCY → Currency code (`USD`, `EUR`, `JPY`, … or `ALL`)
- COUNTRY_CODE → Country code (`US`, `EU`, `GB`, …)
- COUNTRY_ID → Numeric ID (can be `0` if not relevant)
- IMPORTANCE → `LOW`, `MODERATE`, or `HIGH`
- EVENT_CODE → Short machine-friendly identifier (`cpi`, `gdp`, `trade-balance`)
- NAME → Human-friendly event name
Example rows:
10001;20001;2025.08.28 12:30:00;;0;3.4;3.2;;3.5;0;USD;US;0;HIGH;cpi;Consumer Price Index (YoY) 10002;20002;2025.08.28 14:00:00;;0;1.8;2.0;;2.1;0;USD;US;0;MODERATE;housing;Housing Starts 10003;20003;2025.08.28 15:00:00;;0;;; ;0.9;0;EUR;EU;0;HIGH;confidence;Consumer Confidence Index
Explanation:
-
The first event is a high-impact USD CPI release.
-
The second event is moderate impact housing data.
-
The third is a high-impact EUR confidence index.
File Naming and Placement
Place one CSV file per currency (e.g. USD.csv , EUR.csv ) inside a folder.
The folder can be located in:
- Common\Files\NEWS\ (shared by all terminals), or
- MQL5\Files\NEWS\ (local to one terminal).
You configure the folder via:
g.SetCsvLocation("NEWS", true); // "true" = use Common\Files
Diagnostics
- 0 = silent
- 1 = critical errors only
- 2 = init + when filter is active
- 3 = adds “outside news” logs
- 4 = full detail (lists all events)
Important Notes
- Even if you don’t need all values (like VALUE_ID or COUNTRY_ID), you must keep the column order and delimiters.
- Empty fields are allowed — just keep the ; separator.
- The parser expects semicolon ; separators, consistent with MetaTrader CSV.
- Event importance must be one of: LOW, MODERATE, HIGH.
Wrapper Header (copy this into MQL5/Include/Greaterwaves/GWNewsFilterLib.mqh)
//+------------------------------------------------------------------+ //| GWNewsFilterLib.mqh | //| Public wrapper for GWNewsFilterLib.ex5 binary | //| (c) GreaterWaves - José Martínez Hernández | //+------------------------------------------------------------------+ // // HOW TO USE // 1) Copy this file to: MQL5/Include/Greaterwaves/GWNewsFilterLib.mqh // 2) Copy the binary to: MQL5/Libraries/GWNewsFilterLib.ex5 // 3) In your EA/Indicator: // #include <Greaterwaves/GWNewsFilterLib.mqh> // // Example: // // GWNewsFilter nf; // if(nf.Create(_Symbol, true, false, // 2, // minImportance (0=None,1=Low,2=Moderate,3=High) // true, // includeGlobalAll // 900,900,// secondsBefore/After // 3, // diagnosticLevel (0-4) // 0)) // forcedSource (0=Auto,1=CSV,2=API) // { // nf.SetCsvLocation("NEWS", true); // Optional custom CSV path // nf.RebuildWindow(); // if(nf.IsFilteringNow(true,false)) // Print("Filter active on entry"); // nf.UpdateChartCommentMinimal(); // } // // =============================================================== // IMPORTS from binary library // =============================================================== #import "GWNewsFilterLib.ex5" int GWFilter_Create(string symbol, bool filterEntry, bool filterExit, int minImportance, bool includeGlobalAll, int secondsBefore, int secondsAfter, int diagnosticLevel, int forcedSource); bool GWFilter_Destroy(int handle); bool GWFilter_RebuildWindow(int handle); bool GWFilter_IsBlockingNow(int handle, bool forEntry, bool forExit); int GWFilter_GetBlockingEventsCount(int handle); int GWFilter_TotalInWindow(int handle); bool GWFilter_GetWindowEventAt(int handle, int index, long &value_id, long &event_id, datetime &time, string ¤cy, string &country_code, string &event_code, string &name, int &importance); bool GWFilter_SetDiagnosticLevel(int handle, int level); bool GWFilter_SetForcedSource (int handle, int forcedSource); bool GWFilter_SetBlockFlags (int handle, bool filterEntry, bool filterExit); bool GWFilter_BuildBlockingComment(int handle, string &out_comment); bool GWFilter_UpdateChartCommentMinimal(int handle); bool GWFilter_SetCsvLocation(int handle, string baseRel, bool useCommon); #import // =============================================================== // Object-oriented wrapper for easier usage in EAs/Indicators // =============================================================== class GWNewsFilter { private: int m_h; // internal handle to binary object public: GWNewsFilter(): m_h(0) {} // Create instance with settings bool Create(string symbol, bool filterEntry, bool filterExit, int minImportance = 2, bool includeGlobalAll= true, int secondsBefore = 900, int secondsAfter = 900, int diagnosticLevel = 2, int forcedSource = 0) { m_h = GWFilter_Create(symbol, filterEntry, filterExit, minImportance, includeGlobalAll, secondsBefore, secondsAfter, diagnosticLevel, forcedSource); return (m_h > 0); } // Destroy instance bool Destroy() { if(m_h<=0) return false; bool ok=GWFilter_Destroy(m_h); m_h=0; return ok; } // Refresh window of upcoming events bool RebuildWindow() { return (m_h>0 ? GWFilter_RebuildWindow(m_h) : false); } // Check if filter is active now (entry/exit) bool IsFilteringNow(bool forEntry, bool forExit) { return (m_h>0 ? GWFilter_IsBlockingNow(m_h, forEntry, forExit) : false); } // Number of filtering events currently active int GetFilteringEventsCount(){ return (m_h>0 ? GWFilter_GetBlockingEventsCount(m_h) : -1); } // Total number of events in the current window int TotalInWindow() { return (m_h>0 ? GWFilter_TotalInWindow(m_h) : -1); } // Get details of an event at index bool GetWindowEventAt(int index, long &value_id, long &event_id, datetime &time, string ¤cy, string &country_code, string &event_code, string &name, int &importance) { return (m_h>0 ? GWFilter_GetWindowEventAt(m_h, index, value_id, event_id, time, currency, country_code, event_code, name, importance) : false); } // Change diagnostic log level bool SetDiagnosticLevel(int level){ return (m_h>0 ? GWFilter_SetDiagnosticLevel(m_h, level) : false); } // Force data source (Auto, CSV, API) bool SetForcedSource (int forced){ return (m_h>0 ? GWFilter_SetForcedSource (m_h, forced) : false); } // Enable/disable filtering for entry/exit bool SetFilterFlags (bool fe, bool fx){ return (m_h>0 ? GWFilter_SetBlockFlags(m_h, fe, fx) : false); } // Build a minimal comment string when filter is active bool BuildFilteringComment(string &out_comment){ out_comment=""; return (m_h>0 ? GWFilter_BuildBlockingComment(m_h, out_comment) : false); } // Update chart comment automatically (only when active) bool UpdateChartCommentMinimal(){ return (m_h>0 ? GWFilter_UpdateChartCommentMinimal(m_h) : false); } // Set CSV folder location bool SetCsvLocation(const string baseRel, const bool useCommon=true) { return (m_h>0 ? GWFilter_SetCsvLocation(m_h, baseRel, useCommon) : false); } // Return internal handle int Handle() const { return m_h; } };
EA Example with minimal usage
// Minimal demo usage #include <Greaterwaves/GWNewsFilterLib.mqh> GWNewsFilter g; int OnInit() { g.Create(_Symbol, true, false, 2, true, 900, 900, 2, 0); g.SetCsvLocation("NEWS", true); // if using CSV return INIT_SUCCEEDED; } void OnTick() { if(g.RebuildWindow()) { if(g.GetFilteringEventsCount()>0) Print("Filter active - skip trading"); } }
Support: https://academy.greaterwaves.com