//+------------------------------------------------------------------+ //| 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 // ========================= // 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); }