Looking for general suggestions to speed up the code

 

Hi, I just started learning MQL5 language, after studying some of the samples in the Codebase, I decided to write a Turtle trading strategy to practice the newly learnt knowledges. I successfully completed the EA and confirmed the results through backtesting, however I found the process of backtesting took long, as the code is nowhere near polished for smooth and fast execution.

Would anyone like to give some general suggestions on how to speed up the code? Thank you very much.

The code logic is to:

  1. Entry at 20 days High/Low with a Buy/Sell order, with 2 ATR stoploss. This position size is adjusted so it will cost 2% of overall loss in the account.
  2. When a first position is opened, as market continue extend for every 0.5 ATR, I add another position size equal to the original one, then move stoploss for all positions to 2 ATR away from the latest opened position. This process will repeat maximum 3 times (open additional 3 positions in total, on top of the original position).
  3. If the 10 days Low/High is higher than the Buy/Sell stoplosses, move the stoploss to the 10 days Low/High, until all positions stop out.


//+------------------------------------------------------------------+
//|                                                    turtel_v1.mq5 |
//|                                             Copyright 2020       |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020"
#property link      ""
#property version   "1.00"
//--- input parameters
#include <Math\Stat\Math.mqh>
input int      ATR_period=20;  // The ATR day value, must be less than or equal to breakoutday
input double   RiskPrecentage=0.02;     // The maximum risk per trade
input int   Breakoutday=20;// Break out day candle sticks
input int   takeprofitday=10; //Take profit drawback day candle sticks
input int EA_Magic=12345;   // EA Magic number
int ATRhandle;  // ATR handle
double ATRvalue[];  //ATR indicator value
double currentprice;    //Current price
double memory[4];   // Store the existing order entry price
int counting;   
int startaddition;
double initialSL;
double lastSL;
double currentSL;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   ATRhandle=iATR(_Symbol, PERIOD_D1, ATR_period);
   if(ATRhandle<0)
     {
      Alert("Error creating ATR handle - error: ", GetLastError());
      return(-1);
     }
   if(ATR_period>Breakoutday)
     {
      Alert("ATR period bigger than breakoutday, EA will now exit!");
      return(-1);
     }
   if(Breakoutday<=takeprofitday)
     {
      Alert("Error initializing EA, BreakoutDay must be bigger than takeprofitday!");
      return(-1);
     }
//---
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   IndicatorRelease(ATRhandle);
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(Bars(_Symbol, PERIOD_D1)<50)
     {
      Alert("We have less than 50 day bars, EA will now exit!");
      return;
     }
   static datetime oldtime;
   datetime newtime[1];
   bool isNewBar=false;
   int copied=CopyTime(_Symbol, PERIOD_D1, 0, 1, newtime);
   if(copied >0)
     {
      if(oldtime!=newtime[0])
        {
         isNewBar=true;
         oldtime=newtime[0];
        }
     }
   else
     {
      Alert("Error copying historical times data - error: ", GetLastError());
      return;
     }
   if(isNewBar=false)
     {
      return;
     }
   MqlTick latestprice;
   MqlTradeRequest mrequest;
   MqlTradeResult mresult;
   MqlRates mrates[];
   ZeroMemory(mrequest);
   ArraySetAsSeries(mrates, true);
   ArraySetAsSeries(ATRvalue, true);
   if(!SymbolInfoTick(_Symbol, latestprice))
     {
      Alert("There is an error getting the latest price quote - error: ", GetLastError());
      return;
     }
   if(CopyRates(_Symbol, PERIOD_D1, 0, Breakoutday, mrates)<0)
     {
      Alert("Error copying latest ", Breakoutday, " days of bars, error - ", GetLastError());
      return;
     }
   if(CopyBuffer(ATRhandle, 0, 0, ATR_period, ATRvalue)<0)
     {
      Alert("Error copying ATR indicator buffer - error: ", GetLastError());
      return;
     }
   double breakoutHigh=iHigh(_Symbol, PERIOD_D1, iHighest(_Symbol, PERIOD_D1, MODE_HIGH, Breakoutday, 1));
   double breakoutLow=iLow(_Symbol, PERIOD_D1, iLowest(_Symbol, PERIOD_D1, MODE_LOW, Breakoutday, 1));
   double takeprofitHigh=iHigh(_Symbol, PERIOD_D1, iHighest(_Symbol, PERIOD_D1, MODE_HIGH, takeprofitday, 1));
   double takeprofitLow=iLow(_Symbol, PERIOD_D1, iLowest(_Symbol, PERIOD_D1, MODE_LOW, takeprofitday, 1));
   bool breakout_condition_buy1=(latestprice.ask>breakoutHigh);
   bool breakout_condition_sell1=(latestprice.bid<breakoutLow);
   bool takeprofit_condition_buy1=(latestprice.bid<takeprofitLow);
   bool takeprofit_condition_sell1=(latestprice.ask>takeprofitHigh);
   bool isSellOpened=false;
   bool isBuyOpened=false;
   if(PositionSelect(_Symbol)==true)
     {
      if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
        {
         isBuyOpened=true;
        }
      else
         if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
           {
            isSellOpened=true;
           }
         else
           {
           lastSL=0;
           }
     }
   double riskPerTrade=AccountInfoDouble(ACCOUNT_EQUITY)*RiskPrecentage;
   double lot=riskPerTrade/((ATRvalue[1]/latestprice.ask)*100000*2);
   lot=MathRound(lot, 2);
   if(breakout_condition_buy1)
     {
      if(PositionSelect(_Symbol)==false)
        {
         counting=0;
         ZeroMemory(mrequest);
         ZeroMemory(mresult);
         mrequest.action=TRADE_ACTION_DEAL;
         mrequest.price=NormalizeDouble(latestprice.ask, _Digits);
         mrequest.sl=NormalizeDouble((latestprice.ask-(2*ATRvalue[1])), _Digits);
         mrequest.symbol=_Symbol;
         mrequest.volume=lot;
         mrequest.magic=EA_Magic;
         mrequest.type=ORDER_TYPE_BUY;
         mrequest.type_filling=ORDER_FILLING_IOC;
         mrequest.deviation=200;
         if(!OrderSend(mrequest, mresult))
           {
            Alert("Cannot open a buy position - error: ", GetLastError());
            return;
           }
         Alert("Buy position opened");
         memory[counting]=latestprice.ask;
         initialSL=mrequest.sl;
         currentSL=mrequest.sl;
         counting=1;
         startaddition=1;
        }
     }
   if(breakout_condition_sell1)
     {
      if(PositionSelect(_Symbol)==false)
        {
         ZeroMemory(mrequest);
         ZeroMemory(mresult);
         counting=0;
         mrequest.action=TRADE_ACTION_DEAL;
         mrequest.price=NormalizeDouble(latestprice.bid, _Digits);
         mrequest.sl=NormalizeDouble((latestprice.bid+(2*ATRvalue[1])), _Digits);
         mrequest.symbol=_Symbol;
         mrequest.volume=lot;
         mrequest.magic=EA_Magic;
         mrequest.type=ORDER_TYPE_SELL;
         mrequest.type_filling=ORDER_FILLING_IOC;
         mrequest.deviation=200;
         if(!OrderSend(mrequest, mresult))
           {
            Alert("Cannot open a sell position - error: ", GetLastError());
            return;
           }
         Alert("sell position opened");
         memory[counting]=latestprice.bid;
         initialSL=mrequest.sl;
         currentSL=mrequest.sl;
         counting=1;
         startaddition=1;
        }
     }
   if(counting>0 && counting<4)
     {
      if(isBuyOpened)
        {
         if(latestprice.ask>(memory[counting-1]+(ATRvalue[1]/2)))
           {
            ZeroMemory(mrequest);
            ZeroMemory(mresult);
            mrequest.action=TRADE_ACTION_DEAL;
            mrequest.price=NormalizeDouble(latestprice.ask, _Digits);
            mrequest.symbol=_Symbol;
            mrequest.volume=lot;
            mrequest.magic=EA_Magic;
            mrequest.type=ORDER_TYPE_BUY;
            mrequest.type_filling=ORDER_FILLING_IOC;
            mrequest.deviation=200;
            if(!OrderSend(mrequest, mresult))
              {
               Alert("Cannot open a buy position - error: ", GetLastError());
               return;
              }
            Alert("Additional Buy 1 position opened");
            initialSL=initialSL+(0.5*ATRvalue[1]);
            memory[counting]=latestprice.ask;
            counting=counting+1;
           }
        }
      if(isSellOpened)
        {
         if(latestprice.bid<(memory[counting-1]-(ATRvalue[1]/2)))
           {
            ZeroMemory(mrequest);
            ZeroMemory(mresult);
            mrequest.action=TRADE_ACTION_DEAL;
            mrequest.price=NormalizeDouble(latestprice.bid, _Digits);
            mrequest.symbol=_Symbol;
            mrequest.volume=lot;
            mrequest.magic=EA_Magic;
            mrequest.type=ORDER_TYPE_SELL;
            mrequest.type_filling=ORDER_FILLING_IOC;
            mrequest.deviation=200;
            if(!OrderSend(mrequest, mresult))
              {
               Alert("Cannot open a sell position - error: ", GetLastError());
               return;
              }
            Alert("Additional sell 1 position opened");
            initialSL=initialSL-(0.5*ATRvalue[1]);
            memory[counting]=mresult.bid;
            counting=counting+1;
           }
        }
     }
   if(counting>1 && counting<5 && currentSL!=initialSL)
     {
     int total=PositionsTotal();
      for(int i=0; i<total; i++)
        {
         ZeroMemory(mrequest);
         ZeroMemory(mresult);
         ulong positionticket=PositionGetTicket(i);
         mrequest.action=TRADE_ACTION_SLTP;
         mrequest.position=positionticket;
         mrequest.symbol=_Symbol;
         if(isBuyOpened)
           {
            mrequest.sl=NormalizeDouble(MathRound(initialSL, _Digits), _Digits);
           }
         if(isSellOpened)
           {
            mrequest.sl=NormalizeDouble(MathRound(initialSL, _Digits), _Digits);
           }
         mrequest.magic=EA_Magic;
         if(!OrderSend(mrequest, mresult))
           {
            Alert("Cannot modify Stop loss - error: ", GetLastError());
            return;
           }
         Alert("Stop loss is modified");
         currentSL=initialSL;
         if(counting==4)
           {
            counting=5;
            lastSL=mrequest.sl;
           }
        }
     }
   if(counting==5)
     {
     int total=PositionsTotal();
      if(lastSL<takeprofitLow && isBuyOpened)
        {
         for(int i=0; i<total; i++)
           {
            ZeroMemory(mrequest);
            ZeroMemory(mresult);
            ulong positionticket=PositionGetTicket(i);
            mrequest.action=TRADE_ACTION_SLTP;
            mrequest.position=positionticket;
            mrequest.symbol=_Symbol;
            mrequest.sl=NormalizeDouble(takeprofitLow, _Digits);
            mrequest.magic=EA_Magic;
            if(!OrderSend(mrequest, mresult))
              {
               Alert("Cannot modify Stop loss - error: ", GetLastError());
               return;
              }
            Alert("Stop loss is modified");
            lastSL=takeprofitLow;
           }
        }
      if(lastSL>takeprofitHigh && isSellOpened)
        {
         for(int i=0; i<total; i++)
           {
            ZeroMemory(mrequest);
            ZeroMemory(mresult);
            ulong positionticket=PositionGetTicket(i);
            mrequest.action=TRADE_ACTION_SLTP;
            mrequest.position=positionticket;
            mrequest.symbol=_Symbol;
            mrequest.sl=NormalizeDouble(takeprofitHigh, _Digits);
            mrequest.magic=EA_Magic;
            if(!OrderSend(mrequest, mresult))
              {
               Alert("Cannot modify Stop loss - error: ", GetLastError());
               return;
              }
           Alert("Stop loss is modified");
           lastSL=takeprofitHigh;
           }
        }
     }
  }
//---
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
Testing trading strategies on real ticks
Testing trading strategies on real ticks
  • www.mql5.com
The article provides the results of testing a simple trading strategy in three modes: "1 minute OHLC", "Every tick" and "Every tick based on real ticks" using actual historical data.
 
Hi I have managed to solve the problem by combining some codes into void xxx() functions. Also I create my own data structure to contain the messy loop counting parameters, the code is now running smoothly/
Reason: