CopyBuffer problem (bug?)

 

#property copyright ""
#property link      ""
#property version   "1.00"
#property  indicator_separate_window
#property  indicator_buffers 1
#property  indicator_plots 1
#property  indicator_color1  Silver
#property  indicator_width1  2
double     MacdBuffer[];
int        handle;
int OnInit()
  {
   SetIndexBuffer(0,MacdBuffer,INDICATOR_DATA);
   PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_HISTOGRAM);
   handle=iMA(NULL,0,26,0,MODE_EMA,PRICE_CLOSE);
   return(0);
  }

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 count = rates_total - prev_calculated;
   Print("count = ", count);
  
   //bug start - the error is present when count == 1
   double buf[];
   ArrayResize(buf, count);
   CopyBuffer(handle, 0, 0, count, buf);
   for(int i = 0; i < count; i++) MacdBuffer[i] = buf[i];
   //bug end
  
   //CopyBuffer(handle, 0, 0, count, MacdBuffer); // <--- WORKS

   return(rates_total);
  }

When count == 1, suddenly ALL displayed values of MacdBuffer are some completely bogus value (the same).

However, when CopyBuffer is used, everything works perfectly, even when count == 1.

This is just a proof of concept of code; I know intermediate buffer is redundant here. I found it while writing a custom indicator

 Bug present

 Bug present

 Bug not present

 

 
Try to get rid of ArrayResize(buf, count). I believe CopyBuffer will do it by its own. Maybe it is the reason of your problem, as well.
 

There is no bug.

Please check your code. When you copy 1 value, you are copying it to wrong place. You should copy buf[0] to MacdBuffer[rates_total-1] instead of MacdBuffer[0].

 

I'm sorry, but that's not true. This results in INVERTED macd  (inversion in the whole domain of all bars).

But regardless, when count  == 1, everything still changes to one weird value.

   for(int i = 0; i < count; i++) MacdBuffer[rates_total-1-i] = buf[i];

 

The "nobug" chart uses (only) CopyBuffer; the "bug" chart uses this for.

Without for, ie MacdBuffer[rates_total-1] = buf[0], it just shows, for every tick, another bar from the end. No difference.

(note: there was no count == 1 value, so no weird one-value everywhere... yet) 

 

hasayama: You are right - it's redundant. But the problem still persists.

 

hasayama: You are right - it's redundant. But the problem still persists.

Well, you are using ArrayResize for buf but not for MacdBuffer. If you don't use CopyBuffer, you should resize it manualy, I believe.

Use smth like:

 

ArrayResize( MacdBuffer, count );
for ...
 

From Help

"The function can be applied only to dynamic arrays. Please note that you can't change the size for dynamic arrays set as indicator buffers by the function SetIndexBuffer(). " 

They are supposed to automatically resize themselves...

Documentation on MQL5: Standard Constants, Enumerations and Structures / Indicator Constants / Indicators Lines
  • www.mql5.com
Standard Constants, Enumerations and Structures / Indicator Constants / Indicators Lines - Documentation on MQL5
 

Then my suggestion is not an option.

Any way, array must have size before you try to write data into it. Otherwise you'll get an unpredictable result.

 

"Solved". It seems that all indicator buffers are cleared after each new tick.

This is in contrast to mql4.

Now, it's not a bug if this is written in the manual and by design - I didn't see it, but I may have missed it. Regardless, old mql4 way was better. What's the point in erasing old data? I know that when resizing reallocations may occur, but old data should be copied...

#property copyright ""
#property link      ""
#property version   "1.00"
#property  indicator_separate_window
#property  indicator_buffers 1
#property  indicator_plots 1
#property  indicator_color1  Silver
#property  indicator_width1  2

double     MacdBuffer[];
int        handle;

int OnInit()
  {
   SetIndexBuffer(0,MacdBuffer,INDICATOR_DATA);
   PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_HISTOGRAM);
   handle=iMA(NULL,0,26,0,MODE_EMA,PRICE_CLOSE);
   return(0);
}
 
double x[];
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 count = rates_total - prev_calculated;
   Print("count = ", count);
   for(int i = 0; i < ArraySize(x); i++) MacdBuffer[i+count] = x[i];
   ArrayResize(x, rates_total);
  
   double buf[];
   ArrayResize(buf, count);
   CopyBuffer(handle, 0, 0, count, buf);
   for(int i = 0; i < count; i++) MacdBuffer[i] = buf[i];

   for(int i = 0; i < ArraySize(x); i++) x[i] = MacdBuffer[i];
   return(rates_total);
  }

Documentation on MQL5: Standard Constants, Enumerations and Structures / Indicator Constants / Indicators Lines
  • www.mql5.com
Standard Constants, Enumerations and Structures / Indicator Constants / Indicators Lines - Documentation on MQL5
 
mqltools:

"Solved". It seems that all indicator buffers are cleared after each new tick.

This is in contrast to mql4.

Now, it's not a bug if this is written in the manual and by design - I didn't see it, but I may have missed it. Regardless, old mql4 way was better. What's the point in erasing old data? I know that when resizing reallocations may occur, but old data should be copied...

#property copyright ""
#property link      ""
#property version   "1.00"
#property  indicator_separate_window
#property  indicator_buffers 1
#property  indicator_plots 1
#property  indicator_color1  Silver
#property  indicator_width1  2

double     MacdBuffer[];
int        handle;

int OnInit()
  {
   SetIndexBuffer(0,MacdBuffer,INDICATOR_DATA);
   PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_HISTOGRAM);
   handle=iMA(NULL,0,26,0,MODE_EMA,PRICE_CLOSE);
   return(0);
}
 
double x[];
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 count = rates_total - prev_calculated;
   Print("count = ", count);
   for(int i = 0; i < ArraySize(x); i++) MacdBuffer[i+count] = x[i];
   ArrayResize(x, rates_total);
  
   double buf[];
   ArrayResize(buf, count);
   CopyBuffer(handle, 0, 0, count, buf);
   for(int i = 0; i < count; i++) MacdBuffer[i] = buf[i];

   for(int i = 0; i < ArraySize(x); i++) x[i] = MacdBuffer[i];
   return(rates_total);
  }

It's the only code in all internet that works to use other indicators to make your own indicator (MT5). This code is gold, but some times it returns "array out of range" in this part:

   for(int i = 0; i < ArraySize(x); i++) MacdBuffer[i+count] = x[i];

MacdBuffer out of range. I am trying to figure out what is the problem but I'm not geting success. Any Sugestions?