1
votes

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.

  • There is a up and down array buffer (an arrow pointing up or down)
  • minCandles is an extern integer that determines after how many bars to point the arrow.
  • the bear part works but from right to left.

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);
 }


//+------------------------------------------------------------------+
1
Would you mind, Sebastian, to post the full code? There are missing both the declarations and externs, the indicator buffer definitions were also not included. StackOverflow recommends users to post high quality posts, based on M-inimum C-omplete V-erifiable E-ample ( incl. data, where appropriate ) that both demonstrate the issue & serve as a self-contained means to validate a working solution. Another fair policy is to post the complete copy of an objected Error Message ( from MetaTrader Terminal 4 log...using a mouse right-click + Copy...one may post it quite comfortably ) - user3666197
done, I copied the whole code - Sebastian Bonilla
Great step, Sebastian, and the actual error message from [ MetaTrader Terminal 4 ] Terminal - log ( the copy / paste ) ? - user3666197
Also, why have you changed the statement " the bear part works, but the bulls does not. " into another one " the bear part works, but from right to left."? Was it due to some new observations relevant in the problem isolation efforts or just a need to revise the expressed initial hypothesis from the original question for being a misleading part of the problem definition? - user3666197

1 Answers

1
votes

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
    }
//+------------------------------------------------------------------+