Sebastian Bonilla
Sebastian Bonilla

Reputation: 87

Why do I get array our of range in MQL4?

I am trying to make an indicator that shows when x candles of the same color appear on the chart. But I am getting an array out of range error.

I think the problem may be in down[i] = Low[i] but I don't know why.

Here is the code:

//+------------------------------------------------------------------+
//|                                                       SlayEm.mq4 |
//|                               Copyright 2016, Sebastian Bonilla. |
//|                                  https://www.sebastianbonilla.me |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Sebastian Bonilla."
#property link      "https://www.sebastianbonilla.me"
#property description "show X amount of candles of the same color."
#property version   "1.00"
#property strict
#property indicator_chart_window

//--- input parameters
extern int minCandles = 4;
double up[];
double down[];

//+------------------------------------------------------------------+    
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
SetIndexBuffer(0,up); //assign up to the first buffer
SetIndexStyle(0,DRAW_ARROW);
SetIndexArrow(0,233);
SetIndexLabel(0, "Up Arrow");

 //stuff for 1
  SetIndexBuffer(1,down); //assign down to the second buffer
  SetIndexStyle(1,DRAW_ARROW);
  SetIndexArrow(1,234);
  SetIndexLabel(1, "Down Arrow");
 //---
return(INIT_SUCCEEDED);
}
  //+------------------------------------------------------------------+
  //| Custom indicator iteration function                              |
 //+------------------------------------------------------------------+
  int OnCalculate(const int rates_total,
            const int prev_calculated,
            const datetime &time[],
            const double &open[],
            const double &high[],
            const double &low[],
            const double &close[],
            const long &tick_volume[],
            const long &volume[],
            const int &spread[])
  {//------------------------------------------

int limit = MathMax(rates_total-prev_calculated,2);
int i; 
int bull_count = 0;
int bear_count = 0;

for (i = 1; i < limit; i++){

//--bears-----------------------------------------------------------------------------------
if(Open[i] >= Open[i-1]){
   bear_count++;
   if (bear_count > minCandles) up[i] = High[i];
}
else bear_count = 0;   // this by itself works but from right to left


// --- bulls ----------------------------------------

if(Open[i] < Open[i-1]){
   bull_count++;
   if (bull_count > minCandles) down[i] = Low[i];
}
else bull_count = 0;  //this part creates the array out of range error*/

}

Comment((string)bear_count+ " --- ", (string)bull_count +" --- ", (string)i);


 //--- return value of prev_calculated for next call
 return(rates_total);
 }


//+------------------------------------------------------------------+

Upvotes: 1

Views: 1511

Answers (1)

user3666197
user3666197

Reputation: 1

There are a few strange things behind the writing a fast and efficient [ Custom Indicator ] MQL4-code.

First, the real-time headache coming from a design decision to accumulate all the computational efforts from all the present [ Custom Indicator ] into a single thread.

While this is hidden, it increases the pressure to minimise all execution latencies at a cost of the colculus being operated in segmented mini-batches, from the deepest history ( the bars farthest back to the left ) proceeding iteratively forwards to the right, towards the current Bar.

One might get confused from the concept of reversed-numbering of the Bars, starting from [0]-for the most recent Bar ( the live Bar ), counting up, while going deeper and deeper towards the history on the far left.

If it were not enough, there are some additional prohibited things inside a [ Custom Indicator ], but as your web-page shows that you provide [ Custom Indicator ] programming on a commercial basis, it is worthless to repeat 'em here again.


Production-grade code for [Custom Indicator] ought have at least:

  • protective fuses
  • minimised main duty-cycle overheads
  • zero raw-Comment()-s to avoid damages to GUI/MMI

#property strict

//--- input parameters
extern int    minCandles = 4;

//--- input PROTECTIVE FUSES:

       int    minCandlesFUSED = MathMax( 2, minCandles );               // assign no less than 2 irrespective of the extern
       double up[];
       double down[];

//+------------------------------------------------------------------+    
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit() {

 // indicator buffers mapping
    SetIndexBuffer( 0, up );                                            // assign up[] to the first buffer
    SetIndexStyle(  0, DRAW_ARROW );
    SetIndexArrow(  0, 233 );
    SetIndexLabel(  0, "Up Arrow" );

 // stuff for 1
    SetIndexBuffer( 1, down );                                          // assign down[] to the second buffer
    SetIndexStyle(  1, DRAW_ARROW );
    SetIndexArrow(  1, 234 );
    SetIndexLabel(  1, "Down Arrow" );

 // RET
    return( INIT_SUCCEEDED );
    }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate( const int       rates_total,
                 const int       prev_calculated,
                 const datetime &time[],
                 const double   &open[],
                 const double   &high[],
                 const double   &low[],
                 const double   &close[],
                 const long     &tick_volume[],
                 const long     &volume[],
                 const int      &spread[]
                 ) {
 // ------------------------------------------

    int          limit  = rates_total
                        - prev_calculated
                        + minCandlesFUSED;
    if (  Bars + limit <  minCandlesFUSED + 1 ) return( 0 ); // --> JIT/RET( 0 )
                                //               ^--------------------^--- MEANING-FULL value, ref prev_calculated mechanisation
                                // makes no sense to start indicator w/o at least minCandlesFUSED + 1 Bars ready
    int bull_count = 0;
    int bear_count = 0;

    for ( int i = limit + 1;    // iterator .SET             to start [limit + 1] Bars back in time (towards left), moving forwards -> [0]
              i > 0;            // iterator .PRE-CONDITION   to keep looping while i > [0] points to already exist. Bars->[1], leaving [0] out
              i--               // iterator .DEC             on loop-end, before re-testing next loop .PRE-CONDITION
              ){
       // --------------------------------------------------------------BEARS
          if (  Open[i] >= Open[i-1] ){
                bear_count++;
                if (  bear_count > minCandlesFUSED ) up[i] = High[i];   // ref. above the 
          }
          else  bear_count = 0;                                         // this by itself works

       // --------------------------------------------------------------BULLS
          if (  Open[i] < Open[i-1] ){
                bull_count++;
                if (  bull_count > minCandlesFUSED ) down[i] = Low[i];
          }
          else  bull_count = 0;                                          // this part creates the array out of range error*/

    }

    Comment( (string)bear_count                                         // rather use StringFormat( "TEMPLATE: %d UP --- %d DN --- ", bear_count,
           + " --- ",                                           //                                                            bull_count
             (string)bull_count                                         //                          )
           + " --- "
             );

    return( rates_total );                                              // return( rates_total ) value becomes -> prev_calculated for the next call
    }
//+------------------------------------------------------------------+

Upvotes: 1

Related Questions