NewsBacktest

Author: Muller Peter
Orders Execution
Checks for the total of open orders
0 Views
0 Downloads
0 Favorites
NewsBacktest
ÿþ#property copyright "Muller Peter"  

#property link      "https://www.mql5.com/en/users/mullerp04/seller"  

#property version   "1.00"  // EA version

#include <Trade\Trade.mqh>  // Include necessary libraries

#include <CalendarFile.mqh>  



input int TPPoints = 150;  // Take Profit in points

input int SLPoints = 150;  // Stop Loss in points

input uint ExpirySeconds = 500;  // Expiry time in seconds for the pending orders

input double Volume = 0.1;  // Trade volume



CalendarFileReader* FReader;  // Declare a pointer to a CalendarFileReader object



int OnInit()

{

   FReader = new CalendarFileReader();  // Create a new instance of the CalendarFileReader

   string CurrencyBase = SymbolInfoString(_Symbol,SYMBOL_CURRENCY_BASE);  // Get the base currency for the symbol

   string CurrencyProfit = SymbolInfoString(_Symbol,SYMBOL_CURRENCY_PROFIT);  // Get the profit currency for the symbol

   FReader.LoadEvents("Calendar\\"+CurrencyBase+"Events.txt");  // Load event data for the base currency

   FReader.LoadEvents("Calendar\\"+CurrencyProfit+"Events.txt");  // Load event data for the profit currency

   FReader.LoadCountries("Calendar\\Countries.txt");  // Load country data

   FReader.LoadValues("Calendar\\News.bin");  // Load calendar values (news data)

   return(INIT_SUCCEEDED);  // Return success

}



void OnDeinit(const int reason)

{

  delete FReader;  // Delete the CalendarFileReader object when the EA is removed or reset

}



void OnTick()

{

   if(!IsMarketOpen(_Symbol))

      return;

   FReader.Propagate();  // Propagate to the next upcoming event, FReader.next -> next event



   MqlCalendarValue CalendarValue;  // Declare a MqlCalendarValue object to hold event values

   MqlCalendarCountry CalendarCountry;  // Declare a MqlCalendarCountry object to hold country data

   MqlCalendarEvent  CalendarEvent;  // Declare a MqlCalendarEvent object to hold event data

   static datetime Expiry = 0;  // Declare a static variable for expiry time

   CTrade trade;  // Create a trade object



   // Loop through the next 5 events

   for(int i = 0; i < 5; i++)

   {

      if(FReader.next + i >= FReader.ValueCount)  // If there are no more events to process

         return;  // Exit the function



      CalendarValue = FReader.Values[FReader.next + i];  // Get the calendar event value



      if(CalendarValue.time > TimeTradeServer() + 50)  // If the event time is more than 50 seconds in the future

         break;  // Stop processing if the event is too far in the future



      CalendarEvent = FReader.EventById(CalendarValue.event_id);  // Get the event details by its ID

      CalendarCountry = FReader.CountryById(CalendarEvent.country_id);  // Get the country details by country ID

      string currency = CalendarCountry.currency;  // Get the currency associated with the country



      // Skip the event if the currency is not related to the base or profit currency of the symbol

      if(CalendarCountry.currency != SymbolInfoString(_Symbol,SYMBOL_CURRENCY_BASE) && CalendarCountry.currency != SymbolInfoString(_Symbol,SYMBOL_CURRENCY_PROFIT))

         continue;  // Continue to the next event

      // Filter events by name for specific types like CPI, PPI, or interest rate decisions

      bool Filtered = StringContains(CalendarEvent.name, "cpi") || StringContains(CalendarEvent.name, "ppi") ||

      StringContains(CalendarEvent.name, "interest rate decision");



      if(Filtered)  // If the event is filtered (matches the criteria)

      {

         if(Expiry != 0)  // If there is already an active trade

               break;  // Exit the loop



         double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);  // Get the current ask price

         double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);  // Get the current bid price



         // Place buy and sell stop orders for the breakout strategy

         trade.BuyStop(Volume, ask + TPPoints * _Point, NULL, ask + TPPoints * _Point - SLPoints * _Point, ask + 2 * TPPoints * _Point);  // Place buy stop order

         trade.SellStop(Volume, bid - TPPoints * _Point, NULL, bid - TPPoints * _Point + SLPoints * _Point, bid - 2 * TPPoints * _Point);  // Place sell stop order



         Expiry = TimeTradeServer() + ExpirySeconds;  // Set the expiry time for the orders

         Print("\nStarted a Breakout strategy at: " + TimeToString(TimeTradeServer()) + " time.");  // Print strategy start message

         Print("Upcoming event: " + CalendarEvent.name + " Time: " + TimeToString(CalendarValue.time) + " \n");  // Print event details

      }

   }



   // If the expiry time has passed and there is an active strategy

   if(TimeTradeServer() > Expiry && Expiry != 0)

   {

      DeletePending();  // Delete all pending orders

      Expiry = 0;  // Reset the expiry time

   }

}



// StringContains function: Checks if a string contains a substring (case-insensitive by default)

bool StringContains(string base, string containing, bool Cased = false)

{

   // If case-insensitive, convert both strings to lowercase

   if(!Cased)

   {

      StringToLower(base);

      StringToLower(containing);

   }



   int ct = 0;  // Counter to track matching characters



   // Loop through the base string

   for(unsigned i = 0; i < base.Length(); i++)

   {

      if(base.GetChar(i) == containing.GetChar(ct))  // If characters match

         ct++;  // Increment counter

      else 

         ct = 0;  // Reset counter if characters don't match



      // If the entire containing string matches, return true

      if(ct == containing.Length() - 1)

         return true;



      // If remaining base string is shorter than containing string, return false

      if(base.Length() - i < containing.Length() && !ct)

         return false;

   }

   return false;  // Return false if no match is found

}



// DeletePending function: Deletes all pending orders associated with the EA's magic number

void DeletePending()

{

   COrderInfo ordinfo;  // Order information object

   CTrade trade;        // Trade object



   // Loop through all orders and delete those with the EA's magic number

   for(int i = OrdersTotal() - 1; i >= 0; i--)

   {

      ordinfo.SelectByIndex(i);  // Select the order by index

      trade.OrderDelete(ordinfo.Ticket());  // Delete the selected order

   }

}





bool IsMarketOpen(const string symbol, const bool debug = false)

{

    datetime from = NULL;

    datetime to = NULL;

    datetime serverTime = TimeTradeServer();



    // Get the day of the week

    MqlDateTime dt;

    TimeToStruct(serverTime,dt);

    const ENUM_DAY_OF_WEEK day_of_week = (ENUM_DAY_OF_WEEK) dt.day_of_week;



    // Get the time component of the current datetime

    const int time = (int) MathMod(serverTime,PeriodSeconds(PERIOD_D1));



    if ( debug ) PrintFormat("%s(%s): Checking %s", __FUNCTION__, symbol, EnumToString(day_of_week));



    // Brokers split some symbols between multiple sessions.

    // One broker splits forex between two sessions (Tues thru Thurs on different session).

    // 2 sessions (0,1,2) should cover most cases.

    int session=2;

    while(session > -1)

    {

        if(SymbolInfoSessionTrade(symbol,day_of_week,session,from,to ))

        {

            if ( debug ) PrintFormat(    "%s(%s): Checking %d>=%d && %d<=%d",

                                        __FUNCTION__,

                                        symbol,

                                        time,

                                        from,

                                        time,

                                        to );

            if(time >=from && time <= to )

            {

                if ( debug ) PrintFormat("%s Market is open", __FUNCTION__);

                return true;

            }

        }

        session--;

    }

    if ( debug ) PrintFormat("%s Market not open", __FUNCTION__);

    return false;

}

Comments