ArrayInitialize() does not initialize buffers when rates_total diminish

 

Hi,
I have an indicator which prints alternatively on the chart, that is if one buffer has a value the other one has an empty value.
Values are printed till the second last bar (current bar 0 is the rightmost bar), only when a new bar appears on the chart.

The indicator works properly till the next update of rates_total when the new total number of bars is less than the previous total number of bars (for instance, new rates_total 7 and previous rates_total 10).
When this occurs I'd like to clean all the buffers with the function ArrayInitialize() otherwise, bar 0 retains an old value of another bar (with the numbers of the previous example, it has the value of the 10 - 7 = 3rd bar).

The problem is that ArrayInitialize() seems to not be able to clean the buffers in fact bar 0 still has an old value (in the attached code it is the commented part).
The only way is to manually set an empty value inside the for-loop (it is the code in green).

I'd like to understand 1) what happens at the buffers when rates_total decreases and 2) why ArrayInitialize() doesn't work as I would expect.

Thanks

// MQL4
#property strict
#property indicator_chart_window

#property indicator_buffers 2

#property indicator_label1 "arrow_up"
#property indicator_color1 Green
#property indicator_type1 DRAW_ARROW

#property indicator_label2 "trend_dn"
#property indicator_color2 Red
#property indicator_type2 DRAW_ARROW

#define arrow_up 233
#define arrow_dn 234

double arrow_up_buffer[];
double arrow_dn_buffer[];


int OnInit() {
  IndicatorBuffers(2);
  
  SetIndexBuffer(0, arrow_up_buffer);
  SetIndexStyle(0, DRAW_ARROW);
  SetIndexArrow(0, arrow_up);
  
  SetIndexBuffer(1, arrow_dn_buffer);
  SetIndexStyle(1, DRAW_ARROW);
  SetIndexArrow(1, arrow_dn);
  
  return(INIT_SUCCEEDED);
}


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 > 1 ? rates_total - 1 : rates_total - prev_calculated;
  
  //if (prev_calculated == 0) {
  //  ArrayInitialize(arrow_up_buffer, EMPTY_VALUE);
  //  ArrayInitialize(arrow_dn_buffer, EMPTY_VALUE);
  //}
  
  for (int i = limit; i >= 1 ; i--) {
    if (i - 1 == 0) {
      arrow_up_buffer[0] = EMPTY_VALUE;
      arrow_dn_buffer[0] = EMPTY_VALUE;
    }
    
    if (close[i] > open[i]) {
      arrow_up_buffer[i] = low[i];
      arrow_dn_buffer[i] = EMPTY_VALUE;
    }
    else if (close[i] < open[i]) {
      arrow_dn_buffer[i] = high[i];
      arrow_up_buffer[i] = EMPTY_VALUE;
    }
  }

  return(rates_total);
}
Documentation on MQL5: Timeseries and Indicators Access / Bars
Documentation on MQL5: Timeseries and Indicators Access / Bars
  • www.mql5.com
Bars - Timeseries and Indicators Access - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
      arrow_up_buffer[i] = low[i];

Your problem has nothing to do with what you stated. You are accessing low/high arrays as-series, but didn't set them that way.

In MT5, you must set the direction.

To define the indexing direction in the time[], open[], high[], low[], close[], tick_volume[], volume[] and spread[] arrays, call the ArrayGetAsSeries() function. In order not to depend on defaults, call the ArraySetAsSeries() function for the arrays to work with.
          Event Handling / OnCalculate - Reference on algorithmic/automated trading language for MetaTrader 5
 

I beg your pardon if I didn't specify that that snippet of code was for MT4 (added a comment at the code). The following is the same code translated for MT5.

I don't think the issue is if my buffers are timeseries or not, since I'm accessing them correctly (for default, in MT4 they are timeseries, in MT5 they are not):

MT4
(buffers as timeseries == bar 0 on the right)
int limit = rates_total - prev_calculated > 1 ? rates_total - 1 : rates_total - prev_calculated;

for (int i = limit; i >= 0 ; i--) {
  if (i == 0) {
    // buffer[i] = EMPTY_VALUE;
  }
  else {
    // print indicator
  }
}
MT5
(buffers not as timeseries == bar 0 on the left)
int begin = rates_total - prev_calculated > 1 ? prev_calculated : prev_calculated - 1;

for (int i = begin; i < rates_total ; i++) {
  if (i == rates_total - 1) {
    // buffer[i] = 0;
  }
  else {
    // print indicator
  }
}


// MQL5
#property indicator_chart_window

#property indicator_buffers 2
#property indicator_plots 2

#property indicator_label1 "arrow_up"
#property indicator_color1 Green
#property indicator_type1 DRAW_ARROW

#property indicator_label2 "arrow_dn"
#property indicator_color2 Red
#property indicator_type2 DRAW_ARROW

#define arrow_up 233
#define arrow_dn 234

double arrow_up_buffer[];
double arrow_dn_buffer[];

int OnInit() {
  SetIndexBuffer(0, arrow_up_buffer);
  PlotIndexSetInteger(0, PLOT_ARROW, arrow_up);
  
  SetIndexBuffer(1, arrow_dn_buffer);
  PlotIndexSetInteger(1, PLOT_ARROW, arrow_dn);

  for (int i = 0; i <= indicator_buffers; i++) {
    PlotIndexSetDouble(i, PLOT_EMPTY_VALUE, 0);
  }
  
  return(INIT_SUCCEEDED);
}


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 begin = rates_total - prev_calculated > 1 ? prev_calculated : prev_calculated - 1;
  
  //if (prev_calculated == 0) {
  //  ArrayInitialize(arrow_up_buffer, 0);
  //  ArrayInitialize(arrow_dn_buffer, 0);
  //}

  for (int i = begin; i < rates_total - 1 ; i++) {
    if (i + 1 == rates_total - 1) {
      arrow_up_buffer[rates_total - 1] = 0;
      arrow_dn_buffer[rates_total - 1] = 0;
    }
    
    if (close[i] > open[i]) {
      arrow_up_buffer[i] = low[i];
      arrow_dn_buffer[i] = 0;
    }
    else if (close[i] < open[i]) {
      arrow_dn_buffer[i] = high[i];
      arrow_up_buffer[i] = 0;
    }
    
  }
    
  return(rates_total);
}
 
dcstoyanov #:

I beg your pardon if I didn't specify that that snippet of code was for MT4 (added a comment at the code). The following is the same code translated for MT5.

I don't think the issue is if my buffers are timeseries or not, since I'm accessing them correctly (for default, in MT4 they are timeseries, in MT5 they are not):

MT4
(buffers as timeseries == bar 0 on the right)
MT5
(buffers not as timeseries == bar 0 on the left)


i have the exact same question. if for some reason we used non reversed  buffers and entering from the selected index to read elements up to the newest data. so: 

int lookback = rates_total - range;
for(int bar = lookback; bar < rates_total-1; bar++)

 now when rates_total decreases to recalculate its value, for example if "Max bars in chart" is selected as 50000. In this case, how would it be best to get the correct value from the timeseries indicator buffer?

 It is not always a solution to go the easier way and reverse the array and read data beginning on the other side because such things still happen in data processing. Therefore, it is very sad that no one has answered, but we hope to raise the topic again.

cheers ! 

ArrayInitialize() does not initialize buffers when rates_total diminish
ArrayInitialize() does not initialize buffers when rates_total diminish
  • 2022.12.13
  • www.mql5.com
Hi, I have an indicator which prints alternatively on the chart, that is if one buffer has a value the other one has an empty value...