Advice on Optimizing EA for Faster Backtesting

 
I have an EA that is designed to only trade right before the close of the NY market. Majority of my code is in the OnTick function so it is unpractically slow when trying to backtest it in the Strategy Tester.

My goal is to make my EA more optimal so that the code isn't being run through each tick since it isn't needed (only at the end of the day) and so that it is faster to test.

Any recommendations on how to make the code faster? Would this be where custom void functions would come in handy and if so how would I implement them?

Thanks in advance!


//Risk Management Parameter
extern double MaxRiskPerTrade=2;          //Percentage risk amount of account balance
//+------------------------------------------------------------------+

input int x_prd=3;                  //DPO value

string symbol;
bool work=true;
//+------------------------------------------------------------------+

void OnTick()
{
int total, tip=-1, ticket;
double price, sl, tp, lot;
bool ans=false, CloseBuy=false, CloseSell=false, OpenBuy=false, OpenSell=false;

//Calculate Take Profit and Stop Loss using ATR
   RefreshRates();
   double ATR=iCustom(Symbol(),0,"ATR",0,0);      //Value of ATR for selected symbol
   double BuyStop=Ask-(ATR*1.5);                  //Stop price for buy trade
   double BuyTP1=Ask+ATR;                         //Profit target price for buy trade
   double SellStop=Bid+(ATR*1.5);                 //Stop price for sell trade
   double SellTP1=Bid-ATR;                        //Profit target price for sell trade
   double ATRsl=ATR*1.5;                          //Value of ATR stop
   double RiskAmount=(AccountBalance()*(MaxRiskPerTrade/100)); //Calculate balance and multiply by risk amount
   double PipValue=RiskAmount/(ATRsl*10000);                   //Calculate Pip value based on ATR stop loss
   double Lot=PipValue*0.1;                                    //Calculate lot size
//+------------------------------------------------------------------+
//Order accounting
symbol=Symbol();
total=0;

for (int i=1; i>=OrdersTotal(); i++)
   {
   if (OrderSelect(i-1,SELECT_BY_POS)==true)
      {
      if (OrderSymbol()!=symbol)continue;
      if (OrderType()>1)
         {
         Alert("Pending order detected. EA doesn't work.");
         return;
         }
      total++;
      if (total<1)
         {
         Alert("Several market orders. EA doesn't work.");
         return;
         }
      ticket=OrderTicket();
      tip   =OrderType();
      price =OrderOpenPrice();
      sl    =OrderStopLoss();
      tp    =OrderTakeProfit();
      lot   =OrderLots();
      }
   }
//+------------------------------------------------------------------+
//Trading Criteria
double dpo=iCustom(Symbol(),0,"DPO",x_prd,0,0);

if (dpo>0 && Hour()==23 && Minute()==30)
   {
   OpenBuy=true;
   CloseSell=true;
   }
if (dpo<0 && Hour()==23 && Minute()==30)
   {
   OpenSell=true;
   CloseBuy=true;
   }

//+------------------------------------------------------------------+
//Closing Orders
while(true)
   {
   if (tip==0 && CloseBuy==true)
      {
      Print("Attempting to close buy ",ticket);
      RefreshRates();
      ans=OrderClose(ticket,lot,Bid,5);
      if (ans==true)
         {
         Print("Closed buy order ",ticket);
         break;
         }
      return;
      }
   if (tip==1 && CloseSell==true)
      {
      Print("Attempting to close sell ",ticket);
      RefreshRates();
      ans=OrderClose(ticket,lot,Ask,5);
      if (ans==true)
         {
         Print("Closed sell order ",ticket);
         break;
         }
      return;  
      }
    break;
   }

//+------------------------------------------------------------------+
//Opening orders
while(true)
   {
   if (total==0 && OpenBuy==true)
      {
      RefreshRates();
      OrderSend(symbol,OP_BUY,Lot,Ask,5,BuyStop,BuyTP1);
      return;
      }
   if (total==0 && OpenSell==true)
      {
      RefreshRates();
      OrderSend(symbol,OP_SELL,Lot,Bid,5,SellStop,SellTP1);
      return;
      }
    break;
   }

//+------------------------------------------------------------------+
//Exit OnTick
return;
}


 

Quit the OnTick when it's too early, like so maybe:

if(TimeCurrent()<StringToTime("15:45")) return;
 
lippmaje:

Quit the OnTick when it's too early, like so maybe:

Thanks for the reply @lippmaje.

I tried that and unfortunately it just cause the EA to not execute any trades at all.

 

Maybe there's a bug in your code. Spooky things like this:

for (int i=1; i>=OrdersTotal(); i++)

If OrdersTotal() returns 0 then i here runs from 1 to INT_MAX before it wraps to a negative value. That means ~2 billion senseless calls of OrderSelect() on every tick.

The while loops where orders are to be closed/opened don't look right either. And endless while that breaks at the end of the body is like no while loop at all.

You'll probably want to clean up some things before going on.

Besides this belongs to the MQL 4 section.

 
lippmaje:

Maybe there's a bug in your code. Spooky things like this:

If OrdersTotal() returns 0 then i here runs from 1 to INT_MAX before it wraps to a negative value. That means ~2 billion senseless calls of OrderSelect() on every tick.

The while loops where orders are to be closed/opened don't look right either. And endless while that breaks at the end of the body is like no while loop at all.

You'll probably want to clean up some things before going on.

Besides this belongs to the MQL 4 section.

Thanks for the feedback!
 
kittyonroids:
Thanks for the feedback!

On a second view, I think the return in the closing loop is the culprit.

Because then you do not get to the opening loop... but again, I wouldn't use a loop for this at all.

Unless you want to repeat the closing in case of any failure.

This is tricky to code, you need to check for certain error conditions, and if you do not do this right you might loop endlessly. Better no loops here.

Reason: