Implement a time based EA (Limit trading sessions to specific Hours)

OTMT Howard
73

Hello MQL5 Community,

I am currently developing an EA based on two MAs and CCI Cross conditions.

I'd like to implement a time-based trading strategy and would appreciate your assistance.

As I am in the process of learning coding. I've received helpful advice from the community as well as materials to work through as I go.

My plan is to create a time function similar to the one in the attached sample file, which I acquired from "GitHub." I have added a bit of information to it as an idea of what I would like.

The highlighted section would be my additional check from the variables section.

Example:

   if(Hour() == StartHour) {  

      if(IsFirstTick == true) {

         IsFirstTick = false;

And my entry time condition:

         if(Open[0] < Open[StartHour] - MinPipLimit*vPoint) {

            //check ma

            if(Close[0] > maCross || MAFilter == false)

The opposite will apply for the sell condition as well, and with the "if (IsFirstTick == true"). I will be using the "OpenBar" instead.

extern int     StartHour      = 9; // Start hour of Trading day
extern int     MinPipLimit    = 0;
extern int     TakeProfit     = 40;
extern int     StopLoss       = 40;
extern double  Lots           = 1; // Volume
extern bool    TrailingStop   = false;  //Trailing Stop
extern int     TrailingStart  = 15;   //Trailing Start (pips)
extern int     TrailingStep   = 5;    //Trailing Step (pips)
input int      Slippage       = 0;
extern int     Magic          = 50262802;        // Magic Number


// CCI Inputs
input int                  CCIPeriod      =  14;            // CCI Period
input ENUM_APPLIED_PRICE   CCIPrice       =  PRICE_CLOSE;   // CCI Applied price
// Fast MA Inputs
input int                  MA_Period  =  14;            // Fast MA periods
input ENUM_MA_METHOD       MA_Method   =  MODE_EMA;      // Fast MA Method
input int                  MA_Shift    =  0;
input ENUM_APPLIED_PRICE   MA_Price    =  PRICE_CLOSE;   // Fast MA Price
// Slow MA Inputs
input int                  SlowMAPeriods  =  28;            // Slow MA periods
input ENUM_MA_METHOD       SlowMAMethod   =  MODE_EMA;      // Slow MA Method
input ENUM_APPLIED_PRICE   SlowMAPrice    =  PRICE_CLOSE;   // Slow MA Price
// Standard trading inputs
input string               TradeComment   =  "CCI2MA";      // Trade comment

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnInit()
  {
//---
// Detect 3/5 digit brokers for Point and Slippage

   if(Point == 0.00001)
     { vPoint = 0.0001; vSlippage = Slippage *10;}
   else
     {
      if(Point == 0.001)
        { vPoint = 0.01; vSlippage = Slippage *10;}
      else
         vPoint = Point;
      vSlippage = Slippage;

      if(TrailingStop && TrailingStart <= 0)
        {
         Alert("Parameters incorrect");
         return (INIT_PARAMETERS_INCORRECT);
        }
      myPoint     = GetPipPoint(Symbol());
     }
     {
      Print("Free margin for 1 lot=",MarketInfo(Symbol(), MODE_MARGINREQUIRED));
      Print("Freezing Distance[pts]=",MarketInfo(Symbol(), MODE_FREEZELEVEL));
      Print("Min Allowed Distance[pts]=",MarketInfo(Symbol(), MODE_STOPLEVEL));
      Print("MODE_LOTSIZE = ", MarketInfo(Symbol(), MODE_LOTSIZE));
      Print("MODE_MINLOT = ", MarketInfo(Symbol(), MODE_MINLOT));
      Print("MODE_LOTSTEP = ", MarketInfo(Symbol(), MODE_LOTSTEP));
      Print("MODE_MAXLOT = ", MarketInfo(Symbol(), MODE_MAXLOT));
     }
//---
   return(INIT_SUCCEEDED);
  }
  
// Global Variables
double vPoint;
int vSlippage;
double   myPoint = Point()*10;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(!(bool)TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
      return;

   static int  maCross  =  0;
   static int  cciCross =  0;
   static int  ticket = 0;
   string comment;
   setTrailingStop(Magic);

   bool  newBar   =  NewBar();
   if(newBar)
     {
      double   cci1     =  iCCI(Symbol(), Period(), CCIPeriod, CCIPrice, 1);
      double   cci2     =  iCCI(Symbol(), Period(), CCIPeriod, CCIPrice, 2);

      if(cci1<100 && cci2>=100)
         cciCross =  1;
      if(cci1>-100 && cci2<=-100)
         cciCross =  -1;

      double   fastMa1  =  iMA(Symbol(),0, MA_Period, MA_Shift, MA_Method, MA_Price, 1);
      double   fastMa2  =  iMA(Symbol(),0, MA_Period, MA_Shift, MA_Method, MA_Price, 2);
      double   slowMa1  =  iMA(Symbol(),0, SlowMAPeriods, MA_Shift, SlowMAMethod, SlowMAPrice, 1);
      double   slowMa2  =  iMA(Symbol(),0, SlowMAPeriods, MA_Shift, SlowMAMethod, SlowMAPrice, 2);

      if(fastMa1>slowMa1 && fastMa2<=slowMa2)
        {
         maCross  =  -1;
         ticket = (ORDER_TYPE_SELL);
        }

      if(fastMa1<slowMa1 && fastMa2>=slowMa2)
        {
         maCross  =  1;
         ticket = (ORDER_TYPE_BUY);
        }
      if(maCross!=0 && maCross==cciCross)
        {
         if(OpenTrade(maCross)>0)
           {
            maCross  =  0;
            cciCross =  0;
           }
        }
     }
  }

//+------------------------------------------------------------------+
//|                     Auxiliary Functions                          |
//+------------------------------------------------------------------+
int FindTicket(int M)
  {
   int ret = 0;
   int total = OrdersTotal();
   for(int i = 0 ; i < total ; i++)
     {
      bool res;
      res = OrderSelect(i, SELECT_BY_POS,MODE_TRADES);
      if(res == true)
        {
         if(OrderMagicNumber() == M)
           {
            ret = OrderTicket();
            break;
           }
        }
     }

   return(ret);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int   OpenTrade(int maCross)
  {


   if(maCross>0)
     {
      return(OrderSend(Symbol(), OP_BUY, Lots, Ask, vSlippage, Bid-StopLoss*vPoint, Bid+TakeProfit*vPoint, "Set by Process Expert Advisor", Magic,0,Blue));
     }
   if(maCross<0)
     {
      return(OrderSend(Symbol(), OP_SELL, Lots, Bid, vSlippage, Ask+StopLoss*vPoint, Ask-TakeProfit*vPoint, "Set by Process Expert Advisor", Magic,0,Blue));
     }
   return(0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool  NewBar()
  {
   static datetime   current  =  0;
   datetime          now      =  iTime(Symbol(), Period(), 0);
   if(now == current)
      return(false);
   current  =  now;
   return(true);
  }

//+------------------------------------------------------------------+
//|                        Trailing Stop                             |
//+------------------------------------------------------------------+
void setTrailingStop(int magicNumber=0)
  {
   if(TrailingStop==false)
      return;

   int      tOrder = 0;
   string   pair = "";
   double   sl = 0.0, tp = 0.0;

   pair = Symbol();

   tOrder = OrdersTotal();
   for(int i=tOrder-1; i>=0; i--)
     {
      bool hrsSelect = OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
      if(OrderMagicNumber() == magicNumber && StringFind(OrderSymbol(), pair, 0) == 0)
        {
         if(OrderType() == OP_BUY)
           {
            if((Bid - (TrailingStart * myPoint)) >= OrderOpenPrice()
               && (Bid - ((TrailingStart+TrailingStep) * myPoint) >= OrderStopLoss())
              )
              {
               sl = NormalizeDouble(Bid - (TrailingStart * myPoint), Digits());
               if(!OrderModify(OrderTicket(), OrderOpenPrice(), sl, OrderTakeProfit(), 0, clrBlue))
                 {
                  Print("#", OrderTicket(), " get minimum stop level");
                 }
              }
           }

         if(OrderType() == OP_SELL)
           {
            if((Ask + (TrailingStart * myPoint)) <= OrderOpenPrice()
               && ((Ask + ((TrailingStart+TrailingStep) * myPoint) <= OrderStopLoss()) || OrderStopLoss() == 0.0)
              )
              {
               sl = NormalizeDouble(Ask + (TrailingStart * myPoint), Digits());
               if(!OrderModify(OrderTicket(), OrderOpenPrice(), sl, OrderTakeProfit(), 0, clrBlue))
                 {
                  Print("#", OrderTicket(), " get minimum stop level");
                 }
              }
           }
        } //end if magicNumber
     }//end for
  }

//+------------------------------------------------------------------+
//|                       Broker Pip Points                                           |
//+------------------------------------------------------------------+

// Fungsi GetPipPoint
double GetPipPoint(string pair)
  {
   double point= 0.0;
   int digits = (int) MarketInfo(pair, MODE_DIGITS);
   if(digits == 2 || digits== 3)
      point= 0.01;
   else
      if(digits== 4 || digits== 5)
         point= 0.0001;
   return(point);
  }
//+------------------------------------------------------------------+
R4tna C
143
R4tna C  
OTMT Howard:

Hello MQL5 Community,

I am currently developing an EA based on two MAs and CCI Cross conditions.

I'd like to implement a time-based trading strategy and would appreciate your assistance.

As I am in the process of learning coding. I've received helpful advice from the community as well as materials to work through as I go.

My plan is to create a time function similar to the one in the attached sample file, which I acquired from "GitHub." I have added a bit of information to it as an idea of what I would like.

The highlighted section would be my additional check from the variables section.

Example:

   if(Hour() == StartHour) {  

      if(IsFirstTick == true) {

         IsFirstTick = false;

And my entry time condition:

         if(Open[0] < Open[StartHour] - MinPipLimit*vPoint) {

            //check ma

            if(Close[0] > maCross || MAFilter == false)

The opposite will apply for the sell condition as well, and with the "if (IsFirstTick == true"). I will be using the "OpenBar" instead.

I currently get two return errors of which I have tried numerous times to resolve with no success. 

1a. Alert("Parameters incorrect"); return (INIT_PARAMETERS_INCORRECT); and the other at 

2b. return (INIT_SUCCEEDED);

The OnInit() function in which you have placed this code has return type "void" - usually it should be "int OnInit()"


OTMT Howard
73
OTMT Howard  
R4tna C #:

The OnInit() function in which you have placed this code has return type "void" - usually it should be "int OnInit()"


Thank you. I will attend to it.
OTMT Howard
73
OTMT Howard  
OTMT Howard #:
Thank you. I will attend to it.

I amended the 'voiid On Init" function as advised and it resolved my errors.


Regards,

R4tna C
143
R4tna C  
OTMT Howard #:

I amended the 'voiid On Init" function as advised and it resolved my errors.


Regards,

Great!

R4tna C
143
R4tna C  
OTMT Howard #:

would you perhaps know of any method as to how i can integrate the time-based entry function into my existing code?.

I did not fully understand your requirement, but there are 2 methods I have used to execute based on specific times:


Example1 - if you want to delay trading for 60 secs (for example), create a variable which holds the target time.

ulong nextTradeTime = TimeCurrent() + 60;

At each tick you can then check if the delay has passed:

if(Timecurrent() <  nextTradeTime)
{
return(-1); //don't execute
}
else
{
//set next trade time and execute
}


Example 2 - Use the TimeToStruct() function with the MqlDateTime structure.

You can convert the current time to a struct and then examine the date, day, hour, min, sec with the target time you want - there are examples in the documentation

https://www.mql5.com/en/docs/constants/structures/mqldatetime

TimeToStruct
Documentation on MQL5: Constants, Enumerations and Structures / Data Structures / Date Type Structure
Documentation on MQL5: Constants, Enumerations and Structures / Data Structures / Date Type Structure
  • www.mql5.com
Date Type Structure - Data Structures - Constants, Enumerations and Structures - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
OTMT Howard
73
OTMT Howard  
R4tna C #:

I did not fully understand your requirement, but there are 2 methods I have used to execute based on specific times:


Example1 - if you want to delay trading for 60 secs (for example), create a variable which holds the target time.

ulong nextTradeTime = TimeCurrent() + 60;

At each tick you can then check if the delay has passed:


Example 2 - Use the TimeToStruct() function with the MqlDateTime structure.

You can convert the current time to a struct and then examine the date, day, hour, min, sec with the target time you want - there are examples in the documentation

https://www.mql5.com/en/docs/constants/structures/mqldatetime

TimeToStruct

Hei R4tna C #:

My idea is to restrict trading actions to specific hours, while also checking the MinPiPLimit before executing a trade.

I've updated my code to reflect the changes I intend to make as part of my strategy.

i hope my explanation is clear for your support.

The additions are found at these points: " if(Hour() == StartHour) " and "int   OpenTrade(int maCross)", where my entry conditions are located. 

replaced values are:

 if( maCross>0 ) {

 return (OrderSend(Symbol(), OP_BUY, Lots, Ask, vSlippage, Bid-StopLoss*vPoint, Bid+TakeProfit*vPoint, "Set by Process Expert Advisor", Magic,0,Blue)); }

   if ( maCross<0 ) {

 return (OrderSend(Symbol(), OP_SELL, Lots, Bid, vSlippage, Ask+StopLoss*vPoint, Ask-TakeProfit*vPoint, "Set by Process Expert Advisor", Magic,0,Blue));}

   return(0);}

I however get the following errors with this addition as shown below:

The third is found at the On Init function:

myPoint     = GetPipPoint(Symbol());

And the parantheses at the start of "OnTick()" and at the end of my code.

extern int     StartHour      = 9; // Start hour of Trading day
extern int     MinPipLimit    = 0;
extern int     TakeProfit     = 40;
extern int     StopLoss       = 40;
extern double  Lots           = 1; // Volume
extern bool    TrailingStop   = false;  //Trailing Stop
extern int     TrailingStart  = 15;   //Trailing Start (pips)
extern int     TrailingStep   = 5;    //Trailing Step (pips)
input int      Slippage       = 0;
extern int     Magic          = 50262802;        // Magic Number


// CCI Inputs
input int                  CCIPeriod      =  14;            // CCI Period
input ENUM_APPLIED_PRICE   CCIPrice       =  PRICE_CLOSE;   // CCI Applied price
// Fast MA Inputs
input int                  MA_Period  =  14;            // Fast MA periods
input ENUM_MA_METHOD       MA_Method   =  MODE_EMA;      // Fast MA Method
input int                  MA_Shift    =  0;
input ENUM_APPLIED_PRICE   MA_Price    =  PRICE_CLOSE;   // Fast MA Price
// Slow MA Inputs
input int                  SlowMAPeriods  =  28;            // Slow MA periods
input ENUM_MA_METHOD       SlowMAMethod   =  MODE_EMA;      // Slow MA Method
input ENUM_APPLIED_PRICE   SlowMAPrice    =  PRICE_CLOSE;   // Slow MA Price
// Standard trading inputs
input string               TradeComment   =  "CCI2MA";      // Trade comment

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
// Detect 3/5 digit brokers for Point and Slippage

   if(Point == 0.00001)
     { vPoint = 0.0001; vSlippage = Slippage *10;}
   else
     {
      if(Point == 0.001)
        { vPoint = 0.01; vSlippage = Slippage *10;}
      else
         vPoint = Point;
      vSlippage = Slippage;

      if(TrailingStop && TrailingStart <= 0)
        {
         Alert("Parameters incorrect");
         return (INIT_PARAMETERS_INCORRECT);
        }
      myPoint     = GetPipPoint(Symbol());
     }
     {
      Print("Free margin for 1 lot=",MarketInfo(Symbol(), MODE_MARGINREQUIRED));
      Print("Freezing Distance[pts]=",MarketInfo(Symbol(), MODE_FREEZELEVEL));
      Print("Min Allowed Distance[pts]=",MarketInfo(Symbol(), MODE_STOPLEVEL));
      Print("MODE_LOTSIZE = ", MarketInfo(Symbol(), MODE_LOTSIZE));
      Print("MODE_MINLOT = ", MarketInfo(Symbol(), MODE_MINLOT));
      Print("MODE_LOTSTEP = ", MarketInfo(Symbol(), MODE_LOTSTEP));
      Print("MODE_MAXLOT = ", MarketInfo(Symbol(), MODE_MAXLOT));
     }
//---
   return(INIT_SUCCEEDED);
  }
  
// Global Variables
double vPoint;
int vSlippage;
double   myPoint = Point()*10;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(!(bool)TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
      return;

   static int  maCross  =  0;
   static int  cciCross =  0;
   static int  ticket = 0;
   string comment;
   static bool NewBar = true;
   setTrailingStop(Magic);


   bool  newBar   =  NewBar();
   if(newBar)
     {
      double   cci1     =  iCCI(Symbol(), Period(), CCIPeriod, CCIPrice, 1);
      double   cci2     =  iCCI(Symbol(), Period(), CCIPeriod, CCIPrice, 2);

      if(cci1<100 && cci2>=100)
         cciCross =  1;
      if(cci1>-100 && cci2<=-100)
         cciCross =  -1;

      double   fastMa1  =  iMA(Symbol(),0, MA_Period, MA_Shift, MA_Method, MA_Price, 1);
      double   fastMa2  =  iMA(Symbol(),0, MA_Period, MA_Shift, MA_Method, MA_Price, 2);
      double   slowMa1  =  iMA(Symbol(),0, SlowMAPeriods, MA_Shift, SlowMAMethod, SlowMAPrice, 1);
      double   slowMa2  =  iMA(Symbol(),0, SlowMAPeriods, MA_Shift, SlowMAMethod, SlowMAPrice, 2);

      
   if(Hour() == StartHour)
     {
      comment = GetDateAndTime();
      if(NewBar == true)
        {
         NewBar = false;
         if(iVolume(NULL,0,0)>1)


            //FindTicket makes sure that the EA will pick up its orders
            //even if it is relaunched
            ticket = FindTicket(Magic);

         bool res;
         res = OrderSelect(ticket, SELECT_BY_POS,MODE_TRADES);
         if(res == true)
           {
            if(OrderCloseTime() == 0)

              {
               bool res2;
               res2 = OrderClose(ticket, Lots, OrderClosePrice(), 10);

               if(res2 == false)
                 {
                  Alert("Error Closing Order #", ticket);
                 }
              }
           }

      if(fastMa1>slowMa1 && fastMa2<=slowMa2)
        {
         maCross  =  -1;
         ticket = (OP_SELL);
        }

      if(fastMa1<slowMa1 && fastMa2>=slowMa2)
        {
         maCross  =  1;
         ticket = (OP_BUY);
        }
      if(maCross!=0 && maCross==cciCross)
        {
         if(OpenTrade(maCross)>0)
           {
            maCross  =  0;
            cciCross =  0;
           }
        }
     }
  }

//+------------------------------------------------------------------+
//|                     Auxiliary Functions                          |
//+------------------------------------------------------------------+
int FindTicket(int M)
  {
   int ret = 0;
   int total = OrdersTotal();
   for(int i = 0 ; i < total ; i++)
     {
      bool res;
      res = OrderSelect(i, SELECT_BY_POS,MODE_TRADES);
      if(res == true)
        {
         if(OrderMagicNumber() == M)
           {
            ret = OrderTicket();
            break;
           }
        }
     }

   return(ret);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int   OpenTrade(int maCross)
  {
           if(Open[0] < Open[StartHour] - MinPipLimit*MyPoint) //v3.0
         {
            //check ma
            if(Close[1] > maCross
            {
               //here we are assuming that the TakeProfit and StopLoss are entered in Pips
               ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, vSlippage, Bid-StopLoss*vPoint, Bid+TakeProfit*vPoint, "Set by Process Expert Advisor", Magic,0,Blue);
               if(ticket < 0)
                              {
                  comment = comment + " " + "Error Sending BUY Order";
               }
               else
               {
                  comment = comment + " " + "BUY Order Executed Succesfuly";
               }               
            }
            else
            {
                  comment = comment + " " + "Reason Order Not Opened: MinPipLimit Filter Not Passed";
            }
         }
         else if(Open[0] > Open[StartHour] + MinPipLimit*MyPoint) //v3.0
         {
            //check ma
            if(Close[1] < maCross
            {
                  ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, vSlippage, Ask+StopLoss*vPoint, Ask-TakeProfit*vPoint, "Set by Process Expert Advisor", Magic,0,Blue);
                  if(ticket < 0)
                              {
                  comment = comment + " " + "Error Sending SELL Order";
               }
               else
               {
                  comment = comment + " " + "SELL Order Executed Succesfuly";
               }                  
            }
         }
         else
         {
            comment = comment + " " + "Reason Order Not Opened: MinPipLimit Filter Not Passed";
         }
         
         Comment(comment);
         Print(comment);
      }

   }
   else
   {
      NewBar = true;
}
bool  NewBar()
  {
   static datetime   current  =  0;
   datetime          now      =  iTime(Symbol(), Period(), 0);
   if(now == current)
      return(false);
   current  =  now;
   return(true);
  }
Implement a time based EA (Limit trading sessions to specific Hours)
Implement a time based EA (Limit trading sessions to specific Hours)
  • 2022.05.22
  • www.mql5.com
Hello MQL5 Community, I am currently developing an EA based on two MAs and CCI Cross conditions...
R4tna C
143
R4tna C  
OTMT Howard #:

Hei R4tna C #:

My idea is to restrict trading actions to specific hours, while also checking the MinPiPLimit before executing a trade.

I've updated my code to reflect the changes I intend to make as part of my strategy.

i hope my explanation is clear for your support.

The additions are found at these points: " if(Hour() == StartHour) " and "int   OpenTrade(int maCross)", where my entry conditions are located. 

replaced values are:

 if( maCross>0 ) {

 return (OrderSend(Symbol(), OP_BUY, Lots, Ask, vSlippage, Bid-StopLoss*vPoint, Bid+TakeProfit*vPoint, "Set by Process Expert Advisor", Magic,0,Blue)); }

   if ( maCross<0 ) {

 return (OrderSend(Symbol(), OP_SELL, Lots, Bid, vSlippage, Ask+StopLoss*vPoint, Ask-TakeProfit*vPoint, "Set by Process Expert Advisor", Magic,0,Blue));}

   return(0);}

I however get the following errors with this addition as shown below:

The third is found at the On Init function:

myPoint     = GetPipPoint(Symbol());

And the parantheses at the start of "OnTick()" and at the end of my code.

Sorry there is a lot of info here and I am not able to invest so much time to review and debug this.

I was hoping my hints helped - I suggest writing a simple script to master the time handling and then you can use it in your main code

R4tna C
143
R4tna C  
R4tna C #:

Sorry there is a lot of info here and I am not able to invest so much time to review and debug this.

I was hoping my hints helped - I suggest writing a simple script to master the time handling and then you can use it in your main code

Also, my guess is you have a missing or extra bracket somewhere - if you have not done so already, switch on "highlight bracket matching" in Tools>Options and see if that helps.

Good luck!

OTMT Howard
73
OTMT Howard  
R4tna C #:

Also, my guess is you have a missing or extra bracket somewhere - if you have not done so already, switch on "highlight bracket matching" in Tools>Options and see if that helps.

Good luck!

I appreciate your time invested so far with my inquiry.


Regards,