//+------------------------------------------------------------------+ //| InvestingForexCalendar.mq4 | //| Lorentzos Roussos 2020 | //| https://www.mql5.com/en/users/lorio | //+------------------------------------------------------------------+ #property copyright "Lorentzos Roussos 2020" #property link "https://www.mql5.com/en/users/lorio" #property version "1.00" #property strict #include input string noteNF="[---]";//NEWS FILTER SETTINGS : input bool NF_Use=true;//Use ? input int NF_CheckInterval=600;//Check Interval in seconds (for new news day)-it will load once input bool NF_LowNews=false;//Filter Low Impact News [1/3 star] input int NF_LowNews_Before=10;//Low Impact News minutes before : input int NF_LowNews_After=10;//Low Impact News minutes after : input bool NF_MedNews=false;//Filter Impact Medium News [2/3 star] input int NF_MedNews_Before=30;//Medium Impact News minutes before : input int NF_MedNews_After=30;//Medium Impact News minutes after : input bool NF_HighNews=true;//Filter High Impact News [3/3 star] input int NF_HighNews_Before=45;//High Impact News minutes before : input int NF_HighNews_After=45;//High Impact News minutes after : input bool NF_LowSpeech=false;//Filter Low Impact Speech [1/3 star] input int NF_LowSpeech_Before=10;//Low Impact Speech minutes before : input int NF_LowSpeech_After=10;//Low Impact Speech minutes after : input bool NF_MedSpeech=false;//Filter Impact Medium Speech [2/3 star] input int NF_MedSpeech_Before=30;//Medium Impact Speech minutes before : input int NF_MedSpeech_After=30;//Medium Impact Speech minutes after : input bool NF_HighSpeech=false;//Filter High Impact Speech [3/3 star] input int NF_HighSpeech_Before=45;//High Impact Speech minutes before : input int NF_HighSpeech_After=45;//High Impact Speech minutes after : /* ---embed#1 : daily news ,all 3 importances , countries EUR,USD,AUD,NZD,JPY,CHF,CAD,GBP - UTC(GMT) timezone +-00:00
Real Time Economic Calendar provided by Investing.com.
*/ string embed_1_link="https://sslecal2.forexprostools.com?columns=exc_flags,exc_currency,exc_importance,exc_actual,exc_forecast,exc_previous&category=_employment,_economicActivity,_inflation,_credit,_centralBanks,_confidenceIndex,_balance,_Bonds&importance=1,2,3&countries=25,6,72,22,17,10,35,43,26,12,4,5&calType=day&timeZone=55&lang=1"; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ web_request WR; string news_folder="NewsFromInvesting",news_file="_list.news",block_file="_block.news"; int OnInit() { //--- create timer news_file=_Symbol+"_list.news"; block_file=_Symbol+"_block.news"; EmptyEvents(); //setup NewsFilterSetup(); NewsFilter.Load(news_folder,news_file,block_file); NewsFilter.Check(news_folder,news_file,block_file,false); EventSetTimer(10); //--- return(INIT_SUCCEEDED); } void NewsFilterSetup() { NewsFilter.Reset(); if(NF_Use) { if(NF_LowNews){NewsFilter.ActivateLowNews(NF_LowNews_Before,NF_LowNews_After);} if(NF_MedNews){NewsFilter.ActivateMedSpeech(NF_MedNews_Before,NF_MedNews_After);} if(NF_HighNews){NewsFilter.ActivateHighSpeech(NF_HighNews_Before,NF_HighNews_After);} if(NF_LowSpeech){NewsFilter.ActivateLowSpeech(NF_LowSpeech_Before,NF_LowSpeech_After);} if(NF_MedSpeech){NewsFilter.ActivateMedSpeech(NF_MedSpeech_Before,NF_MedSpeech_After);} if(NF_HighSpeech){NewsFilter.ActivateHighSpeech(NF_HighSpeech_Before,NF_HighSpeech_After);} } } string Mozilla="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0"; void SetupWR(bool &loaded) { loaded=false; WR.SetupWithBasicHeaders(wr_type_get,"https://sslecal2.forexprostools.com",5000); WR.SetReferer("https://www.investing.com"); WR.SetUserAgent(Mozilla); WR.Parameters+"columns"="exc_flags,exc_currency,exc_importance,exc_actual,exc_forecast,exc_previous"; WR.Parameters+"category"="_employment,_economicActivity,_inflation,_credit,_centralBanks,_confidenceIndex,_balance,_Bonds"; WR.Parameters+"importance"="1,2,3"; WR.Parameters+"countries"="25,6,72,22,17,10,35,43,26,12,4,5"; WR.Parameters+"calType"="day"; WR.Parameters+"timeZone"="55"; WR.Parameters+"lang"="1"; simple_result result=WR.Send(); Print("Errors : "+result.error); if(result.status==200) { loaded=true; //Alert("response headers : \n"+result.response_headers+"\nresponse body : \n"+result.response_body); ExtractNewsFromHTML(result.response_body); } } //NEWS EXTACTOR struct investing_news_event { string name,currency,timestring,daystring; int importance;//1 low 2 medi 3 high int gmthours,gmtminutes; bool expired,speech; void Load(string folder,string file) { string filename=folder+"\\"+file; //file exists if(FileIsExist(filename)) { int fop=FileOpen(filename,FILE_READ|FILE_TXT); if(fop!=INVALID_HANDLE){ name=FileReadString(fop); currency=FileReadString(fop); timestring=FileReadString(fop); daystring=FileReadString(fop); importance=(int)StringToInteger(FileReadString(fop)); gmthours=(int)StringToInteger(FileReadString(fop)); gmtminutes=(int)StringToInteger(FileReadString(fop)); expired=false; if(StringFind(FileReadString(fop),"TRUE",0)!=-1){expired=true;} speech=false; if(StringFind(FileReadString(fop),"TRUE",0)!=-1){speech=true;} FileClose(fop); } } //file exists ends here } void Save(string folder,string file) { string filename=folder+"\\"+file; if(FileIsExist(filename)){FileDelete(filename);} int fop=FileOpen(filename,FILE_WRITE|FILE_TXT); if(fop!=INVALID_HANDLE){ FileWriteString(fop,name+"\n"); FileWriteString(fop,currency+"\n"); FileWriteString(fop,timestring+"\n"); FileWriteString(fop,daystring+"\n"); FileWriteString(fop,IntegerToString(importance)+"\n"); FileWriteString(fop,IntegerToString(gmthours)+"\n"); FileWriteString(fop,IntegerToString(gmtminutes)+"\n"); if(expired){FileWriteString(fop,"TRUE\n");}if(!expired){FileWriteString(fop,"FALSE\n");} if(speech){FileWriteString(fop,"TRUE\n");}if(!speech){FileWriteString(fop,"FALSE\n");} FileClose(fop); } } }; investing_news_event NewsEvents[]; int NewsEventsTotal=0,NewsEventsSize=0,NewsEventsStep=20; void ExtractNewsFromHTML(string &html) { int found_start=-1,found_end=-1; found_start=StringFind(html,"",0); found_end=StringFind(html,"",0); if(found_start!=-1&&found_end!=-1){ Print("Found Data Edges :"); int len=found_end-found_start; string extract=StringSubstr(html,found_start,len); //get day string int fa=StringFind(extract,"",0); int fb=StringFind(extract,"",fa+4); int fc=fb; int e_len=fb-fa;//extract length string sub_extrak=StringSubstr(extract,fa,e_len); fa=StringFind(sub_extrak,"\">",0); fb=StringFind(sub_extrak,"",0); e_len=fb-fa; sub_extrak=StringSubstr(sub_extrak,fa+2,e_len-2); string DayTitle=TextGapsTreat(sub_extrak); Print("Day Title : "+DayTitle); //get day string ends here //start string packets[]; //replace characters that will be used int rep=StringReplace(extract,"@",""); //replace separator text with character rep=StringReplace(extract,"1) { //loop in packets for(int p=1;p",0); //if found if(fa!=-1) { //next fa=StringFind(packets[p],"\">",fa+3); //if found if(fa!=-1) { fb=StringFind(packets[p],"",fa+3); //if found if(fb!=-1) { //extract string e_len=fb-fa; sub_extrak=StringSubstr(packets[p],fa+2,e_len-2); string TimeString=TextGapsTreat(sub_extrak); fc=fb+6; //find span fa=StringFind(packets[p],"",fc); if(fa!=-1) { //find td fb=StringFind(packets[p],"",fa+8); if(fb!=-1) { e_len=fb-fa; sub_extrak=StringSubstr(packets[p],fa+7,e_len-7); string Currency=TextGapsTreat(sub_extrak); fc=fb+6; //find class sentiment fa=StringFind(packets[p],"class=\"sentiment\"",fc); if(fa!=-1) { //find title fa=StringFind(packets[p],"title=\"",fa+StringLen("class=\"sentiment\"")); if(fa!=-1) { fb=StringFind(packets[p],"\"",fa+StringLen("title=\"")); if(fb!=-1) { //extract sentiment e_len=fb-fa; sub_extrak=StringSubstr(packets[p],fa+2,e_len-2); int Sentiment=0; bool uppa=StringToLower(sub_extrak); if(StringFind(sub_extrak,"volatility",0)!=-1) { if(StringFind(sub_extrak,"low",0)!=-1){Sentiment=1;} if(StringFind(sub_extrak,"moderate",0)!=-1){Sentiment=2;} if(StringFind(sub_extrak,"high",0)!=-1){Sentiment=3;} fc=fb+2; //find td fa=StringFind(packets[p],"",fc); if(fa!=-1) { fc=fa+6; fa=StringFind(packets[p],"\">",fc); if(fa!=-1) { fb=StringFind(packets[p],"<",fa+3); if(fb!=-1) { e_len=fb-fa; sub_extrak=StringSubstr(packets[p],fa+2,e_len-2); string EventTitle=TextGapsTreat(sub_extrak); //check if speech bool IsSpeech=false; if(StringFind(packets[p],"title=\"Speech\"",0)!=-1){IsSpeech=true;} //add event AddEvent(DayTitle,Currency,EventTitle,TimeString,Sentiment,IsSpeech); //check if speech ends here } } } //find td ends here } //extract sentiment ends her e } } //find title ends here } //find class sentiment ends here } //find td ends here } //find span ends here } //if found } //if found } //if found } //loop in packets ends her e } //start } PrintEvents(); } //NEWS EXTRACTOR ENDS HERE void EmptyEvents() { ArrayFree(NewsEvents); NewsEventsTotal=0; NewsEventsSize=0; } void AddEvent(string daytitle, string currency, string title, string timestring, int impact, bool isspeech) { NewsEventsTotal++; if(NewsEventsTotal>NewsEventsSize){ NewsEventsSize+=NewsEventsStep; ArrayResize(NewsEvents,NewsEventsSize,0); } int ix=NewsEventsTotal-1; NewsEvents[ix].expired=false; NewsEvents[ix].daystring=daytitle; NewsEvents[ix].timestring=timestring; NewsEvents[ix].currency=currency; NewsEvents[ix].importance=impact; NewsEvents[ix].name=title; NewsEvents[ix].speech=isspeech; timestring_to_hours_minutes(timestring,NewsEvents[ix].gmthours,NewsEvents[ix].gmtminutes,":"); //test save load /* if(NewsEvents[ix].speech) { int e=ix; string txt="SAVED : \n"; txt+="["+NewsEvents[e].daystring+"]\n"; txt+="["+NewsEvents[e].timestring+"||"+IntegerToString(NewsEvents[e].gmthours)+":"+IntegerToString(NewsEvents[e].gmtminutes)+"]["+IntegerToString(NewsEvents[e].importance)+"]["+NewsEvents[e].currency+"]["+NewsEvents[e].name+"]\n"; //check check_event(e); if(!NewsEvents[e].expired){txt+="StillActive\n";} if(NewsEvents[e].expired){txt+="EventOver\n";} if(!NewsEvents[e].speech){txt+="IsNotSpeech\n";} if(NewsEvents[e].speech){txt+="IsSpeech\n";} Alert(txt); NewsEvents[e].Save("TestNews","TestItem.txt"); NewsEvents[e].Load("TestNews","TestItem.txt"); txt="LOADED : \n"; txt+="["+NewsEvents[e].daystring+"]\n"; txt+="["+NewsEvents[e].timestring+"||"+IntegerToString(NewsEvents[e].gmthours)+":"+IntegerToString(NewsEvents[e].gmtminutes)+"]["+IntegerToString(NewsEvents[e].importance)+"]["+NewsEvents[e].currency+"]["+NewsEvents[e].name+"]\n"; //check check_event(e); if(!NewsEvents[e].expired){txt+="StillActive\n";} if(NewsEvents[e].expired){txt+="EventOver\n";} if(!NewsEvents[e].speech){txt+="IsNotSpeech\n";} if(NewsEvents[e].speech){txt+="IsSpeech\n";} Alert(txt); } */ //test save load ends here } void timestring_to_hours_minutes(string timestring,int &hours,int &minutes,string separator) { ushort usep=StringGetCharacter(separator,0); string parts[]; int k=StringSplit(timestring,usep,parts); if(k==1){minutes=0;hours=(int)StringToInteger(parts[0]);} if(k>1){hours=(int)StringToInteger(parts[0]);minutes=(int)StringToInteger(parts[1]);} } void check_event(int ix) { //get gmt hours ,and minutes datetime time_gmt=TimeGMT(); int gmt_actual_hour=TimeHour(time_gmt); int gmt_actual_minute=TimeMinute(time_gmt); //turn to minutes ,theres not slipping into next days etc int actual_mins=gmt_actual_hour*60+gmt_actual_minute; int event_mins=NewsEvents[ix].gmthours*60+NewsEvents[ix].gmtminutes; if(actual_mins>=event_mins){NewsEvents[ix].expired=true;} } void PrintEvents() { string txt="Events Caught = "+IntegerToString(NewsEventsTotal)+"\n"; for(int e=0;e=Base.BlockLifts))){ allow=true; if(Base.BlockCarry&&time_gmt>=Base.BlockLifts){Base.BlockCarry=false;Base.BlockLifts=0;will_save=true;} //from the last to the first for(int e=NewsEventsTotal-1;e>=0;e--) { //will use news class to return data news_check checked=CheckEvent(NewsEvents[e],time_gmt); if(checked.Active) { if(time_gmt>=checked.minTime&&time_gmt<=checked.maxTime){allow=false;break;} } } //from the last to the first ends here //loop into news ends here } if(will_save){Save(folder,file,blk_file);} return(allow); } //check used before trades void Check(string folder,string file,string blk_file,bool check_timestamp) { bool will_save=false; //difference in seconds for checks int secs=(int)(TimeCurrent()-Base.LastCheck); if(!check_timestamp||secs>=NF_CheckInterval) { Print("Check"); //if connected if(IsConnected()) { //if loaded if(Base.Loaded) { //if in block state check if its breached if(Base.BlockCarry&&TimeGMT()>=Base.BlockLifts){Base.BlockCarry=false;Base.BlockLifts=0;will_save=true;} //check for day change datetime time_gmt=TimeGMT(); int doy=TimeDayOfYear(time_gmt); if(doy!=Base.GMTLastDayOfYear) { datetime time_gmt_yesterday=(datetime)(time_gmt-24*60*60); will_save=true; Base.BlockCarry=false;Base.BlockLifts=0; //if theres an event list present check for carry blocks if(NewsEventsTotal>0) { datetime max_carry_time=0; int max_carry_event=-1; //from the last to the first for(int e=NewsEventsTotal-1;e>=0;e--) { //will use news class to return data news_check checked=CheckEvent(NewsEvents[e],time_gmt_yesterday); if(checked.Active&&max_carry_time!=0&&checked.maxTime>max_carry_time){max_carry_time=checked.maxTime;max_carry_event=e;} if(checked.Active&&max_carry_time==0){max_carry_time=checked.maxTime;max_carry_event=e;} } //from the last to the first ends here if(max_carry_time!=0){Base.BlockCarry=true;Base.BlockLifts=max_carry_time;BlockCarryEvent=NewsEvents[max_carry_event];will_save=true;} } //if theres an event list present check for carry blocks ends here //load EmptyEvents(); SetupWR(Base.Loaded); Base.GMTLastDayOfYear=doy; will_save=true; } //check for day change ends here } //if loaded ends here //if not loaded ,try again if(!Base.Loaded) { EmptyEvents(); SetupWR(Base.Loaded); datetime time_gmt=TimeGMT(); Base.GMTLastDayOfYear=TimeDayOfYear(time_gmt); will_save=true; } if(will_save){Save(folder,file,blk_file);} } //if connected ends here Base.LastCheck=TimeCurrent(); } //difference in seconds ends here } //check and event and return if it blocks and its minutes news_check CheckEvent(investing_news_event &event,datetime &gmt_time) { news_check result; //low news if(LowNews.Active&&event.importance==1&&!event.speech){result.Active=true;result.MinutesBefore=LowNews.MinutesBefore;result.MinutesAfter=LowNews.MinutesAfter;} //med news if(MedNews.Active&&event.importance==2&&!event.speech){result.Active=true;result.MinutesBefore=MedNews.MinutesBefore;result.MinutesAfter=MedNews.MinutesAfter;} //high news if(HighNews.Active&&event.importance==3&&!event.speech){result.Active=true;result.MinutesBefore=HighNews.MinutesBefore;result.MinutesAfter=HighNews.MinutesAfter;} //low speech if(LowSpeeches.Active&&event.importance==1&&event.speech){result.Active=true;result.MinutesBefore=LowSpeeches.MinutesBefore;result.MinutesAfter=LowSpeeches.MinutesAfter;} //med speech if(MedSpeeches.Active&&event.importance==2&&event.speech){result.Active=true;result.MinutesBefore=MedSpeeches.MinutesBefore;result.MinutesAfter=MedSpeeches.MinutesAfter;} //high speech if(HighSpeeches.Active&&event.importance==3&&event.speech){result.Active=true;result.MinutesBefore=HighSpeeches.MinutesBefore;result.MinutesAfter=HighSpeeches.MinutesAfter;} //if it fired off anything ,then create surrounding times and if(result.Active) { MqlDateTime formation; TimeToStruct(gmt_time,formation); //change time to event formation.hour=event.gmthours; formation.min=event.gmtminutes; result.minTime=(datetime)(StructToTime(formation)-result.MinutesBefore*60); result.maxTime=(datetime)(StructToTime(formation)+result.MinutesAfter*60); //and if our time } return(result); } }; news_filter NewsFilter; //news filter controller ends here //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- destroy timer // EventKillTimer(); EmptyEvents(); NewsFilter.Save(news_folder,news_file,block_file); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+ //| Timer function | //+------------------------------------------------------------------+ void OnTimer() { //--- NewsFilter.Check(news_folder,news_file,block_file,true); } //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { //--- } //+------------------------------------------------------------------+