Welcome Forex EA downloads & MT4/MT5 auto-trading resources — EAs, Gold EAs, quant tools and real-world automation.
Sign In Sign Up

Retrieve high-impact events from ForexFactory.com and display them in your indicator or Expert Advisor - Expert for MetaTrader 4

author EAcpu | 3 reads | 0 comments |

Retrieve high impact events from ForexFactory.com and display them in your indicator or Expert Advisor - expert for MetaTrader 4

Since I am currently developing an Expert Advisor for Crude Oil and Brent Crude Oil, I would like to get the exact date and time of the "Crude Oil Stocks" report from ForexFactory.com. The report is typically released Wednesday at 10:30 a.m. ET, but the release date may change during holidays. Since this is an important report for my EA, the only way is to check an online service to verify the release date.

The first is to add the OPTIONS | EXPERT ADVISOR tab that will be used to issue the WebRequest website, namely "http://www.forexfactory.com/" (see Figure 1)

Retrieve high impact events from ForexFactory.com and display them in your indicator or Expert Advisor - expert for MetaTrader 4

The next step is to define a structure in the code to store the events. It's somewhere at the top of the code that declares "DailyEvents" as a global variable and defines the maximum number of stored events by the "MaxDailyEvents" variable.

 //Define event structure
structure activity {
string time;
string title;
string currency;
boolean display;
}; #Define max daily events 20 // Increase this number if you think you will have more than 20 high impact events. Event DailyEvents[MaxDailyEvents];

Next we need to retrieve the HTML code from ForexFactory.com and parse it. If you don't understand HTML code, don't worry, I'll walk you through it :)

We first need to construct the URL of the WebRequest. Since I only want their calendar for the current day and not the default (whole week) calendar, we can do this by setting the "day" parameter of the request to today's date and sending the request.

string URL= “http://www.forexfactory.com/calendar.php?day=” ; url += MthName( month ()) + double conversion string ( day (), 0 ) + "." + double conversion string ( year (), 0 );

We then send the request, check for the error code (if any) and convert the returned character array to a string. This makes parsing HTML code easier.

// Convert character array to string HTML = character array to string (result);

Now that we have a string, we can use the "StringFind" function to locate the HTML element. The first thing is to make sure that the HTML returned is indeed today's date, and remove anything that comes before this HTML tag. The function "GetHTMLElement" parses the HTML code and returns the value between the specified HTML tags. See definition below.

// The calendar has been loaded, make sure it is today's date
integer i = string find (html, " " ); if (i == - 1 ) return ( false );
html = string substring (html,i); string date = GetHTMLElement(html, "<span>" , " " ); if (date!= MthName( month ()) + "" + double string ( day (), 0 )) return ( false );

Definition of the "GetHTMLElement" function.

//+------------------------------------------------------------------+
//|Extract HTML elements
//+------------------------------------------------------------------+
String Get HTML element ( string hypertext markup language, string element starts, string element ends)
{
string data = void ;
  
// Find the start and end position of the element integer s = string search (HTML, start of element) + string length (start of element);
Integer e = string search ( string substring (HTML, s), ElementEnd);
  
// Return element content if (e!= 0 ) data = string substring (HTML, s, e);
return (data);
}

Okay, now that we've made sure the calendar returned is today's date, let's start parsing each table row and extracting the elements we need. That is, event time, event currency, event impact, and event title. We need to do this for every table row in the HTML code until the calendar ends or MaxDailyEvents is reached.

After extracting the data for each row, we add it to the DailyEvents structure.

// Now get the table row for each event last = invalid ;
cnrt = 0 ;
Date = double conversion string ( year (), 0 ) + "." + double conversion string ( month (), 0 ) + "." + double conversion string ( day (), 0 ) + "" ; do {
// Get event information time = GetHTMLElement(HTML, " ", " ");
if ( String find (time, " ) == 0 ) time = GetHTMLElement(time, "class=\"next\">" , " " );
if ( stringlength (time) != 0 ) last = time;
if ( stringlength (time) == 0 ) time = last; 
  time = date + time;
  Currency = GetHTMLElement(HTML, " " , " " );
  Effect = GetHTMLElement(HTML, "<span title=\"" , "\" class=\"" );
  i = string find (affect, "impact" );
if ( i != - 1 ) effects = string substring ( effects , 0 , i );
  Title = GetHTMLElement(HTML, "\"Calendar__Event Title\">" , " ");
  
// Is this a high-impact event? if ( String lookup ( symbol (), currency) != - 1 && impact == "high" )
  {
//Add to daily event structure DailyEvents[cntr].displayed = false ;
      DailyEvents[cntr].time = time;
      DailyEvents[cntr].title = title;
      DailyEvents[cntr++].currency = currency;
  }
 
// Cut the HTML string to the next table row i = String Find (HTML, " " );
if ( i != - 1 ) HTML = string substring (HTML, i + 30 );
if ( string find (html, " ") == 0 ) i = - 1 ;
} although (i != - 1 || cntr == MaxDailyEvents);

Once we have parsed all the table rows and reached the end of the calendar, we need to display the events on the chart. I want a vertical line to be displayed if the event happened in the future, and no line to be displayed if it happened in the past.

// Show high impact events (if any) last = invalid ; for (cntr = 0 ; cntr < max daily events; cntr++)
{
if ( StringLength (DailyEvents[cntr].time) == 0 ) rest ;
 
// Create event markers on the chart if the last market time is different if (last != DailyEvents[cntr].time)
  {
      resource = cntr;
// If "pm" is in the string, add 12 hours to the time if ( String lookup (DailyEvents[cntr].time, "PM" ) != - 1 ) DailyEvents[cntr].time = arrival time ( time to time (DailyEvents[cntr].time) + 43200 );
if ( objectCreate ( 0 , event + cntr , object_event , 0 , time_to_time (daily_event[cntr].time), 0 ))
      {
Object set string ( 0 , event + cntr, OBJPROP_TEXT , DailyEvents[cntr].title + ”(” + DailyEvents[cntr].currency + “)” );
object set integer ( 0 , event + cntr, OBJPROP_COLOR , red);
ObjectSetInteger ( 0 , event+cntr, OBJPROP_WIDTH , 2 );
ObjectSetInteger ( 0 , event+cntr, OBJPROP_BACK , true );
objectSet integer ( 0 , event + cntr , OBJPROP_SELECTABLE , false );
ObjectSetInteger ( 0 , event + cntr , OBJPROP_SELECTED , false );
ObjectSetInteger ( 0 , event+cntr, OBJPROP_HIDDEN , true );
object set string ( 0 , event + cntr, OBJPROP_tooltip , DailyEvents[cntr].title + ”(” + DailyEvents[cntr].currency + “)” );
      }
 
// If the event occurs in the future, create a vertical line if ( timecurrent () < TimeOffset(DailyEvents[cntr].time, 0 ))
      {
if ( ObjectCreate ( 0 , VLine + cntr, OBJ_VLINE , 0 , TimeOffset(DailyEvents[cntr].time, 0 ), 0 ))
        {
object set integer ( 0 , VLine + cntr, OBJPROP_COLOR , red);
object set integer ( 0 , VLine + cntr, OBJPROP_WIDTH , 1 );
ObjectSetInteger ( 0 , VLine + cntr , OBJPROP_BACK , true );
object set integer ( 0 , VLine + cntr , OBJPROP_SELECTABLE , false );
object set integer ( 0 , VLine + cntr , OBJPROP_SELECTED , false );
ObjectSetInteger ( 0 , VLine + cntr , OBJPROP_HIDDEN , true );
Object Set String ( 0 , VLine + cntr, OBJPROP_ToolTip , DailyEvents[cntr].title + ”(” + DailyEvents[cntr].currency + “)” );
        }
      }
else DailyEvents[cntr].displayed = true ;
  }else { title = object getString ( 0 , event+resource, objprop_tooltip ); title += "\n" + DailyEvents[cntr].title + "(" + DailyEvents[cntr].currency + ")" ; object set string ( 0 , event+resource, objprop_tooltip , title); if ( timecurrent () < TimeOffset(DailyEvents[cntr].time, 0 )) object set string ( 0 , VLine + res, OBJPROP_tooltip , title); } last time = DailyEvents[cntr].time; }

If it is a future event, I want to notify the user of the upcoming event (if the event is within 5 minutes of the current time) and remove the vertical line. This is done by adding some code in the "start()" function of the EA or indicator.

//+------------------------------------------------------------------+
//|Expert start function |
//+------------------------------------------------------------------+
blank start()
{
string event = void ;
  
// Are there any events with greater impact in the next 5 minutes? for ( integer i = 0 ; i < maximum number of daily events; i++)
  {
if ( StringLength (DailyEvents[i].Time) == 0 ) rest ;
if ( timecurrent () >= timetotime (DailyEvents[i].time) - 300 && timecurrent () < timetotime (DailyEvents[i].time) && !DailyEvents[i].displayed)
      {
// Events after 5 minutes... event += DailyEvents[i].title + "(" + DailyEvents[i].currency + "), " ;
        DailyEvents[i].displayed = true ;
  
// Delete the vertical line associated with the event if ( object find ( "V-line" + double-turn string (i, 0 )) >= 0 ) object delete ( "V-line" + double-turn string (i, 0 ));
      } 
   }
  
// Is there anything to display? if ( stringlength (event) != 0 )
  {
      event += "5 minutes later." ;
alert (event);
  }
}

Finally, we need to get the daily events. This is done by adding a line in the OnInit() function.

 //+------------------------------------------------------------------+
//|Expert initialization function |
//+------------------------------------------------------------------+
Integer initialization ()
{
// Get today's events Get HighImpactEvents();
  
Return ( initialization successful );
}

Nice and easy. You can of course modify the code to display all events for a currency pair, or add input parameters to your indicator or EA to specify the impact to be displayed (high, medium or low), and of course add a check for midnight turnover to get a new daily event list, but I'll let you try it out :)


Attachment download

📎 highimpactevents.mq4 (11 KB)

Source: MQL5 #15505

Verification code Refresh