"endless loop detected in OnInit function" (EA rejected by Cloud Network)?

 

This is the error I get when I try to test my EA on the Cloud Network. I know what an endless loop looks like and there can't be one. The loop in OnInit is setting up the arrays/handles for my multi-currency EA. The currency string is an input. It can also be set to "Current" which is just the chart the EA is on. The first thing my OnInit does (if not "Current") is split the string of input currencies, sets the NumberOfTradeableSymbols and resizes all arrays and handles for this. The loop is:

for(int SymbolLoop=0;SymbolLoop<NumberOfTradeableSymbols;SymbolLoop++){

}

It's worth mentioning that this error is never one I have ever got when trying my EA on my local farm network or local agents. It's a little confusing, as there is no path in the code where NumberOfTradeableSymbols could be a massive number...

 
Peat Walker: This is the error I get when I try to test my EA on the Cloud Network. I know what an endless loop looks like and there can't be one. The loop in OnInit is setting up the arrays/handles for my multi-currency EA. The currency string is an input. It can also be set to "Current" which is just the chart the EA is on. The first thing my OnInit does (if not "Current") is split the string of input currencies, sets the NumberOfTradeableSymbols and resizes all arrays and handles for this. The loop is:
for(int SymbolLoop=0;SymbolLoop<NumberOfTradeableSymbols;SymbolLoop++){}
It's worth mentioning that this error is never one I have ever got when trying my EA on my local farm network or local agents. It's a little confusing, as there is no path in the code where NumberOfTradeableSymbols could be a massive number...

Then you have a bug in your code and you are not properly accounting for all possible outcomes of the inputs.

Some condition is causing your loop to become "infinite". Without that part of the source code, we can not say much, so analyse and debug your code thoroughly to find the issue, and correct it.

Also, please use the CODE button when you post code.

Code button in editor

 

Fernando Carreiro #:

Then you have a bug in your code and you are not properly accounting for all possible outcomes of the inputs.

Some condition is causing your loop to become "infinite". Without that part of the source code, we can not say much, so analyse and debug your code thoroughly to find the issue, and correct it.

Also, please use the CODE button when you post code.

Below is my OnInit function. The ResizeCoreArrays()/ResizeIndicatorHandles() functions have no loops of any kind in it, purely ArrayResize(), and SetUpIndicatorHandles() function has the same loop that is in the OnInit() function, so if it is endless in OnInit, it will also be endless in SetUpIndicatorHandles().

int OnInit()
  {
//---
   if(!MQLInfoInteger(MQL_TRADE_ALLOWED))
     {
      Alert(eaName + " - " + _Symbol + ": Trading Is Not Allowed");
      return(INIT_FAILED);
     }

   if(TradeSymbols == "CURRENT")  //Override TradeSymbols input variable and use the current chart symbol only
     {
      NumberOfTradeableSymbols = 1;

      ArrayResize(SymbolArray, 1);
      SymbolArray[0] = Symbol();

      Print("EA will process ", SymbolArray[0], " only");
     }
   else
     {
      string TradeSymbolsToUse = "";
      if(TradeSymbols == "ALL") NumberOfTradeableSymbols = StringSplit(AllSymbolsString, '|', SymbolArray);
      else NumberOfTradeableSymbols = StringSplit(TradeSymbols, '|', SymbolArray);
      
      //CONVERT TradeSymbolsToUse TO THE STRING ARRAY SymbolArray
      for(int SymbolLoop=0; SymbolLoop<NumberOfTradeableSymbols;SymbolLoop++){     
         int num = StringAdd(SymbolArray[SymbolLoop],SymbolSuffix);
         Print("EA will process: ", SymbolArray[SymbolLoop]);
       }
     }
//RESIZE OPEN TRADE ARRAYS (based on how many symbols are being traded)
   ResizeCoreArrays();
//RESIZE INDICATOR HANDLE ARRAYS
   if (inpEMAPd==T82050) inpShortPd=8; inpMedPd=20; inpLongPd=50;
   if (inpEMAPd==T2050100) inpShortPd=20; inpMedPd=50; inpLongPd=100;
   if (inpEMAPd==T850100) inpShortPd=8; inpMedPd=50; inpLongPd=100;
   ResizeIndicatorHandleArrays();
   Print("All arrays sized to accommodate ", NumberOfTradeableSymbols, " symbols");

//INITIALIZE ARAYS
   for(int SymbolLoop=0; SymbolLoop < NumberOfTradeableSymbols; SymbolLoop++)
     {
      trade_this_trend[SymbolLoop] = false;
      OpenTradeOrderTicket[SymbolLoop] = 0;
      spread[SymbolLoop] = pAsk(SymbolArray[SymbolLoop])-pBid(SymbolArray[SymbolLoop]);
      trade_this_trend[SymbolLoop] = false;
     }

//INSTANTIATE INDICATOR HANDLES
   if(!SetUpIndicatorHandles())
      return(INIT_FAILED);
//--------------------------------------------------
   timeBarHTF = 0;
   cTrade.SetExpertMagicNumber(inpMagicNumber);
   cTrade.SetAsyncMode(false);
//---
//SET UP EQUITY HISTORY ARRAY AND FIRST DATE - USED TO CALCULATE CAGR/MeanDD
   if(MQLInfoInteger(MQL_TESTER))
     {
      BackTestFirstDate = TimeCurrent();
      ArrayResize(EquityHistoryArray, 1);
      EquityHistoryArray[0] = AccountInfoDouble(ACCOUNT_EQUITY);
     }

   return(INIT_SUCCEEDED);
  }
 
Peat Walker #:

Below is my OnInit function. The ResizeCoreArrays()/ResizeIndicatorHandles() functions have no loops of any kind in it, purely ArrayResize(), and SetUpIndicatorHandles() function has the same loop that is in the OnInit() function, so if it is endless in OnInit, it will also be endless in SetUpIndicatorHandles().

Please also show the line when you declare the variable

NumberOfTradeableSymbols


I want to see the type and initial value you set.

 

Look if that helps.

Forum on trading, automated trading systems and testing trading strategies

Cloud sync errors

Slava, 2013.05.07 08:54

Endless loop detected on Cloud Agents only. If one of calls (OnInit, OnDeinit, OnTick, OnTimer etc) works more than 10 minutes

 
Peat Walker #:Below is my OnInit function. The ResizeCoreArrays()/ResizeIndicatorHandles() functions have no loops of any kind in it, purely ArrayResize(), and SetUpIndicatorHandles() function has the same loop that is in the OnInit() function, so if it is endless in OnInit, it will also be endless in SetUpIndicatorHandles().

I see several problematic points that may or may not be relevant to the issue.

  1. You don't check for an error case when using StringSplit fails and returns -1 for NumberOfTradeableSymbols. Although the loops will not run in this case, we can't see how that will affect the rest of the functions you call (e.g. ResizeCoreArrays, ResizeIndicatorHandleArrays), and you are also not returning a INIT_FAILED for these cases.
  2. You seem to be trying to read Bid and Ask quote prices (function pAsk and pBid) from within OnInit() event handler which is a bad practice. During OnInit() the connection to the trade server may not have been established yet. You should only look at such data once you have confirmed the connection and the existence of data. The best way to do this is after receiving the first tick in the OnTick() event handler, not in OnInit().
  3. We cannot see how the functions pAsk and pBid are implemented, and how you implement the case where Ask and Bid prices are not available. Are they perhaps blocking while waiting for data?
  4. Even discounting the problem with the connection issue in OnInit, this is a multi-symbol EA, and I don't see any code that checks if the Symbols being accessed are active and enabled in the Market Watch and that their data is available and synchronised. How are you handling the cases of symbols not even being available in the Market Watch?
In summary, you are trying to access data that may not be available during OnInit(). You should offload a lot of this initialisation procedure to run during OnTick() or OnTimer() calls instead and you also need to verify the all the symbols are available, enabling them if necessary, and synchronising their data before accessing it. You may need to establish a state machine, so the initialisation procedure does not block any of the event handlers while waiting for data synchronisation.
 
Fernando Carreiro #:

I see several problematic points that may or may not be relevant to the issue.

  1. You don't check for an error case when using StringSplit fails and returns -1 for NumberOfTradeableSymbols. Although the loops will not run in this case, we can't see how that will affect the rest of the functions you call (e.g. ResizeCoreArrays, ResizeIndicatorHandleArrays), and you are also not returning a INIT_FAILED for these cases.
  2. You seem to be trying to read Bid and Ask quote prices (function pAsk and pBid) from within OnInit() event handler which is a bad practice. During OnInit() the connection to the trade server may not have been established yet. You should only look at such data once you have confirmed the connection and the existence of data. The best way to do this is after receiving the first tick in the OnTick() event handler, not in OnInit().
  3. We cannot see how the functions pAsk and pBid are implemented, and how you implement the case where Ask and Bid prices are not available. Are they perhaps blocking while waiting for data?
  4. Even discount the issue with the connection issue in OnInit, this is a multi-symbol EA, and I don't see any code that checks if the Symbols being accessed are active and enabled in the Market watch and data is available and synchronised. How are you handling the cases of symbols not even being available in the Market Watch?
In summary, you are trying to access data that may not be available during OnInit(). You should offload some of initialisation procedure to run during OnTick() or OnTimer() calls instead and you also need to verify the all the symbols are available, enabling them if necessary, and synchronising their data before accessing it.

OK, thanks. I will address these. If SetUpIndicatorHandles() fails, INIT_FAILED is returned and if ResizeIndicatorHandleArrays() fails, SetUpIndicatorHandles() will also fail, so ultimately INIT_FAILED will be returned in case either function fails to run successfully. Regarding pAsk and pBid, they are defined as such:

#define pBid(CurrentSymbol)   SymbolInfoDouble(CurrentSymbol,SYMBOL_BID)
#define pAsk(CurrentSymbol)   SymbolInfoDouble(CurrentSymbol,SYMBOL_ASK)

Regarding MarketWatch error handling, there is code in the SetUpIndicatorHandles() when attempting to instantiate handles that checks for the error code 4302 and prints a message saying that the symbols need to be added to MarketWatch first.

I'll fix the other issues and see if I still get the same error. I appreciate the advice.

 
Alain Verleyen #:

Look if that helps.


Thanks, I did read this. Very interesting. I will attempt to implement both solutions where there is an agent check before any optimisations begin. My guess is that this issue becomes a performance problem with some agents because of the EA being multi-currency and sometimes even the data download from MQL5 can take a while. On top of this, I have a PC with 64GB of RAM, and after optimising the rest of the code to minimise memory usage, and maximising the number of calculations that are done within the EA code itself, once you have around 8 symbols with 8 years of data loaded (8 years for optimization, 2 years of walk-forward), RAM is completely maxed out and of my 20 agents in my PC, I can only run around 10. I know this because I've also tested 20 symbols and then I'm limited to 4-5 cores max. If you don't disable the other agents, you get the "no memory" error or "no disk space for ticks generating function" and agents automatically disable themselves after enough errors.

That's why I believe the cloud agent's RAM check code helps in reducing the endless loop error. I'm yet to test this, so I will report back once I do.

 
AMI289 #:

Please also show the line when you declare the variable


I want to see the type and initial value you set.

It is a global variable declared before the OnInit() call as such:

int NumberOfTradeableSymbols = 1;
 
Peat Walker #:

Thanks, I did read this. Very interesting. I will attempt to implement both solutions where there is an agent check before any optimisations begin. My guess is that this issue becomes a performance problem with some agents because of the EA being multi-currency and sometimes even the data download from MQL5 can take a while. On top of this, I have a PC with 64GB of RAM, and after optimising the rest of the code to minimise memory usage, and maximising the number of calculations that are done within the EA code itself, once you have around 8 symbols with 8 years of data loaded (8 years for optimization, 2 years of walk-forward), RAM is completely maxed out and of my 20 agents in my PC, I can only run around 10. I know this because I've also tested 20 symbols and then I'm limited to 4-5 cores max. If you don't disable the other agents, you get the "no memory" error or "no disk space for ticks generating function" and agents automatically disable themselves after enough errors.

That's why I believe the cloud agent's RAM check code helps in reducing the endless loop error. I'm yet to test this, so I will report back once I do.

It's always recommended to use, at maximum, a number of agents matching the physical cores of your computer.
 
Alain Verleyen #:
It's always recommended to use, at maximum, a number of agents matching the physical cores of your computer.

Ok. I have been able to use all 20 agents when the number of pairs is low so memory required per task passed to the CPU is manageable. If I'm testing on 20 symbols however, with 64GB of RAM, anything more than 3-4 active agents on a 12-core (20-thread) CPU causes problems. 

Now I'm having another problem with the Cloud Network where history data consistently times out (attachment)...maybe a new thread needed for this...

Reason: