Backtest too slow

 
Hi, I'm opening this thread here to discuss possible things that can slow down the backtest. I created an EA and its backtest is very slow and I don't know why. I would like to know what the possible causes of this slowness are.
 
Attach your MQL5 code. Show the settings of the MQL5 Strategy Tester.
 
maybe you modify orders by tick
 
Vladimir Karputov:
Conecte seu código MQL5. Mostre as configurações do Testadorde Estratégia MQL5 .

I did a test here by adding a reading after a new candle, but it hurts my operational. My setup needs to be updated at least every 1 minute and even I put the function for each new 1 minute candle the backtest is slow.

void OnTick()

{

   CopyRates(_Symbol,_Period,0,5,velas);}
   
    ArraySetAsSeries(velas,true);       


      if(GetData())     //Here loads the data of my indicators.

       {

          if(CheckPositionsAndOrders()) // check for open position

           {

            if( !TradeLogic() ) //Here is the function of my operational logic, that is, my setup

             {

              Print("Lógica operacional não realizada com sucesso!");

             }

           }

         }

}


GET DATA FUNCTION

bool GetData()
  {
   int barsToCopy = 5;
   int barsToCopy2 = 5; 
   
   int copied1 = CopyBuffer(ma1_handler,0,0,barsToCopy,ma1_buffer);
   int copied2 = CopyBuffer(ma2_handler,0,0,barsToCopy,ma2_buffer);
   
   int copied3 = CopyBuffer(ifr_handler,0,0,barsToCopy,ifr_buffer);
   int copied4 = (CalcMode==MODE_ATR) ? CopyBuffer(atr_handler,0,0,barsToCopy,atr_buffer) : barsToCopy;
   
   int copied5 = CopyBuffer(bb_handler,1,0,barsToCopy,bb_Cima);
   int copied6 = CopyBuffer(bb_handler,0,0,barsToCopy,bb_meio);
   int copied7 = CopyBuffer(bb_handler,2,0,barsToCopy,bb_baixo);
   
   int copied8 = CopyBuffer(hilo_handler,0,0,barsToCopy,hilo_buffer);
   
   int copied10 = CopyBuffer(SilverTrend_handler,0,0,barsToCopy2,SilverTrend_sell_buffer);
   int copied11 = CopyBuffer(SilverTrend_handler,1,0,barsToCopy2,SilverTrend_buy_buffer);
   
   int copied12 = CopyBuffer(SuperTrend_handler,0,0,barsToCopy2,SuperTrend_UP_buffer);
   int copied13 = CopyBuffer(SuperTrend_handler,1,0,barsToCopy2,SuperTrend_DOWN_buffer);
   int copied14 = CopyBuffer(SuperTrend_handler,2,0,barsToCopy2,SuperTrend_BUY_buffer);
   int copied15 = CopyBuffer(SuperTrend_handler,3,0,barsToCopy2,SuperTrend_SELL_buffer);
   
   int copied16 = CopyBuffer(Parabolic_handler,0,0,barsToCopy,Parabolic_Buffer);
   
   int copied17 = CopyBuffer(FiboCandle_handler,0,0,barsToCopy,FiboCandle_Open);
   int copied18 = CopyBuffer(FiboCandle_handler,1,0,barsToCopy,FiboCandle_High);
   int copied19 = CopyBuffer(FiboCandle_handler,2,0,barsToCopy,FiboCandle_Low);
   int copied20 = CopyBuffer(FiboCandle_handler,3,0,barsToCopy,FiboCandle_Close);
   int copied21 = CopyBuffer(FiboCandle_handler,4,0,barsToCopy,FiboCandle_Color);
   
   int copied22 = CopyBuffer(Estocastico_handler, 0, 0, barsToCopy, Estocastico_Buffer);
   int copied23 = CopyBuffer(Estocastico_handler, 1, 0, barsToCopy, EstocasticoSinal_Buffer);
   
 
   
   
   
      
   //
   if(copied1!=barsToCopy   || copied2!=barsToCopy   || copied3!=barsToCopy   || copied4!=barsToCopy   || copied5!=barsToCopy   || 
      copied6!=barsToCopy   || copied7!=barsToCopy   || copied8!=barsToCopy                            || copied10!=barsToCopy2 || 
      copied11!=barsToCopy2 || copied12!=barsToCopy2 || copied13!=barsToCopy2 || copied14!=barsToCopy2 || copied15!=barsToCopy2 ||
      copied16!=barsToCopy  || copied17!=barsToCopy  || copied18!=barsToCopy  || copied19!=barsToCopy  || copied20!=barsToCopy  ||
      copied21!=barsToCopy  || copied22!=barsToCopy  || copied23!=barsToCopy )
     {
      Print("ERRO -> Dados de indicadores não foram copiados corretamente");
      return(false);
     }
   
   //
   if( !SymbolInfoTick(_Symbol,tick) )
     {
      Print("ERRO -> Dados de ticks não foram copiados corretamente");
      return(false);
     }
   
   //
   return(true);
  }


FUNCTION CHECKS POSITION

// 2) CheckPositionsAndOrders() -> função para verificação de ordens e posições
bool CheckPositionsAndOrders()
  {
   // variáveis para controle de posições
   comprado = false;
   vendido  = false;
   ticketComprado = 0;
   ticketVendido = 0;
   
   // variáveis para controle de ordens
   compraPendente = false;
   vendaPendente = false;
   ticketCompraPendente = 0;
   ticketVendaPendente = 0;
   
   //+------------------------------------------------------------------+
   //| LOOP NAS POSIÇÕES                                                |
   //+------------------------------------------------------------------+
   // caso não tenha posição -> compra a mercado
   int positionsTotal = PositionsTotal();
   for(int i=0;i<positionsTotal;i++)
     {
      ulong posTicket = PositionGetTicket(i);
      //
      if(PositionSelectByTicket(posTicket))
        {
         ulong posMagic = PositionGetInteger(POSITION_MAGIC);
         string posSymbol = PositionGetString(POSITION_SYMBOL);
         ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
         
         // já tenho posição com meu magic number
         if(posSymbol==_Symbol && posMagic==MagicNumber)
           {
            if(posType==POSITION_TYPE_BUY)
              {
               comprado = true;
               ticketComprado = posTicket;
              }
            //
            if(posType==POSITION_TYPE_SELL)
              {
               vendido  = true;
               ticketVendido = posTicket;
              }
           }
        }
      else
        {
         Print("ERRO -> Posição não selecionada com sucesso");
         return(false);
        }
     }
   
   //+------------------------------------------------------------------+
   //| LOOP NAS ORDENS                                                  |
   //+------------------------------------------------------------------+
   int ordersTotal = OrdersTotal();
   for(int i=0;i<ordersTotal;i++)
     {
      ulong orderTicket = OrderGetTicket(i);
      
      // caso a ordem tenha sido selecionada com sucesso
      if(OrderSelect(orderTicket))
        {
         ulong orderMagic = OrderGetInteger(ORDER_MAGIC);
         string orderSymbol = OrderGetString(ORDER_SYMBOL);
         ENUM_ORDER_TYPE orderType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
         
         //
         if(orderSymbol==_Symbol && orderMagic==MagicNumber)
           {
            if(orderType==ORDER_TYPE_BUY_LIMIT)
              {
               compraPendente = true;
               ticketCompraPendente = orderTicket;
              }
            if(orderType==ORDER_TYPE_SELL_LIMIT)
              {
               vendaPendente = true;
               ticketVendaPendente = orderTicket;
              }
           }
        }
      else
        {
         Print("ERRO -> Ordem não selecionada com sucesso");
         return(false);
        }
     }
   
   // returna verdadeiro depois de atualizadas as variáveis de controle
   return(true);
  }


TRADE LOGIC FUNCTION

bool TradeLogic()
  {
   
   sinalCompra  = false;
   sinalVenda   = false;
   filtroCompra = false;
   filtroVenda  = false;
   Indicador1_compra   = false;
   Indicador1_venda    = false;
   Indicador2_compra   = false;
   Indicador2_venda    = false;

  
      Painel();
      
        if(Funcao_Janeiro(TimeCurrent())   != Janeiro)
        {
        if(Funcao_Fevereiro(TimeCurrent()) != Fevereiro)
        {
        if(Funcao_Marco(TimeCurrent())     != Marco)
        {
        if(Funcao_Abril(TimeCurrent())     != Abril)
        {
        if(Funcao_Maio(TimeCurrent())      != Maio)
        {
        if(Funcao_Junho(TimeCurrent())     != Junho)
        {
        if(Funcao_Julho(TimeCurrent())     != Julho)
        {
        if(Funcao_Agosto(TimeCurrent())    != Agosto)
        {
        if(Funcao_Setembro(TimeCurrent())  != Setembro)
        {
        if(Funcao_Outubro(TimeCurrent())   != Outubro)
        {
        if(Funcao_Novembro(TimeCurrent())  != Novembro)
        {
        if(Funcao_Dezembro(TimeCurrent())  != Dezembro)
        {
        //-------------------------------------
        if(Funcao_Segunda(TimeCurrent())   != Segunda)
        {
        if(Funcao_Terca(TimeCurrent())     != Terca)
        {
        if(Funcao_Quarta(TimeCurrent())    != Quarta)
        {
        if(Funcao_Quinta(TimeCurrent())    != Quinta)
        {
        if(Funcao_Sexta(TimeCurrent())     != Sexta)
        {
         //----------------------------------------------
            if(Limite_TakeProfit(LimiteTake)==false)
              {
               if(Limite_StopLoss(LimiteLoss)==false)
                 {
                  if(Limite_Operacoes(LimiteOp)==false)
                    {
                      if(CheckTradePause(1, MagicNumber))
                      {
                  
      
                        ////////////////////////////////////////////////////////////////////////////
                        ////+------------------------------------------------------------------+////
                        ////|                                                                  |////
                        ////|                         INDICADORES                              |////
                        ////|                                                                  |////
                        ////+------------------------------------------------------------------+////
                        ////////////////////////////////////////////////////////////////////////////
    
      
//------------------------ BANDA DE BOLLINGER ------------------------------------
           
      // ROMPIMENTO BANDA DE BOLLINGER - PARA FORA 
      if(EstrategiaBB==Rompimento)
        {
         //------ INDICADOR 1
         if(Indicador1==BandaBollinger)
           {         
            if((velas[1].close > bb_Cima[1])) 
              {Funcao_compra_1();}
           
            if((velas[1].close < bb_baixo[1])) 
              {Funcao_venda_1();} 
            }
          }
 
Rafael Magalhães:  My setup needs to be updated at least every 1 minute and even I put the function for each new 1 minute candle the backtest is slow.
  1. You are doing all that, every tick.
  2. Test for a new M1 bar.

    For a new bar test, Bars is unreliable (a refresh/reconnect can change number of bars on chart), volume is unreliable (miss ticks), Price is unreliable (duplicate prices and The == operand. - MQL4 programming forum.) Always use time.
              New candle - MQL4 programming forum #3 (2014.04.04)

    I disagree with making a new bar function, because it can only be called once per tick. A variable can be tested multiple times.
              Running EA once at the start of each bar - MQL4 programming forum (2011.05.06)

    detecting a new bar without removing ability to detect tick in multiple timeframe - Easy Trading Strategy - MQL4 programming forum #8 (2021.08.24)

 
William Roeder:
  1. Você está fazendo tudo isso, cada carrapato.
  2. Teste para um novo bar M1.

I put a function to update every new 1 minute bar, but even so the backtest was very slow. It only got better with the update every new 10 minute bar, but that changes my operational and hurts strategy.

Reason: