Help me on array out of range guys

 

Hi guys, I am an upcoming developer.

I coded an ea and implemented TP based on bars count but what I noticed is that at certain point the ea gets detached from the chart even when I re-attach it. When I check the expert tab for the bug I saw it quoting array out of range line 394 and at times  399

Below is the code of TP based on bars count implemented in which line 394 and 399.

Help me out, what am I doing wrong?

Please check the attached image.

//+------------------------------------------------------------------+
void TPOnCandle()
{
   int bar=0;
   double open_price=0;
   datetime open_time=0;
   
   for(int i=PositionsTotal()-1;i>=0;i--)
   {
      if(oPosition.SelectByIndex(i))
      {
         if(oPosition.Symbol()==oSymbol.Name())
         {
            if(oPosition.Magic()==Magic)
            {
               open_time=oPosition.Time();
               bar=iBarShift(oSymbol.Name(),PERIOD_CURRENT,open_time,true);
               open_price=oPosition.PriceOpen();
               int n=0;
               if(bar<=TakeProfitOnCandle)continue;
               else
               {
                  for(int y=bar-1;y>0;y--)
                  {
                     if(oPosition.PositionType()==POSITION_TYPE_BUY)
                     {
                        if(rates[y].close>open_price)n++;
                        if(rates[y].close<open_price)n=0;
                     }
                     else
                     {
                        if(rates[y].close<open_price)n++;
                        if(rates[y].close>open_price)n=0;
                     }
                  }
                  if(n>=TakeProfitOnCandle)
                  {
                     if(!oTrade.PositionClose(oPosition.Ticket()))
                     {
                        Print(FUNCTION": Position #",oPosition.Ticket()," not closed! Error code:",oTrade.ResultRetcode(),"; Error description:",oTrade.ResultRetcodeDescription());
                     }
                     else Print(FUNCTION);
                  }
               }
            }
         }
      }
   }
}
//+------------------------------------------
 

The code is incomplete, cause we don't know exactly what the variable rates is nor how it is initialized. However, I'll assume rates is an array of type MqlRates and you call CopyRates to fill the buffer.

When you acess rates, you loop through it expecting it has a size of equal or bigger bar-1, which corresponds to the number of bars since the selected position open candle. This means that if you access rates at index bar+N, you'll get the error array out of range. So you must make sure that rates array is bigger than or equal the iBarShift function result. If you are hedging (which you probably are considering the code you provided), every position will have a different open time, farther or closer to the current candle, then iBarShift shall return a bigger value than the size of rates array.


Either call CopyRates everytime you loop through a position list in TPOnCandle or loop once through every position, get the farthest candle where you opened a position, store it in a variable and then call CopyRates.

Descubra novos recursos para o MetaTrader 5 com a comunidade e os serviços MQL5
Descubra novos recursos para o MetaTrader 5 com a comunidade e os serviços MQL5
  • 2024.02.16
  • www.mql5.com
MQL5: linguagem de estratégias de negociação inseridas no Terminal do Cliente MetaTrader 5. A linguagem permite escrever seus próprios sistemas automáticos de negócios, indicadores técnicos, scripts e bibliotecas de funções
 
kennymic1:

Hi guys, I am an upcoming developer.

I coded an ea and implemented TP based on bars count but what I noticed is that at certain point the ea gets detached from the chart even when I re-attach it. When I check the expert tab for the bug I saw it quoting array out of range line 394 and at times  399

Below is the code of TP based on bars count implemented in which line 394 and 399.

Help me out, what am I doing wrong?

Please check the attached image.

We will not be able to assist you with this snippet, we need to see the code to establish where the error originates and what is causing it. I can help with the following if you want to go see if you have this problem


So, In MQL5, "array out of range" refers to an error that occurs when you attempt to access or modify an element of an array at an index that is beyond the valid range of indices for that array.

Arrays in MQL5, like in many programming languages, are zero-indexed, meaning that the index of the first element is 0, the second element is at index 1, and so on. When you receive an "array out of range" error, it typically means that you've attempted to access an element at an index that is less than 0 or greater than or equal to the length of the array.

Here is a simple example for you down below i have created.

int myArray[3]; // Array with 3 elements

// Trying to access an element outside the valid range
int element = myArray[3]; // This will cause an "array out of range" error because valid indices are 0, 1, and 2.

To avoid this error, ensure that you're accessing array elements within the valid index range, typically from 0 to ArraySize(array) - 1 . Also, consider using functions like ArraySize() to dynamically determine the size of the array to avoid hardcoding array lengths, which can lead to errors when the array size changes. Additionally, always validate user inputs or loop indices to make sure they are within the valid range before accessing array elements.

 

I appreciate everyone responding in order to help me out, thank you very much.

Below is the code you requested for.

I will await your response. Thanks once again

MqlRates rates[];
int st_handle=0,
    n_trade=0,
    m_trade=0,
    iShift=0;
double st_color[],
       stop_loss=0,
       take_profit=0,
       t_stop=0,
       t_step=0,
       brk=0,
       buy_sl=0,
       sell_sl=0;
static datetime prevtime;

//-----------------------------------------------------

string _symbol[];
string symbol2[];

datetime ExpiryDate=D'2024.02.28 23:00'; //Expiry Date
int account_number=22512591;  // account number

//---v1
bool EquityTargetMeet = false;
double equityNow;
long MyCharts[];


//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{

//--------------------------------------------

if((long)ExpiryDate <= TimeCurrent())
    ExpertRemove();

  if(account_number != AccountInfoInteger(ACCOUNT_LOGIN) && account_number != 0)
    ExpertRemove();
    
//--------------------------------------------- 

   oSymbol.Name(_Symbol);
   oTrade.SetExpertMagicNumber(Magic);
   oTrade.SetDeviationInPoints(Deviation);
   oTrade.SetTypeFillingBySymbol(_Symbol);
   oTrade.SetAsyncMode(false);
   
   st_handle=iCustom(oSymbol.Name(),
                     PERIOD_CURRENT,
                     "::Indicators\\My_trend.ex5",
                     inpPeriod,
                     inpAtrDevPeriod,
                     inpUseWhat,
                     UseSound,
                     UseNotification);
   if(st_handle==INVALID_HANDLE)
   {
      Print("Simple Trend indicator is not loaded! Error:",GetLastError());
      return(INIT_FAILED);
   }
   
   if(nTrade<1){Print("Trades per signal cannot be less than 1! Trades per signal set as 1!");n_trade=1;}
   else n_trade=nTrade;
   if(MaxOrders<1){Print("Max number of orders cannot be less than 1! Max number of orders set as 1!");m_trade=1;}
   else m_trade=MaxOrders;
   
   if(enter_type==e0||enter_type==e2)iShift=1;
   else iShift=0;
   
   if(StopLossOnMoney>0)
   {
      Print("Stop loss in money cannot be greater than zero! Please check it out!");
      return(INIT_FAILED);
   }
   if(TakeProfitOnMoney<0)
   {
      Print("Take Profit in money cannot be less than zero! Please check it out!");
      return(INIT_FAILED);
   }
   
   stop_loss=oSymbol.NormalizePrice(StopLoss*oSymbol.Point());
   take_profit=oSymbol.NormalizePrice(TakeProfit*oSymbol.Point());
   t_stop=oSymbol.NormalizePrice(Trailing*oSymbol.Point());
   t_step=oSymbol.NormalizePrice(TrailingDist*oSymbol.Point());
   brk=oSymbol.NormalizePrice(Breakeven*oSymbol.Point());
   
   ArraySetAsSeries(rates,true);
   ArraySetAsSeries(st_color,true);
   
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{

//---- four functions
   if(!FourFunctions())return;
   
//--------------------------------------------------------------------

   if(!GetData()){Print("Last indicator data or last rates is not loaded! Error:",GetLastError());return;}

   trailing_stop();
   break_even();
   if(StopLossOnMoney<0||TakeProfitOnMoney>0)CheckSLTPOnMoney();
   if(enter_type==e2)CheckCustomSL();

   if(prevtime!=rates[0].time)
   {
      if(TakeProfitOnCandle!=0)TPOnCandle();
      if(TradeTime())
      {
         if(oSymbol.Spread()<=Spread)
         {
            if(CountCandleDeal(POSITION_TYPE_BUY)==0)
            {
               if(CheckSignal(0,iShift))
               {
                  if(enter_type==e0||enter_type==e1||(enter_type==e2&&rates[1].close>rates[1].open))
                  {
                     if(CountPositions(-1)<m_trade&&(trade_dir==t0||trade_dir==t2))OpenPosition(ORDER_TYPE_BUY);
                  }
               }
            }
            if(CountCandleDeal(POSITION_TYPE_SELL)==0)
            {
               if(CheckSignal(1,iShift))
               {
                  if(enter_type==e0||enter_type==e1||(enter_type==e2&&rates[1].close<rates[1].open))
                  {
                     if(CountPositions(-1)<m_trade&&(trade_dir==t1||trade_dir==t2))OpenPosition(ORDER_TYPE_SELL);
                  }   
               }
            }
         }
      }
      if(enter_type==e0||enter_type==e2)prevtime=rates[0].time;
   }
}
//+------------------------------------------------------------------+
bool GetData()
{
   if(!CopyRates(oSymbol.Name(),PERIOD_CURRENT,0,100,rates))return(false);
   if(!CopyBuffer(st_handle,1,0,3,st_color))return(false);
   if(!oSymbol.RefreshRates())return(false);
   if(!oSymbol.Refresh())return(false);
   return(true);
}
//+------------------------------------------------------------------+
bool TradeTime()
{
   MqlDateTime time;
   string curr_time=TimeToString(TimeCurrent(),TIME_MINUTES);
   if(TimeToStruct(TimeCurrent(),time))
   {
      if(time.day_of_week==1&&monday==o1)
      {
         if(curr_time>=start1&&curr_time<stop1)return(true);
      }
      if(time.day_of_week==2&&tuesday==o1)
      {
         if(curr_time>=start2&&curr_time<stop2)return(true);
      }
      if(time.day_of_week==3&&wednesday==o1)
      {
         if(curr_time>=start3&&curr_time<stop3)return(true);
      }
      if(time.day_of_week==4&&thursday==o1)
      {
         if(curr_time>=start4&&curr_time<stop4)return(true);
      }
      if(time.day_of_week==5&&friday==o1)
      {
         if(curr_time>=start5&&curr_time<stop5)return(true);
      }
      if(time.day_of_week==6&&saturday==o1)
      {
         if(curr_time>=start6&&curr_time<stop6)return(true);
      }
      if(time.day_of_week==0&&sunday==o1)
      {
         if(curr_time>=start7&&curr_time<stop7)return(true);
      }
   }
   return(false);
}
//+------------------------------------------------------------------+
void CheckCustomSL()
{
   if(CountPositions(POSITION_TYPE_BUY)!=0)
   {
      if(ObjectFind(ChartID(),"Custom SL for BUY")<0)
      {
         if(ObjectCreate(ChartID(),"Custom SL for BUY",OBJ_HLINE,0,TimeCurrent(),sl_buy))
         {
            ObjectSetInteger(ChartID(),"Custom SL for BUY",OBJPROP_STYLE,STYLE_DASHDOT);
         }
      }
      if(sl_buy!=0&&oSymbol.Bid()<=sl_buy)
      {
         ClosePositions(POSITION_TYPE_BUY);
         ObjectDelete(ChartID(),"Custom SL for BUY");
      }
   }
   else if(ObjectFind(ChartID(),"Custom SL for BUY")>-1)ObjectDelete(ChartID(),"Custom SL for BUY");
   
   if(CountPositions(POSITION_TYPE_SELL)!=0)
   {
      if(ObjectFind(ChartID(),"Custom SL for SELL")<0)
      {
         if(ObjectCreate(ChartID(),"Custom SL for SELL",OBJ_HLINE,0,TimeCurrent(),sl_sell))
         {
            ObjectSetInteger(ChartID(),"Custom SL for SELL",OBJPROP_STYLE,STYLE_DASHDOT);
         }
      }
      if(sl_sell!=0&&oSymbol.Ask()>=sl_sell)
      {
         ClosePositions(POSITION_TYPE_SELL);
         ObjectDelete(ChartID(),"Custom SL for SELL");
      }
   }
   else if(ObjectFind(ChartID(),"Custom SL for SELL")>-1)ObjectDelete(ChartID(),"Custom SL for SELL");
}
//+------------------------------------------------------------------+
void TPOnCandle()
{
   int bar=0;
   double open_price=0;
   datetime open_time=0;
   
   for(int i=PositionsTotal()-1;i>=0;i--)
   {
      if(oPosition.SelectByIndex(i))
      {
         if(oPosition.Symbol()==oSymbol.Name())
         {
            if(oPosition.Magic()==Magic)
            {
               open_time=oPosition.Time();
               bar=iBarShift(oSymbol.Name(),PERIOD_CURRENT,open_time,true);
               open_price=oPosition.PriceOpen();
               int n=0;
               if(bar<=TakeProfitOnCandle)continue;
               else
               {
                  for(int y=bar-1;y>0;y--)
                  {
                     if(oPosition.PositionType()==POSITION_TYPE_BUY)
                     {
                        if(rates[y].close>open_price)n++;
                        if(rates[y].close<open_price)n=0;
                     }
                     else
                     {
                        if(rates[y].close<open_price)n++;
                        if(rates[y].close>open_price)n=0;
                     }
                  }
                  if(n>=TakeProfitOnCandle)
                  {
                     if(!oTrade.PositionClose(oPosition.Ticket()))
                     {
                        Print(__FUNCTION__": Position #",oPosition.Ticket()," not closed! Error code:",oTrade.ResultRetcode(),"; Error description:",oTrade.ResultRetcodeDescription());
                     }
                     else Print(__FUNCTION__);
                  }
               }
            }
         }
      }
   }
}
 
kennymic1 #:

I appreciate everyone responding in order to help me out, thank you very much.

Below is the code you requested for.

I will await your response. Thanks once again

In your TPOnCandle() function, the loop seems fine at first glance, but the issue might occur when y reaches 0 and tries to access rates[y] . In MQL4, array indexing starts from 0, so accessing rates[0] is valid, but if y becomes -1, accessing rates[-1] would cause an "array out of range" error.

To fix this issue, you need to ensure that the loop stops before y becomes negative. You can modify the loop condition to y >= 1 instead of y > 0 to prevent accessing rates[-1] . Here's the modified section of your code i have created:

for(int y = bar - 1; y >= 1; y--)
{
    if(oPosition.PositionType() == POSITION_TYPE_BUY)
    {
        if(rates[y].close > open_price) n++;
        if(rates[y].close < open_price) n = 0;
    }
    else
    {
        if(rates[y].close < open_price) n++;
        if(rates[y].close > open_price) n = 0;
    }
}

This change ensures that the loop stops before y reaches 0, preventing the "array out of range" error.

Additionally, you should also consider checking if bar is greater than the array size before entering the loop to avoid accessing rates[bar - 1] when bar is out of range.

if (bar > ArraySize(rates)) return; // Check if bar is out of range

for(int y = bar - 1; y >= 1; y--)
{
    // Loop body remains the same
}
Make sure to apply these modifications to both occurrences of the loop in your TPOnCandle() function. This should resolve the "array out of range" issue you're encountering. For an upcoming developer you are doing good work, the code is not so easy.
 
Nardus Van Staden #:
if (bar > ArraySize(rates)) return; // Check if bar is out of range

Thank you sir. I have implemented the modification at your directives.

I love testing with live market condition so I will let you know if it has been solved when market open.

Thank you all. I am learning from you all. Good to learn at the feet of the masters. Thanks

 
kennymic1 #:

Thank you sir. I have implemented the modification at your directives.

I love testing with live market condition so I will let you know if it has been solved when market open.

Thank you all. I am learning from you all. Good to learn at the feet of the masters. Thanks

It is a pleasure, please let me know if it worked. Yes, i agree, forward testing is the best way

 
kennymic1 #: Below is the code you requested for.
int st_handle=0,
    n_trade=0,
    m_trade=0,
    iShift=0;
double st_color[],
       stop_loss=0,
       take_profit=0,

You initialized the global variables. Remember that on chart change (symbol/TF) an EA is not reloaded. Thus, the variables keep their previous value. If you actually need them re-initialized you must do it in OnInit.

 
kennymic1 #:

Thank you sir. I have implemented the modification at your directives.

I love testing with live market condition so I will let you know if it has been solved when market open.

Thank you all. I am learning from you all. Good to learn at the feet of the masters. Thanks

Just follow what i wrote and explained in great detail up here, youll see, it will work.

 
Nardus Van Staden #:

Just follow what i wrote and explained in great detail up here, youll see, it will work.

hello sir, thank you very much sir. I am just coming online.

The problem is solved.

You are the real G sir! Thank you sir.

Thanks everyone!

 
William Roeder #:

You initialized the global variables. Remember that on chart change (symbol/TF) an EA is not reloaded. Thus, the variables keep their previous value. If you actually need them re-initialized you must do it in OnInit.

hello sir, thanks for pointing this out.

Do you mean I should put those variables in the Oninit?

I await your response sir. Thanks once again

Reason: