News_Plotter

Download script
Author: DesORegan
News_Plotter

News Event Plotter Overview

This tool is designed to help traders visualize upcoming economic news events directly on their trading charts. It automates the process of reading a news calendar, calculating the correct times for those events based on your local time zone, and drawing visual markers so you can prepare for market volatility.

Core Functionality

Data Integration and Processing The script works by reading an external CSV file containing global economic news. Because these files often contain raw data in various formats, the logic includes several automatic conversion steps:

  • Time Zone Adjustment: It takes a GMT offset into account to ensure that news events align with your specific local time.
  • Time Formatting: It automatically converts standard AM/PM time formats into a 24-hour format required for accurate chart plotting.
  • Date Standardization: It parses dates from the file and organizes them into a structured list for the software to read.

Visual Chart Markers Once the news data is processed, the script draws vertical dotted lines on your chart at the exact moment an event is scheduled to occur.

  • Dynamic Coloring: Events are color-coded by their importance level (e.g., High, Medium, and Low) to help you quickly identify high-impact volatility.
  • Information Labels: Each line on the chart includes a text description indicating both the severity rating and the name of the news event (e.g., "High: Non-Farm Payrolls").
  • Smart Layering: If multiple news events occur at the exact same time, the logic prioritizes the highest-rated event to ensure that critical information is not hidden behind less important data.

Alert System Beyond just visual markers, the script includes a proactive notification system:

  • Advance Warnings: You can set a specific warning period (in minutes). The script will trigger an audio alert before a news event occurs.
  • Selective Alerts: You can choose to receive alerts only for high-impact news or across all categories, allowing you to filter out the "noise" of minor updates.
  • One-Time Notifications: To prevent constant buzzing, the script is designed to alert you only once per specific news event.

Chart Maintenance To keep your trading workspace clean, the script includes an optional cleanup feature. If enabled, it will automatically detect and remove vertical lines for news events that occurred on previous days, ensuring your chart only shows relevant, upcoming information.

Price Data Components
Series array that contains open time of each bar
Miscellaneous
Uses files from the file systemIt issuies visual alerts to the screenIt reads information from a file
16 Views
0 Downloads
0 Favorites
News_Plotter
//+------------------------------------------------------------------+
//|                                             Des_News_Plotter.mq4 |
//|                                                        DesORegan |
//|                                   mailto: oregan_des@hotmail.com |
//+------------------------------------------------------------------+
// ========================================================================================================
// This indicator displays lines on the chart corresponding to upcoming news events. It has the following features:
//        1. Customizable audio alerts prior to the news event itself.
//        2. Allows the user to display lines according to event rating. e.g. display High rated events only.
//        3. Deletes old news lines from the chart(older than today's)".
//        4. Adjusts GMT from file to local (using GMT_Offset).
//        5. Converts AM/PM time in file to 24hr for correct plotting.
//        6. Prioritises higher rated events at same time as lower events. Prevents High "hiding" behind Low etc..
//            (assuming appropriate timeframe is selected)
//        7. Event descriptions used to populate object descriptions.
//
// To be able to use this indicator you must first save the file from the DailyFx website to the 
// C:\Program Files\Broker Metatrader\experts\files folder. The file is located at:
//         http://www.dailyfx.com/calendar/Dailyfx_Global_Economic_Calendar.csv
// IMPORTANT: It must be saved as "News.csv". Make sure it's for the current week.
//
// Save your own preferences by changing the external inputs in the code and recompiling.
// There may be bugs in this indicator but I think I've got most if not all ironed out.
// Only one way to find out. ;-) 
//
// ========================================================================================================

#property copyright "DesORegan"
#property link      "mailto: oregan_des@hotmail.com"

#property indicator_chart_window

#include <stdlib.mqh>


// =========================                        
// External Global Variables
// =========================

extern int     GMT_Offset=2;  // change this to suit, default (+2) is for CET
extern bool    Display_Low=true; 
extern color   Low_Color=Blue;   
extern bool    Display_Medium=true;
extern color   Medium_Color=Orange;
extern bool    Display_High=true;
extern color   High_Color=Red;
extern bool    News_Alerts=true;
extern bool    Low_Alerts=false;
extern bool    Medium_Alerts=false;
extern bool    High_Alerts=true;
extern int     Warning_In_Mins=15;
extern bool    Delete_Old_News=false; // deletes events older than today's


// =========================                        
// Internal Global Variables
// =========================
datetime Today_Start;


// =========================                        
// Internal Global Arrays
// =========================
string News_Array [][5]; // 0=Date,1=Description,2=Rating,3=Rating No.,4=Alert Given?



// =================================================================================================    
// =================================================================================================
// Custom indicator initialization function                          
// =================================================================================================          
// =================================================================================================  
int init()
   {
   
   //======================
   // Variable Init
   //======================     
   Today_Start = iTime(Symbol(),PERIOD_D1,0);   
   GMT_Offset = GMT_Offset*3600; // *secs in hour
   Warning_In_Mins = Warning_In_Mins*60; // *secs in minute
   
   
   
   News_Plotter();   // reads file and plots news according to preferences
   
   if (Delete_Old_News == true) Delete_Old_News();    // deletes old event lines



   return(0);
   }
   
   
// =================================================================================================    
// =================================================================================================
// Custom indicator deinitialization function                          
// =================================================================================================          
// =================================================================================================    
int deinit()
   {
      
   ObjectsDeleteAll();

   return(0);
   }
   
   
   
// =================================================================================================    
// =================================================================================================
// Custom indicator iteration function                          
// =================================================================================================          
// ================================================================================================= 

int start()
  {
   

   if (News_Alerts == true) Check_News(); // checks for imminent news events
   
   if (Delete_Old_News == true && Today_Start != iTime(Symbol(),PERIOD_D1,0)) // only calls if new day
      {
      Delete_Old_News();
      Today_Start = iTime(Symbol(),PERIOD_D1,0);
      }
   
   

   return(0);
  }



// =================================================================================================
//| News_Plotter function                          
// =================================================================================================     
int News_Plotter ()
   {   
   

   
   string Event_Date, Event_Month, Event_Day, Event_Time;
   string Gap, Event_Description, Event_Rating, Event_Rating_No;
   string Hrs, Mins;
   int Int_Hrs, Int_Mins, Last_Int_Event_Rating, i=0;
   datetime Real_Event_DateTime, Real_Event_Time;
   color Market_Event_Color;
   
   int File = FileOpen("News.CSV", FILE_CSV|FILE_READ,','); // opens News.csv file 
   
   
   if (File == -1)
      {    
      Alert("News Events File Error.");
      int err=GetLastError();
      Print("Error(",err,"): ",ErrorDescription(err));      
      }
      
   FileSeek(File, 96, SEEK_SET); // move file pointer to beginning of valid data
      
    
   while(FileIsEnding(File)==false)  // While the file pointer is not at the end of the file      
      {                                
      
      ArrayResize(News_Array,i+1);  //resizes array for every loop (event)
      
      // ===========================
      // Reads file and formats data
      // ===========================      
      Event_Date =  FileReadString(File);                                     // Read Date from file
      
      if(StringSubstr(Event_Date,4,3) == "Jan") Event_Month = "01";           // extract Month and convert to number
      else if(StringSubstr(Event_Date,4,3) == "Feb") Event_Month = "02";      // in string format for adding to 
      else if(StringSubstr(Event_Date,4,3) == "Mar") Event_Month = "03";      // other components of Date
      else if(StringSubstr(Event_Date,4,3) == "Apr") Event_Month = "04";
      else if(StringSubstr(Event_Date,4,3) == "May") Event_Month = "05";
      else if(StringSubstr(Event_Date,4,3) == "Jun") Event_Month = "06";
      else if(StringSubstr(Event_Date,4,3) == "Jul") Event_Month = "07";
      else if(StringSubstr(Event_Date,4,3) == "Aug") Event_Month = "08";
      else if(StringSubstr(Event_Date,4,3) == "Sep") Event_Month = "09";
      else if(StringSubstr(Event_Date,4,3) == "Oct") Event_Month = "10";
      else if(StringSubstr(Event_Date,4,3) == "Nov") Event_Month = "11"; 
      else if(StringSubstr(Event_Date,4,3) == "Dec") Event_Month = "12";   
      else Alert ("Date Reading Error in News Function");   

      Event_Day = StringSubstr(Event_Date, (StringLen(Event_Date)-2), 0);     // extract Day
      Event_Date = TimeYear(TimeCurrent())+"."+Event_Month+"."+Event_Day;     // reconfigure Date
      Event_Time = StringConcatenate("0000",FileReadString(File)) ;           // read Time and fill out with 0's
      

      // ===========================
      // Converts AM/PM to 24hr
      // =========================== 
      if (StringSubstr(Event_Time, (StringLen(Event_Time)-2), 2) == "PM") // PM time conversion
         {
         Mins = StringSubstr(Event_Time,(StringLen(Event_Time)-5),2);
         Hrs = StringSubstr(Event_Time,(StringLen(Event_Time)-8),2);
         Int_Hrs = StrToInteger(Hrs)*3600;
         Int_Mins = StrToInteger(Mins)*60;         
         Real_Event_Time = Int_Hrs + Int_Mins;
         if (Real_Event_Time < 43200) Real_Event_Time = Real_Event_Time + 43200; // prevents 12:12PM etc from being altered
         }
      else  // AM time conversion 
         {
         Mins = StringSubstr(Event_Time,(StringLen(Event_Time)-5),2);   
         Hrs = StringSubstr(Event_Time,(StringLen(Event_Time)-8),2);
         Int_Hrs = StrToInteger(Hrs)*3600;
         Int_Mins = StrToInteger(Mins)*60;         
         Real_Event_Time = Int_Hrs + Int_Mins;
         }
        
      
      Gap = FileReadString(File) ;
      Gap = FileReadString(File) ;
      Event_Description = FileReadString(File);
      Event_Rating = FileReadString(File) ;
      for (int p = 1; p <= 5; p++) Gap = FileReadString(File) ; // more gaps in file for unused data
      
      
      if (Real_Event_Time == 0) // if no time is specified in file 
         {
         Real_Event_DateTime = StrToTime(Event_Date) + Real_Event_Time;  
         //Print("Warning: "+Event_Date+" "+Event_Rating+" - "+Event_Description+" - Event Time Unknown");
         //Print("Please check internet for updates.");
         Event_Description = "Event Time Unknown "+Event_Description;
         }
      else Real_Event_DateTime = StrToTime(Event_Date) + Real_Event_Time + GMT_Offset;      
         
         
      // ==================
      // Fills News_Array
      // ==================   
      News_Array[i,0] = TimeToStr(Real_Event_DateTime);  // fills datetime data in compatible format
      News_Array[i,1] = Event_Description;   // fills description data
      News_Array[i,2] = Event_Rating;  // fills rating data
      if (Event_Rating == "High") Event_Rating_No = "3";
      if (Event_Rating == "Medium") Event_Rating_No = "2";
      if (Event_Rating == "Low") Event_Rating_No = "1";      
      News_Array[i,3] = Event_Rating_No;  // number equivalent for ratings
      News_Array[i,4] = "0";  // used for prevents repetition of alerts
      
      
      i++; // required to increment News_Array
         
 

      }

   FileClose( File );      
   
      
   // =================================================================
   // Helps set rating color for events at same time to highest rating.
   // Used with Market_Event_Color below.
   // =================================================================
   for (p = 1; (p <= ArraySize(News_Array)/5); p++) // this helps give priority to higher rated events
      {
      if (News_Array[p,0] == News_Array[p-1,0] && StrToInteger(News_Array[p,3]) < StrToInteger(News_Array[p-1,3]))
         {
         News_Array[p,3] = News_Array[p-1,3];
         }
      }         

   // ============================
   // Plots event lines on chart 
   // ============================        
   for (p = 0; p < (ArraySize(News_Array)/5); p++)
      {
      
      if (News_Array[p,3] == "1") Market_Event_Color = Low_Color;
      if (News_Array[p,3] == "2") Market_Event_Color = Medium_Color;
      if (News_Array[p,3] == "3") Market_Event_Color = High_Color;
      
      if(Display_Low == true && News_Array[p,2] == "Low") 
         {
         ObjectCreate(p+".News: "+News_Array[p,0],OBJ_VLINE,0,StrToTime(News_Array[p,0]),NULL);
         ObjectSet(p+".News: "+News_Array[p,0],OBJPROP_COLOR,Market_Event_Color);      
         ObjectSet(p+".News: "+News_Array[p,0],OBJPROP_WIDTH,1);
         ObjectSet(p+".News: "+News_Array[p,0], OBJPROP_BACK, true);   
         ObjectSet(p+".News: "+News_Array[p,0],OBJPROP_STYLE,STYLE_DOT);
         ObjectSetText(p+".News: "+News_Array[p,0], News_Array[p,2]+": "+News_Array[p,1], 8);   
         }
      if(Display_Medium == true && News_Array[p,2] == "Medium") 
         {
         ObjectCreate(p+".News: "+News_Array[p,0],OBJ_VLINE,0,StrToTime(News_Array[p,0]),NULL);
         ObjectSet(p+".News: "+News_Array[p,0],OBJPROP_COLOR,Market_Event_Color);      
         ObjectSet(p+".News: "+News_Array[p,0],OBJPROP_WIDTH,1);
         ObjectSet(p+".News: "+News_Array[p,0], OBJPROP_BACK, true);   
         ObjectSet(p+".News: "+News_Array[p,0],OBJPROP_STYLE,STYLE_DOT);
         ObjectSetText(p+".News: "+News_Array[p,0], News_Array[p,2]+": "+News_Array[p,1], 8);   
         }
      if(Display_High == true && News_Array[p,2] == "High") 
         {
         ObjectCreate(p+".News: "+News_Array[p,0],OBJ_VLINE,0,StrToTime(News_Array[p,0]),NULL);
         ObjectSet(p+".News: "+News_Array[p,0],OBJPROP_COLOR,Market_Event_Color);      
         ObjectSet(p+".News: "+News_Array[p,0],OBJPROP_WIDTH,1);
         ObjectSet(p+".News: "+News_Array[p,0], OBJPROP_BACK, true);   
         ObjectSet(p+".News: "+News_Array[p,0],OBJPROP_STYLE,STYLE_DOT);
         ObjectSetText(p+".News: "+News_Array[p,0], News_Array[p,2]+": "+News_Array[p,1], 8);   
         }               

      }
      
      
   // ==================================
   // DEBUG TOOL - PRINTS ARRAY CONTENTS
   // ==================================   
   //for (p = 0; p < (ArraySize(News_Array)/5); p++) 
   //   {      
   //   Print(News_Array[p,0]+" "+News_Array[p,1]+" "+News_Array[p,2]+" "+News_Array[p,3]+" "+News_Array[p,4]);
   //   }



   return(0);
   }            
   

// =================================================================================================
// Check News function                          
// =================================================================================================     
int Check_News ()
   {      
   
   
   for (int p = 0; p < (ArraySize(News_Array)/5); p++)
      {
      if (TimeCurrent()-TimeSeconds(TimeCurrent()) == (StrToTime(News_Array[p,0])-Warning_In_Mins) && News_Array[p,4] == "0") 
         {
         if (Low_Alerts == true && News_Array[p,2] == "Low")
            {
            Alert(News_Array[p,1]+" rated "+News_Array[p,2]+" occurs in "+Warning_In_Mins/60+"mins.");
            News_Array[p,4] = "1";
            }
         if (Medium_Alerts == true && News_Array[p,2] == "Medium")
            {
            Alert(News_Array[p,1]+" rated "+News_Array[p,2]+" occurs in "+Warning_In_Mins/60+"mins.");
            News_Array[p,4] = "1";
            }
         if (High_Alerts == true && News_Array[p,2] == "High")
            {
            Alert(News_Array[p,1]+" rated "+News_Array[p,2]+" occurs in "+Warning_In_Mins/60+"mins.");
            News_Array[p,4] = "1";
            }                                
            
         }
      }
   return(0);
   }        
   
   
// =================================================================================================
// Delete_Old_News function                          
// =================================================================================================    
int Delete_Old_News()
   {
   
   for (int p = 0; p < (ArraySize(News_Array)/5); p++)
      {

      if (iTime(Symbol(),PERIOD_D1,0) > StrToTime(News_Array[p,0]))
         {
         ObjectDelete(p+".News: "+News_Array[p,0]);
         }
      }
   return(0);
   }       

Comments