More CopyBuffer woes: SetIndexBuffer(etc.) is inconsistent, CopyBuffer behaves differently

 

Completely flummoxed now. I hope someone can help.

I'll put the code and test results below, but in a nutshell, I've got 2 arrays declared exactly the same way:

double                   MABuffer[];
int                      ma_handle;
double                   DMABuffer[];
int                      Dma_handle;

At the top of OnInit, before doing anything with them, both show to be dynamic arrays:

(Don't know why so fuzzy, it clears up if you click on the image.)

test results 1

Then I set both as indicator buffers in exactly the same way:

   bool bMABfrSet = SetIndexBuffer(0,MABuffer,INDICATOR_DATA);

   bool bDMABfrSet = SetIndexBuffer(1,DMABuffer,INDICATOR_DATA);

... with the result that the SetIndexBuffer for DMABuffer fails, and so it remains dynamic. I have problems with it further down in the code, but I'm guessing they all start here.


What the heck?

Ideas?

Here's the whole thing:

//+------------------------------------------------------------------+
//|                                              TestCopyBuffer3.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
 
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//---- plot MA
#property indicator_label1  "MA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input bool               AsSeries=false;
input int                MA_period=5;
input ENUM_MA_METHOD     smootMode=MODE_EMA;
input ENUM_APPLIED_PRICE price=PRICE_CLOSE;
input int                shift=0;
//--- indicator buffers
double                   MABuffer[];
int                      ma_handle;
double                   DMABuffer[];
int                      Dma_handle;
string                   sDMALcn = "Demo_iMA";
ENUM_TIMEFRAMES          etThsTF = PERIOD_CURRENT;
//string                   sDMALcn = "My MT5 Indicators\\Demo_iMA ASSERIES MJM";

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   Print("["+__FILE__+"/"+__FUNCTION__+"] LINE "+(string)__LINE__+" MS: "+(string)GetMicrosecondCount()+" - TOP of OnInit: ",
      "EnumToString(PERIOD_CURRENT)<",EnumToString(etThsTF),">");
//--- indicator buffers mapping
   bool bMABfrSet = SetIndexBuffer(0,MABuffer,INDICATOR_DATA);
   Print("["+__FILE__+"/"+__FUNCTION__+"] LINE "+(string)__LINE__+" MS: "+(string)GetMicrosecondCount()+" - in OnInit: ",
      "Indicator buffer MABuffer after SetIndexBuffer() is a timeseries = ",
         ArrayGetAsSeries(MABuffer));
//--- set shift
   PlotIndexSetInteger(0,PLOT_SHIFT,shift);   
   
   bool bDMABfrSet = SetIndexBuffer(1,DMABuffer,INDICATOR_DATA);
   Print("["+__FILE__+"/"+__FUNCTION__+"] LINE "+(string)__LINE__+" MS: "+(string)GetMicrosecondCount()+" - in OnInit: ",
      "Indicator buffer DMABuffer after SetIndexBuffer() is a timeseries = ",
         ArrayGetAsSeries(DMABuffer));
//--- set shift
   PlotIndexSetInteger(1,PLOT_SHIFT,shift);   
   
//--- set short indicator name
   IndicatorSetString(INDICATOR_SHORTNAME,"MA("+MA_period+")"+AsSeries);
//--- set AsSeries (depends on input parameter AsSeries, default=false)
   ArraySetAsSeries(MABuffer,AsSeries);
   ArraySetAsSeries(DMABuffer,AsSeries);
   Print("["+__FILE__+"/"+__FUNCTION__+"] LINE "+(string)__LINE__+" MS: "+(string)GetMicrosecondCount()+" - in OnInit: ",
         "Indicator buffer after MABuffer ArraySetAsSeries(MABuffer,",AsSeries,") is a timeseries = ",
         ArrayGetAsSeries(MABuffer));
   Print("["+__FILE__+"/"+__FUNCTION__+"] LINE "+(string)__LINE__+" MS: "+(string)GetMicrosecondCount()+" - in OnInit: ",
         "Indicator buffer after DMABuffer ArraySetAsSeries(DMABuffer,",AsSeries,") is a timeseries = ",
         ArrayGetAsSeries(DMABuffer));
////---
   ma_handle=iMA(_Symbol,etThsTF,MA_period,shift,smootMode,price);
//--- if the handle is not created
   if(ma_handle==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",
                  _Symbol,
                  EnumToString(etThsTF),
                  GetLastError());
      //--- the indicator is stopped early
      return(INIT_FAILED);
     }
   Dma_handle=iCustom(_Symbol,etThsTF,sDMALcn,0,MA_period,shift,smootMode,price,_Symbol,etThsTF);
   if(Dma_handle==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",
                  _Symbol,
                  EnumToString(etThsTF),
                  GetLastError());
      //--- the indicator is stopped early
      return(INIT_FAILED);
     }
   int ii=0;
   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[])
  {
//--- check if all data calculated
   int iMAClcCNT = BarsCalculated(ma_handle);
   if(iMAClcCNT < rates_total) return(rates_total);
   int iDMAClcCNT = BarsCalculated(Dma_handle);
   if(iDMAClcCNT < rates_total) return(rates_total);
//--- we can copy not all data
   int to_copy;
   if(prev_calculated>rates_total || prev_calculated<=0) to_copy=rates_total;
   else
     {
      to_copy=rates_total-prev_calculated;
      //--- last value is always copied
      to_copy++;
     }
//--- try to copy
   if(CopyBuffer(ma_handle,0,0,to_copy,MABuffer)<=0) return(rates_total);
//--- return value of prev_calculated for next call

   if(CopyBuffer(Dma_handle,0,0,to_copy,DMABuffer)<=0) return(rates_total);
//--- return value of prev_calculated for next call

Print("["+__FILE__+"/"+__FUNCTION__+"] LINE "+(string)__LINE__+" MS: "+(string)GetMicrosecondCount()+" - in OnCalculate AFTER CopyBuffer: ",
                                       "ma_handle<",ma_handle,"> ",
                                       "rates_total<",rates_total,"> ",
                                       "prev_calculated<",prev_calculated,"> ",
                                       "to_copy<",to_copy,"> ",
                                       "ArraySize: MABuffer<",ArraySize(MABuffer),">, "
                                       "DMABuffer<",ArraySize(DMABuffer),"> "
                                       
                                       ); 
Print("["+__FILE__+"/"+__FUNCTION__+"] LINE "+(string)__LINE__+" MS: "+(string)GetMicrosecondCount()+" - in OnCalculate AFTER CopyBuffer: ",
      "MABuffer is a timeseries = <",ArrayGetAsSeries(MABuffer),"> DMABuffer is a timeseries = <",ArrayGetAsSeries(DMABuffer),">");
         
   for(int ix=0;ix<10;ix++)
   {
Print("["+__FILE__+"/"+__FUNCTION__+"] LINE "+(string)__LINE__+" MS: "+(string)GetMicrosecondCount()+" - in FOR loop: ",
                                       "ix<",ix,"> ",
                                       "MABuffer[",ix,"]<",MABuffer[ix],"> "
                                       );
                                       
Print("["+__FILE__+"/"+__FUNCTION__+"] LINE "+(string)__LINE__+" MS: "+(string)GetMicrosecondCount()+" - in FOR loop: ",
                                       "ix<",ix,"> ",
                                       "DMABuffer[",ix,"]<",DMABuffer[ix],"> "
                                       ); 
      double dd = MABuffer[ix];
      double ddd = DMABuffer[ix];
   }
   
   int ii = 0;

   return(rates_total);
  }
//+------------------------------------------------------------------+

After the initial pass (prev_calculated == 0), the CopyBuffer statements use a to_copy of 1:

      to_copy=rates_total-prev_calculated;
      //--- last value is always copied
      to_copy++;

which works just find for MABuffer, but leaves DMA_Buffer with an ArraySize of 1. So, of course, I get an index out of range error in the for() loop:

   for(int ix=0;ix<10;ix++)
   {
Print("["+__FILE__+"/"+__FUNCTION__+"] LINE "+(string)__LINE__+" MS: "+(string)GetMicrosecondCount()+" - in FOR loop: ",
                                       "ix<",ix,"> ",
                                       "MABuffer[",ix,"]<",MABuffer[ix],"> "
                                       );
                                       
Print("["+__FILE__+"/"+__FUNCTION__+"] LINE "+(string)__LINE__+" MS: "+(string)GetMicrosecondCount()+" - in FOR loop: ",
                                       "ix<",ix,"> ",
                                       "DMABuffer[",ix,"]<",DMABuffer[ix],"> "
                                       ); 
      double dd = MABuffer[ix];
      double ddd = DMABuffer[ix];
   }

Here's the test run Print output from the Experts tab:

(scroll to the right to see line numbers and data values)

2024.03.19 10:34:12.436 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnInit] LINE 39 MS: 261 - TOP of OnInit: EnumToString(PERIOD_CURRENT)<PERIOD_CURRENT>
2024.03.19 10:34:12.436 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnInit] LINE 49 MS: 273 - in OnInit: Indicator buffer MABuffer after SetIndexBuffer() is a timeseries = false
2024.03.19 10:34:12.436 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnInit] LINE 57 MS: 276 - in OnInit: Indicator buffer after MABuffer ArraySetAsSeries(MABuffer,true); is a timeseries = false
2024.03.19 10:34:12.436 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnInit] LINE 60 MS: 278 - in OnInit: Indicator buffer after DMABuffer ArraySetAsSeries(DMABuffer,true); is a timeseries = false
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 125 MS: 2709 - in OnCalculate AFTER CopyBuffer: ma_handle<10> Dma_handle<11> rates_total<101384> prev_calculated<0> to_copy<101384> ArraySize: MABuffer<101384>, DMABuffer<101384> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 135 MS: 2719 - in OnCalculate AFTER CopyBuffer: MABuffer is a timeseries = <false> DMABuffer is a timeseries = <false>
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 140 MS: 2722 - in FOR loop: ix<0> MABuffer[0]<0.66168> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 145 MS: 2725 - in FOR loop: ix<0> DMABuffer[0]<0.66168> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 140 MS: 2727 - in FOR loop: ix<1> MABuffer[1]<0.6616733333333334> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 145 MS: 2729 - in FOR loop: ix<1> DMABuffer[1]<0.6616733333333334> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 140 MS: 2731 - in FOR loop: ix<2> MABuffer[2]<0.6616755555555557> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 145 MS: 2732 - in FOR loop: ix<2> DMABuffer[2]<0.6616755555555557> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 140 MS: 2734 - in FOR loop: ix<3> MABuffer[3]<0.6616637037037039> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 145 MS: 2736 - in FOR loop: ix<3> DMABuffer[3]<0.6616637037037039> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 140 MS: 2738 - in FOR loop: ix<4> MABuffer[4]<0.6616824691358026> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 145 MS: 2739 - in FOR loop: ix<4> DMABuffer[4]<0.6616824691358026> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 140 MS: 2741 - in FOR loop: ix<5> MABuffer[5]<0.6616649794238685> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 145 MS: 2743 - in FOR loop: ix<5> DMABuffer[5]<0.6616649794238685> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 140 MS: 2744 - in FOR loop: ix<6> MABuffer[6]<0.6616133196159124> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 145 MS: 2746 - in FOR loop: ix<6> DMABuffer[6]<0.6616133196159124> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 140 MS: 2748 - in FOR loop: ix<7> MABuffer[7]<0.6616088797439417> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 145 MS: 2750 - in FOR loop: ix<7> DMABuffer[7]<0.6616088797439417> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 140 MS: 2751 - in FOR loop: ix<8> MABuffer[8]<0.6616459198292944> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 145 MS: 2753 - in FOR loop: ix<8> DMABuffer[8]<0.6616459198292944> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 140 MS: 2755 - in FOR loop: ix<9> MABuffer[9]<0.6616072798861963> 
2024.03.19 10:34:12.439 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 145 MS: 2756 - in FOR loop: ix<9> DMABuffer[9]<0.6616072798861963> 
2024.03.19 10:34:12.461 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 125 MS: 25182 - in OnCalculate AFTER CopyBuffer: ma_handle<10> Dma_handle<11> rates_total<101384> prev_calculated<101384> to_copy<1> ArraySize: MABuffer<101384>, DMABuffer<1> 
2024.03.19 10:34:12.461 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 135 MS: 25195 - in OnCalculate AFTER CopyBuffer: MABuffer is a timeseries = <false> DMABuffer is a timeseries = <false>
2024.03.19 10:34:12.461 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 140 MS: 25198 - in FOR loop: ix<0> MABuffer[0]<0.66168> 
2024.03.19 10:34:12.461 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 145 MS: 25201 - in FOR loop: ix<0> DMABuffer[0]<0.6529349522563693> 
2024.03.19 10:34:12.461 TestCopyBuffer3 CLEAN (AUDUSD,M1)       [TestCopyBuffer3 CLEAN.mq5/OnCalculate] LINE 140 MS: 25203 - in FOR loop: ix<1> MABuffer[1]<0.6616733333333334> 
2024.03.19 10:34:12.461 TestCopyBuffer3 CLEAN (AUDUSD,M1)       array out of range in 'TestCopyBuffer3 CLEAN.mq5' (147,71)

Thanks for your help. I'll be really glad once I've wrapped my mind around this sucker.

 

Duhr. Solved. Face palmed. 

lol

And to think I used to be good at this. In the 90s. 🤣

 
Millard Melnyk #:

Duhr. Solved. Face palmed. 

lol

And to think I used to be good at this. In the 90s. 🤣

jip

Reason: