EA Backtesting - How To

 

Hello @ all,

 I need some help with the backtesting of my EA.

Here is the overall structure of the EA:

 

extern int ticket_b1;
extern int ticket_b2;
extern int deleted = 0;
extern int deleted_tmp;
extern int order_type;

int init()
{   
   return(0);
}

int deinit()
{
   return(0);
}

int start()
{

   // At this point I open two Orders - one Short and one Long (ticket_b1 and ticket_b2)
   
   // In this while-loop I am waiting until one of those two was triggered to delete the opposite one - as my broker doesn't provide OCO-Orders
   while(deleted == 0)
   {
      //Ticket_1 closes ticket 2, BUY_LIMIT = 2, SELL_LIMIT =3, BUY=0, SELL=1

      if (OrderSelect (ticket_b1,SELECT_BY_TICKET)==True)
      {
         order_type = OrderType();
         Print ("---------- Ticket1 (Order_Type): ", order_type);
   
         if (order_type == OP_SELL || order_type == OP_BUY)
         {
            Print("---------- Deleting Ticket_b1 "+"("+ticket_b2+")");
            OrderDelete (ticket_b2);
            ObjectCreate("Deleted",OBJ_LABEL,0,0,0,0,0);
            ObjectSet ("Deleted",OBJPROP_XDISTANCE,20);
            ObjectSet ("Deleted", OBJPROP_YDISTANCE,80);
            ObjectSetText("Deleted","Pending Deleted",10,"Tahoma", Black);
            deleted = 1;
            Print("---------- deleted: "+deleted);
            deleted_tmp = 2;
            Print("---------- deleted_tmp: "+deleted_tmp);
         }
      }
   
      //Ticket_2 closes ticket 1
      if (OrderSelect (ticket_b2,SELECT_BY_TICKET)==True)
      {
         order_type = OrderType();
         Print ("---------- Ticket2 (Order_Type): ", order_type);
   
         if (order_type == OP_SELL || order_type == OP_BUY)
         {
            Print("---------- Deleting Ticket_b1 "+"("+ticket_b1+")");
            OrderDelete (ticket_b1);
            ObjectCreate("Deleted",OBJ_LABEL,0,0,0,0,0);
            ObjectSet ("Deleted",OBJPROP_XDISTANCE,20);
            ObjectSet ("Deleted", OBJPROP_YDISTANCE,80);
            ObjectSetText("Deleted","Pending Deleted",10,"Tahoma", Black);
            deleted = 1;
            Print("---------- deleted: "+deleted);
            deleted_tmp = 4;
            Print("---------- deleted_tmp: "+deleted_tmp);
         }
      }
      Sleep(30000);
      Print("---------- Sleep(30000) is over");
   }// while-end
   
   // with the following two IF's I am waiting until the triggered order has been closed (by hitting TP or SL)
   if(deleted_tmp == 2)
   {
      while(deleted == 1)
      {
         if (OrderSelect (ticket_b1,SELECT_BY_TICKET)==True)
         {
            order_type = OrderType();
            Print("---------- Order_Type @ deleted_tmp = 2 --- "+order_type);
            if (order_type != OP_SELL || order_type != OP_BUY)
            {
               // if the order has been closed I set this two variables to enter the IF at the end
               deleted = 0; deleted_tmp = 0;
            }
            Sleep(120000);
            Print("---------- Sleep(120000) is over");
         }
      }
   }
   if(deleted_tmp == 4)
   {
      while(deleted == 1)
      {
         if (OrderSelect (ticket_b2,SELECT_BY_TICKET)==True)
         {
            order_type = OrderType();
            Print("---------- Order_Type @ deleted_tmp = 4 --- "+order_type);
            if (order_type != OP_SELL || order_type != OP_BUY)
            {
               // if the order has been closed I set this two variables to enter the IF at the end
               deleted = 0; deleted_tmp = 0;
            }
            Sleep(120000);
            Print("---------- Sleep(120000) is over");
         }
      }
   }
   
   // after the triggered order has been closed - there are no open orders so, I am waiting for a certain time to set the new orders
   if(deleted == 0 && deleted_tmp == 0)
   {
      while(Hour() < 19)
      {
         Sleep(900000);
         Print("---------- Sleep(900000) is over");
         Print("---------- Hour(): "+Hour());
      }
   }
   
   // when the certain time has come - the EA returns 0 and starts the function start() again ?
   return(0);
}

So when I start the backtest with this code it seems to loop forever in the first while: while(deleted == 0)

 I chose the Model: Every tick and Use date for a certain interval, Optimization was not checked - then I started the test, and in the Journal it only printed the whole time "Sleep(30000)" so that is why I guess that it can't finish the first loop - but the code that is in the first loop (the OCO-Code) is used in another EA where it works - so is it maybe that the Strategy Tester works different then the usual trading way?

 Thank you all in advance!

Kind regards,

John 

 
Johnny_:

Hello @ all,

So when I start the backtest with this code it seems to loop forever in the first while: while(deleted == 0)


First run through the EA what is the value of ticket_b1 & ticket_b2 ?  probably 0 so the OrderSelect() fails . . .  add some print statements and find out . . .
 
       if (order_type == OP_SELL || order_type == OP_BUY)
         {
            Print("---------- Deleting Ticket_b1 "+"("+ticket_b1+")");
            OrderDelete (ticket_b1);
  1. You can NOT delete open orders only pending orders. You can only close open orders not pending or previously closed.
  2. What are Function return values ? How do I use them ? - MQL4 forum
  3. You can NOT loop in the tester. You will get no more ticks until you return from start.
  4.  while(deleted == 0)
       {
          if (OrderSelect (ticket_b1,SELECT_BY_TICKET)==True)
    The first time you load the EA, deleted will default to zero, so will ticket_b1. So the OrderSelect always fails you have an infinite loop
 
RaptorUK:
First run through the EA what is the value of ticket_b1 & ticket_b2 ?  probably 0 so the OrderSelect() fails . . .  add some print statements and find out . . .


WHRoeder:
  1. You can NOT delete open orders only pending orders. You can only close open orders not pending or previously closed.
  2. What are Function return values ? How do I use them ? - MQL4 forum
  3. You can NOT loop in the tester. You will get no more ticks until you return from start.
  4. The first time you load the EA, deleted will default to zero, so will ticket_b1. So the OrderSelect always fails you have an infinite loop

ticket_b1 and ticket_b2 get the returnvalue of OrderSend() at the beginning - but it seems that these two orders are not placed at the beginnen ??

 
There is NO orderSend in the code you posted.
 
WHRoeder:
There is NO orderSend in the code you posted.


I just wrote a comment at the point in the code where i open the orders, they look like this:

   ticket_1 = OrderSend(Symbol(), OP_BUYSTOP, 0.01, myLong, NULL, myLongSL, myLongTP, NULL, NULL, NULL, Green);
   ticket_2 = OrderSend(Symbol(), OP_SELLSTOP, 0.01, myShort, NULL, myShortSL, myShortTP, NULL, NULL, NULL, Green);

 The code above where i Delete an order, this is the opposite order that is deleted because the other one was triggered.

 
RaptorUK:
First run through the EA what is the value of ticket_b1 & ticket_b2 ?  probably 0 so the OrderSelect() fails . . .  add some print statements and find out . . .

Did you add the Print statement ?
 
RaptorUK:
Did you add the Print statement ?


Yes, I added some print statements and recognized that the ticketnumber of the pending orders (ticket_1 and ticket_2) changes when the order was triggered, so I am working with the wrong ticketnumber.

But how do I get the new ticketnumber of the triggered order?  (It looks like the pending order becomes a completely new order with a new ticketnumber?!)

 
Johnny_:


Yes, I added some print statements and recognized that the ticketnumber of the pending orders (ticket_1 and ticket_2) changes when the order was triggered, so I am working with the wrong ticketnumber.

But how do I get the new ticketnumber of the triggered order?  (It looks like the pending order becomes a completely new order with a new ticketnumber?!)

This is not my understanding of how pending orders work . . .  can you provide the complete code or a sub-version that demonstrates the problem so I can test and investigate ?  I would like to know if you are correct and understand for myself what is going on.
 
RaptorUK:
This is not my understanding of how pending orders work . . .  can you provide the complete code or a sub-version that demonstrates the problem so I can test and investigate ?  I would like to know if you are correct and understand for myself what is going on.


Hi Raptor,

thank you for your help!!

Here is the complete code of my EA - I just change the Price, SL and TP (all variables that start with my*) and then start it:

(This code works on IBFX but on OANDA and AlpariUK it doesn't - I only checked the Ticketnumber on OANDA and saw there that it changes when one of these two orders was triggered.) 

#property copyright "free to share"
#property link      ""
#include <WinUser32.mqh>
extern int ticket_1;
extern int ticket_2;
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
      
   return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {

   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   ticket_1 = OrderSend(Symbol(), OP_BUYSTOP, 0.01, myLong, NULL, myLongSL, myLongTP, NULL, 11111, NULL, Green);
   if(ticket_1 < 0)
   {
      Print("OrderSend failed with error #",GetLastError());
   }
   
   ticket_2 = OrderSend(Symbol(), OP_SELLSTOP, 0.01, myShort, NULL, myShortSL, myShortTP, NULL, 22222, NULL, Green);
   if(ticket_2 < 0)
   {
      Print("OrderSend failed with error #",GetLastError());
   }
   
   Print("++++++++++++++++++++++++ ", ticket_1);
   Print("++++++++++++++++++++++++ ", ticket_2);
   
   int order_type;
   int deleted = 0;
   
   while(deleted == 0)
   {
      if (OrderSelect (ticket_1,SELECT_BY_TICKET)==True)
      {
         order_type = OrderType();
         Print ("-------------------------Ticket1: "+ticket_1 + " OrderType: "+order_type);
         Print ("MAGICNUMBER: "+OrderMagicNumber());
   
         if (order_type == OP_SELL || order_type == OP_BUY)
         {
            OrderDelete (ticket_2);
            ObjectCreate("Deleted",OBJ_LABEL,0,0,0,0,0);
            ObjectSet ("Deleted",OBJPROP_XDISTANCE,20);
            ObjectSet ("Deleted", OBJPROP_YDISTANCE,80);
            ObjectSetText("Deleted","Pending Deleted",10,"Tahoma", Black);
            deleted = 1;
         }
      }
      if (OrderSelect (ticket_2,SELECT_BY_TICKET)==True)
      {
         order_type = OrderType();
         Print ("-------------------------Ticket2: "+ticket_2 + " OrderType: "+order_type);
         Print ("MAGICNUMBER: "+OrderMagicNumber());
   
         if (order_type == OP_SELL || order_type == OP_BUY)
         {
            OrderDelete (ticket_1);
            ObjectCreate("Deleted",OBJ_LABEL,0,0,0,0,0);
            ObjectSet ("Deleted",OBJPROP_XDISTANCE,20);
            ObjectSet ("Deleted", OBJPROP_YDISTANCE,80);
            ObjectSetText("Deleted","Pending Deleted",10,"Tahoma", Black);
            deleted = 1;
         }
      }
      Sleep(30000);
      Print("Sleep(30000) IS OVER");
   }
   
   PostMessageA( WindowHandle( Symbol(), Period()), WM_COMMAND, 33050, 0); // remove EA
   return(0);
  }
//+------------------------------------------------------------------+

 Kind regards

 
Johnny_:


Hi Raptor,

thank you for your help!!

Here is the complete code of my EA - I just change the Price, SL and TP (all variables that start with my*) and then start it:

(This code works on IBFX but on OANDA and AlpariUK it doesn't - I only checked the Ticketnumber on OANDA and saw there that it changes when one of these two orders was triggered.) 

 Kind regards

Your code does not compile.  If I have to change the code to reproduce the error then that defeats the the idea or reproducing what you are seeing . . . 

OK,  so I guess the important piece of information that you never specifically mentioned,  other than a comment in your code,  is that you open the two Orders manually ?