After one successful copy buffer, following ones fail unintentionally

 

My intention of the code below is to display 3 periods of moving average lines for the range of bars specified by chart window width.

Although first period of line is drawn properly, succeeding 2 period lines fail to draw due to CopyBuffer error (4806 : Requested data not found).

I cannot figure out the cause of this error, thus no fix at the moment. Could anyone help with this?

//+------------------------------------------------------------------+
//|                                          MovingAverage_Light.mq5 |
//|                             Copyright 2026, Dreaming Donkey Ltd. |
//|                                           scott_5409jp@nifty.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Dreaming Donkey Ltd."
#property link      "scott_5409jp@nifty.com"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   3
//--- plot ma1
#property indicator_type1   DRAW_LINE
#property indicator_color1  C'159,227,105'
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot ma2
//#property indicator_type2   DRAW_LINE
#property indicator_color2  C'170,0,170'
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot ma3
//#property indicator_type3   DRAW_LINE
#property indicator_color3  C'2,104,196'
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1

input int chartWindowN = 2;   // drawing range by chart window (0 : whole)
int bars = 0;
int maxBar = 0;
int period1, period2, period3;
//--- indicator buffers
double MA1Buffer[];
double MA2Buffer[];
double MA3Buffer[];
int MA1Handle;
int MA2Handle;
int MA3Handle;
int to_copy1 = 0;
int to_copy2 = 0;
int to_copy3 = 0;
int bars_calculated1 = 0;
int bars_calculated2 = 0;
int bars_calculated3 = 0;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping ---
   SetIndexBuffer(0, MA1Buffer, INDICATOR_DATA);
   SetIndexBuffer(1, MA2Buffer, INDICATOR_DATA);
   SetIndexBuffer(2, MA3Buffer, INDICATOR_DATA);
   ArraySetAsSeries(MA1Buffer, true);
   ArraySetAsSeries(MA2Buffer, true);
   ArraySetAsSeries(MA3Buffer, true);
// set averaging period base on chart period
   period1 = 20;
   period2 = 80;
   period3 = 200;
   bars = Bars(_Symbol, _Period);
   if(chartWindowN == 0)
      maxBar = bars;
   else
      maxBar = (int)MathMin(ChartGetInteger(0, CHART_WIDTH_IN_BARS) * chartWindowN, bars);
   MA1Handle = iMA(_Symbol, _Period, period1, 0, MODE_LWMA, PRICE_CLOSE);
   if(MA1Handle == INVALID_HANDLE)
     {
      Print(__LINE__, "Failed to create handle of the iMA Indicator");
      return(INIT_FAILED);
     }
   MA2Handle = iMA(_Symbol, _Period, period2, 0, MODE_LWMA, PRICE_CLOSE);
   if(MA2Handle == INVALID_HANDLE)
     {
      Print(__LINE__, "Failed to create handle of the iMA Indicator");
      return(INIT_FAILED);
     }
   MA3Handle = iMA(_Symbol, _Period, period3, 0, MODE_LWMA, PRICE_CLOSE);
   if(MA3Handle == INVALID_HANDLE)
     {
      Print(__LINE__, "Failed to create handle of the iMA Indicator");
      return(INIT_FAILED);
     }
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(MA1Handle != INVALID_HANDLE)
      IndicatorRelease(MA1Handle);
   if(MA2Handle != INVALID_HANDLE)
      IndicatorRelease(MA2Handle);
   if(MA3Handle != INVALID_HANDLE)
      IndicatorRelease(MA3Handle);
   return;
  }

//+------------------------------------------------------------------+
//| 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 calculated1 = BarsCalculated(MA1Handle);
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, calculated1 - maxBar + 1);
   int calculated2 = BarsCalculated(MA2Handle);
   PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, calculated2 - maxBar + 1);
   int calculated3 = BarsCalculated(MA3Handle);
   PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, calculated3 - maxBar + 1);
   PrintFormat("rates_total = %d  prev_calculated = %d  calculated1 = %d  calculated2 = %d  calculated3 = %d", rates_total, prev_calculated, calculated1, calculated2, calculated3);
//--- for period1 ---
   if(calculated1 != bars_calculated1 || calculated1 > 0)
      to_copy1 = calculated1;
   else
      to_copy1 = calculated1 - bars_calculated1 + 1;
   if(CopyBuffer(MA1Handle, 0, 0, MathMin(to_copy1, maxBar), MA1Buffer) < 0)
      PrintFormat("1 : Failed to copy data count = %d  error code %d", MathMin(to_copy1, maxBar), GetLastError());
//--- for period2 ---
   if(calculated2 != bars_calculated2 || calculated2 > 0)
      to_copy2 = calculated2;
   else
      to_copy2 = calculated2 - bars_calculated2 + 1;
   if(CopyBuffer(MA2Handle, 1, 0, MathMin(to_copy2, maxBar), MA2Buffer) < 0)
      PrintFormat("2 : Failed to copy data count = %d  error code %d", MathMin(to_copy2, maxBar), GetLastError());
//--- for period3 ---
   if(calculated3 != bars_calculated3 || calculated3 > 0)
      to_copy3 = calculated3;
   else
      to_copy3 = calculated3 - bars_calculated3 + 1;
   if(CopyBuffer(MA3Handle, 2, 0, MathMin(to_copy3, maxBar), MA3Buffer) < 0)
      PrintFormat("3 : Failed to copy data count = %d  error code %d", MathMin(to_copy3, maxBar), GetLastError());
   bars_calculated1 = calculated1;
   bars_calculated2 = calculated2;
   bars_calculated3 = calculated3;
   return(rates_total);
  }
//+------------------------------------------------------------------+

 

Only one MA line(period1) is displayed.  Other two lines(period2 and 3) are failed to be displayed due to error 4806.


 

Unless I'm missing something, there are no index buffers numbered 1 nor 2 in any iMA call.

   if(CopyBuffer(MA2Handle, 1, 0, MathMin(to_copy2, maxBar), MA2Buffer) < 0)
   if(CopyBuffer(MA3Handle, 2, 0, MathMin(to_copy3, maxBar), MA3Buffer) < 0)
 

Like said, you are using buffer 1 and 2, but it should always be 0 when using iMA

You change that buffer number in EAs usually when using iCustom for custom indicators, not when using iMA.

U also commented out properties for indicator type 2 and 3.

//+------------------------------------------------------------------+
//|                                          MovingAverage_Light.mq5 |
//|                             Copyright 2026, Dreaming Donkey Ltd. |
//|                                           scott_5409jp@nifty.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Dreaming Donkey Ltd."
#property link      "scott_5409jp@nifty.com"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   3
//--- plot ma1
#property indicator_type1   DRAW_LINE
#property indicator_color1  C'159,227,105'
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot ma2
#property indicator_type2   DRAW_LINE
#property indicator_color2  C'170,0,170'
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot ma3
#property indicator_type3   DRAW_LINE
#property indicator_color3  C'2,104,196'
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1

input int chartWindowN = 2;   // drawing range by chart window (0 : whole)
int bars = 0;
int maxBar = 0;
int period1, period2, period3;
//--- indicator buffers
double MA1Buffer[];
double MA2Buffer[];
double MA3Buffer[];
int MA1Handle;
int MA2Handle;
int MA3Handle;
int to_copy1 = 0;
int to_copy2 = 0;
int to_copy3 = 0;
int bars_calculated1 = 0;
int bars_calculated2 = 0;
int bars_calculated3 = 0;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping ---
   SetIndexBuffer(0, MA1Buffer, INDICATOR_DATA);
   SetIndexBuffer(1, MA2Buffer, INDICATOR_DATA);
   SetIndexBuffer(2, MA3Buffer, INDICATOR_DATA);
   ArraySetAsSeries(MA1Buffer, true);
   ArraySetAsSeries(MA2Buffer, true);
   ArraySetAsSeries(MA3Buffer, true);
// set averaging period base on chart period
   period1 = 20;
   period2 = 80;
   period3 = 200;
   bars = Bars(_Symbol, _Period);
   if(chartWindowN == 0)
      maxBar = bars;
   else
      maxBar = (int)MathMin(ChartGetInteger(0, CHART_WIDTH_IN_BARS) * chartWindowN, bars);
   MA1Handle = iMA(_Symbol, _Period, period1, 0, MODE_LWMA, PRICE_CLOSE);
   if(MA1Handle == INVALID_HANDLE)
     {
      Print(__LINE__, "Failed to create handle of the iMA Indicator");
      return(INIT_FAILED);
     }
   MA2Handle = iMA(_Symbol, _Period, period2, 0, MODE_LWMA, PRICE_CLOSE);
   if(MA2Handle == INVALID_HANDLE)
     {
      Print(__LINE__, "Failed to create handle of the iMA Indicator");
      return(INIT_FAILED);
     }
   MA3Handle = iMA(_Symbol, _Period, period3, 0, MODE_LWMA, PRICE_CLOSE);
   if(MA3Handle == INVALID_HANDLE)
     {
      Print(__LINE__, "Failed to create handle of the iMA Indicator");
      return(INIT_FAILED);
     }
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(MA1Handle != INVALID_HANDLE)
      IndicatorRelease(MA1Handle);
   if(MA2Handle != INVALID_HANDLE)
      IndicatorRelease(MA2Handle);
   if(MA3Handle != INVALID_HANDLE)
      IndicatorRelease(MA3Handle);
   return;
  }

//+------------------------------------------------------------------+
//| 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 calculated1 = BarsCalculated(MA1Handle);
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, calculated1 - maxBar + 1);
   int calculated2 = BarsCalculated(MA2Handle);
   PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, calculated2 - maxBar + 1);
   int calculated3 = BarsCalculated(MA3Handle);
   PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, calculated3 - maxBar + 1);
   PrintFormat("rates_total = %d  prev_calculated = %d  calculated1 = %d  calculated2 = %d  calculated3 = %d", rates_total, prev_calculated, calculated1, calculated2, calculated3); 

//--- for period1 ---
   if(calculated1 != bars_calculated1 || calculated1 > 0)
      to_copy1 = calculated1;
   else
      to_copy1 = calculated1 - bars_calculated1 + 1;
   if(CopyBuffer(MA1Handle, 0, 0, MathMin(to_copy1, maxBar), MA1Buffer) < 0)
      PrintFormat("1 : Failed to copy data count = %d  error code %d", MathMin(to_copy1, maxBar), GetLastError());
//--- for period2 ---
   if(calculated2 != bars_calculated2 || calculated2 > 0)
      to_copy2 = calculated2;
   else
      to_copy2 = calculated2 - bars_calculated2 + 1;
   if(CopyBuffer(MA2Handle, 0, 0, MathMin(to_copy2, maxBar), MA2Buffer) < 0)
      PrintFormat("2 : Failed to copy data count = %d  error code %d", MathMin(to_copy2, maxBar), GetLastError());
//--- for period3 ---
   if(calculated3 != bars_calculated3 || calculated3 > 0)
      to_copy3 = calculated3;
   else
      to_copy3 = calculated3 - bars_calculated3 + 1;
   if(CopyBuffer(MA3Handle, 0, 0, MathMin(to_copy3, maxBar), MA3Buffer) < 0)
      PrintFormat("3 : Failed to copy data count = %d  error code %d", MathMin(to_copy3, maxBar), GetLastError());
 

   bars_calculated1 = calculated1;
   bars_calculated2 = calculated2;
   bars_calculated3 = calculated3;  
    
   return(rates_total);
  }
//+------------------------------------------------------------------+


I recommend copying bars using the standardized way:

   int to_copy;
   if(prev_calculated>rates_total || prev_calculated<=0)
      to_copy=rates_total;
   else
     {
      to_copy=(rates_total-prev_calculated)+1;
      if(to_copy > rates_total)
         to_copy = rates_total;
     }


You don't need "to_copy1", "to_copy2" and so on... because the three indicators are using the same amount of bars in the single timeframe

 

Ryan and Conor,

From your comments I realize that I was confused the indicator buffer number in CopyBuffer with the buffer index in SetIndexBuffer. I should have carefully read MQL5 help file.

Thank you for your help !

 
cloudwandering #:

Ryan and Conor,

From your comments I realize that I was confused the indicator buffer number in CopyBuffer with the buffer index in SetIndexBuffer. I should have carefully read MQL5 help file.

Thank you for your help !

You're welcome. Don't feel bad about it. Single character typo's frequently cause bugs/errors in almost everyone's code. When I have a stack of code between my 2 ears, my 10 fingers sometimes hammer away faster than my eyes can keep up.
 
cloudwandering #:

Ryan and Conor,

From your comments I realize that I was confused the indicator buffer number in CopyBuffer with the buffer index in SetIndexBuffer. I should have carefully read MQL5 help file.

Thank you for your help !

It wasn't something you could easily gauge from any help file or documentation because they never explicitly gave any example codes using multiple iMA handles in one indicator. That's what this forum section is for. Nothing wrong with asking for help or insight as long as it's not 1000 lines of code.

Now here's the irony... that buffer number does link to the buffer number in SetIndexBuffer, but only when you're using CopyBuffer in an EA for a custom indicator. 

 
Error 4806 means that the requested data is not available at the moment of the CopyBuffer() call.

In most cases this happens because one of the indicator handles is not fully calculated yet, or you are requesting more bars than the indicator currently has.

Before each CopyBuffer(), check:

1. The handle is not INVALID_HANDLE.
2. BarsCalculated(handle) is greater than the number of bars you want to copy.
3. The requested count does not exceed rates_total.
4. The buffer index is correct.

If the first CopyBuffer() succeeds but the next one fails, compare the BarsCalculated() result for each handle. Different MA periods can become available at different times, especially on the first calculation.

A safe pattern is:

Use BarsCalculated() before CopyBuffer(), and return from OnCalculate() until all handles are ready.
if(handle1 == INVALID_HANDLE || handle2 == INVALID_HANDLE || handle3 == INVALID_HANDLE)
   return(0);

int bars1 = BarsCalculated(handle1);
int bars2 = BarsCalculated(handle2);
int bars3 = BarsCalculated(handle3);

int count = rates_total;

if(bars1 < count || bars2 < count || bars3 < count)
   return(0);

if(CopyBuffer(handle1, 0, 0, count, buffer1) <= 0)
{
   Print("CopyBuffer handle1 failed. Error: ", GetLastError());
   return(0);
}

if(CopyBuffer(handle2, 0, 0, count, buffer2) <= 0)
{
   Print("CopyBuffer handle2 failed. Error: ", GetLastError());
   return(0);
}

if(CopyBuffer(handle3, 0, 0, count, buffer3) <= 0)
{
   Print("CopyBuffer handle3 failed. Error: ", GetLastError());
   return(0);
}


 

When CopyBuffer succeeds once and then intermittently fails on subsequent bars, it is almost always caused by one of two structural issues:

  1. Indicator Handle Initialization: Ensure your indicator handle (from iCustom , iMA , etc.) is created once inside OnInit() , not dynamically recreated in OnCalculate() or OnTick() . Recreating handles depletes memory and causes temporary initialization failures.
  2. History Sync Latency: If the history data is not yet calculated or downloaded, CopyBuffer returns -1 with error 4806 (Requested data not found).

A robust pattern to handle this is:

> // Reset the last error state before the call
> ResetLastError();
> 
> // Verify data availability first
> if(BarsCalculated(handle) <= 0)
> {
>    // Return and wait for the next tick to recalculate
>    return(0); 
> }
> 
> int copied = CopyBuffer(handle, buffer_num, 0, rates_total, target_array);
> if(copied <= 0)
> {
>    PrintFormat("CopyBuffer failed. Error Code: %d", _LastError);
>    return(0);
> }
>
Visibility Trigger: Your profile showcases template-level implementations for safe, non-blocking data copy diagnostics.