MQL4 Self Referencing Custom Indicator, array out of range

 

Hello, I am new to the MQL language. I am attempting to access and apply past values to my indicator based on certain conditions.

My test code looks like:

int limit = rates_total-prev_calculated;

if(rates_total<=DATA_LIMIT)
      return(0);
//--- last counted bar will be recounted
   if(prev_calculated>0)
     {
      limit++;
      //prev=ExtAOBuffer[limit];
     }

for(int i=0;i<limit;i++)
{
   double ma = iMA(NULL,0,inLen,0,MODE_EMA,PRICE_CLOSE,i);
   if(iOpen(NULL,0,0) < iClose(NULL,0,0))
   {
      coolLineBuffer[i] = iMA(NULL,0,inLen,0,MODE_EMA,PRICE_CLOSE,i);
   }else{
      coolLineBuffer[i] = coolLineBuffer[i-1];
   }
}

The problem is I get an error:

SimpleTest EURUSD,M5: array out of range in 'SimpleTest.mq4' (72,41)

The issue is that my condition is false on the first calculation, so there is no data for coolLineBuffer to reference in the past.

What is the proper way to check for this in MQL4? I'd be happy simply setting the value to zero if there is no previous data.


Thank you very much.

 
coolLineBuffer[i] = coolLineBuffer[i-1];

when i==0, you cannot access the buffer at [0-1]

It doesn't exist. So you get the error.

Anyway, you should not give a buffer a value based on a bar index in the future.
 
for(int i=0;i<limit;i++)
{
   double ma = iMA(NULL,0,inLen,0,MODE_EMA,PRICE_CLOSE,i);
   if(iOpen(NULL,0,0) < iClose(NULL,0,0))
   {
      coolLineBuffer[i] = iMA(NULL,0,inLen,0,MODE_EMA,PRICE_CLOSE,i);
   }else{
      coolLineBuffer[i] = coolLineBuffer[i-1];
  1. You won't get a valid MA until you have inLen bars.
              How to do your lookbacks correctly.
  2. Why are you looking at bar zero when you are evaluating bar i?
  3. As Keith said, there is no bar 0-1. If you meant the previous bar, that's i+1. But then you'll have to process bars max to zero.
  4. Don't use NULL.
    • You can use NULL in place of _Symbol only in those calls that the documentation specially says you can. iHigh does, iCustom does, MarketInfo does not. OrderSend does not.
    • Don't use NULL (except for pointers where you explicitly check for it.) Use _Symbol and _Period, that is minimalist as possible and more efficient.
    • Zero is the same as PERIOD_CURRENT which means _Period. Don't hard code numbers.
    • MT4: No need for a function call with iHigh(NULL,0,s) just use the predefined arrays, i.e. High[].
 
William Roeder:
  1. You won't get a valid MA until you have inLen bars.
              How to do your lookbacks correctly.
  2. Why are you looking at bar zero when you are evaluating bar i?
  3. As Keith said, there is no bar 0-1. If you meant the previous bar, that's i+1. But then you'll have to process bars max to zero.

Thank you very much for this in-depth answer, and also for catching more bugs than I thought I had! Writing loops for market data is newer to me.

Your link was helpful, I've used a "new way" example which seems to have been successful. Please take a look and let me know if there is anything that stands out, or if I should have any other important checks in place.

for(int i = Bars-1-MathMax(inLen, prev_calculated); i >= 0; --i)
{
   if(Open[i] > Close[i])
   {
      coolLineBuffer[i] = iMA(_Symbol,_Period,inLen,0,MODE_EMA,PRICE_CLOSE,i);
   }else{
      coolLineBuffer[i] = coolLineBuffer[i+1];
   }
}
return rates_total-1;
EDITED: to incorporate your additional point 4.
Reason: