Complete MQL5 guide & code

MQL5 CopyBuffer Function Guide: Indicator Buffers, Handles & EA Examples

Complete guide to the MQL5 CopyBuffer function. Learn how to create technical indicator handles (iMA, iRSI), index arrays as series, read buffer values into Expert Advisors, and handle asynchronous data loading.

What this MQL5 guide covers

CopyBuffer extracts calculated data from indicator buffers into dynamic arrays for Expert Advisors and custom indicators.

Indicator handles must be created once in OnInit() using functions like iMA() or iRSI() and released in OnDeinit() with IndicatorRelease().

Use ArraySetAsSeries(array, true) so that index 0 represents the newest bar (current candle) and index 1 is the most recently closed bar.

Always verify the return value of CopyBuffer(); it returns the number of copied elements, or -1 if the indicator is still calculating.

CopyBuffer Function Signatures and Overloads

In MQL5, technical indicators run in separate threads and store their outputs in internal buffers. The CopyBuffer function bridges indicator computations and Expert Advisors, copying calculated values into user-defined double arrays.

There are three official overloads of CopyBuffer: copying by starting bar index and count, copying by starting datetime and count, and copying between two specific datetime boundaries.

ParameterTypeDescription
indicator_handleintHandle returned by iMA, iRSI, iMACD, or iCustom
buffer_numintBuffer index (0 = main line, 1 = signal line, etc.)
start_posintStarting bar position (0 = current bar, 1 = previous closed bar)
countintNumber of elements to copy into the target array
buffer_array[]double[]Target dynamic array receiving the calculated float values

Array Indexing Direction: ArraySetAsSeries

By default, standard MQL5 dynamic arrays are indexed in chronological order (index 0 is the oldest bar in the array). In algorithmic trading, you almost always want reverse chronological indexing where index 0 is the current developing bar and index 1 is the last completed bar.

Calling ArraySetAsSeries(buffer, true) switches the array to time-series indexing. When copying count=3 bars starting from index 0: buffer[0] is current bar, buffer[1] is 1 bar ago, and buffer[2] is 2 bars ago.

  • ArraySetAsSeries(arr, true): Index 0 = newest copied bar (standard EA convention).
  • ArraySetAsSeries(arr, false): Index 0 = oldest copied bar (standard indicator calculation convention).
  • ArrayFree(arr) or dynamic resizing: CopyBuffer automatically allocates memory for target dynamic arrays.

Common CopyBuffer Pitfalls and Error Handling

Indicators in MetaTrader 5 calculate asynchronously. When an EA starts or switches timeframes, calling CopyBuffer on the very first tick may return -1 with error 4806 (ERR_INDICATOR_DATA_NOT_FOUND) or 4807.

Check BarsCalculated(handle) before reading, or simply test if CopyBuffer() < count. If not enough bars are ready, log a warning and return early from OnTick() until the indicator cache populates.

Implementation details & mechanics

Core implementation pattern

Initialize indicator handles in OnInit() using iMA(_Symbol, _Period, 14, 0, MODE_EMA, PRICE_CLOSE) and iRSI(_Symbol, _Period, 14, PRICE_CLOSE). Set target arrays as series with ArraySetAsSeries(). In OnTick(), copy 2 bars of MA and RSI. Confirm both CopyBuffer calls return exactly 2 elements before evaluating crossover or threshold logic.

Error handling & safety rules

In OnDeinit(const int reason), release all initialized handles using IndicatorRelease(maHandle) and IndicatorRelease(rsiHandle) to prevent memory leaks in terminal memory. When evaluating exits, read the latest closed bar values (index 1) to avoid repaint or unfinished candle fluctuations.

MQL5 Code Implementation Code

//+------------------------------------------------------------------+
//|                                            CopyBufferGuideEA.mq5 |
//|                             Copyright 2026, Pineify Guides Series |
//|                                              https://pineify.app |
//+------------------------------------------------------------------+
#property copyright "Pineify Guides Series"
#property link      "https://pineify.app/mql5/copybuffer-guide"
#property version   "1.00"
#property strict

//--- Input parameters
input group "--- Moving Average ---"
input int               InpMAPeriod   = 20;           // MA Period
input ENUM_MA_METHOD    InpMAMethod   = MODE_EMA;     // MA Method
input ENUM_APPLIED_PRICE InpMAPrice   = PRICE_CLOSE;  // Applied Price

input group "--- RSI Settings ---"
input int               InpRSIPeriod  = 14;           // RSI Period
input ENUM_APPLIED_PRICE InpRSIPrice  = PRICE_CLOSE;  // RSI Applied Price

//--- Indicator handles
int g_maHandle  = INVALID_HANDLE;
int g_rsiHandle = INVALID_HANDLE;

//--- Data buffers
double g_maBuffer[];
double g_rsiBuffer[];

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   // 1. Create Moving Average handle
   g_maHandle = iMA(_Symbol, _Period, InpMAPeriod, 0, InpMAMethod, InpMAPrice);
   if(g_maHandle == INVALID_HANDLE)
     {
      Print("Error creating iMA handle: ", GetLastError());
      return(INIT_FAILED);
     }

   // 2. Create RSI handle
   g_rsiHandle = iRSI(_Symbol, _Period, InpRSIPeriod, InpRSIPrice);
   if(g_rsiHandle == INVALID_HANDLE)
     {
      Print("Error creating iRSI handle: ", GetLastError());
      return(INIT_FAILED);
     }

   // 3. Configure arrays as time series (Index 0 = current bar, Index 1 = bar 1)
   ArraySetAsSeries(g_maBuffer, true);
   ArraySetAsSeries(g_rsiBuffer, true);

   Print("CopyBufferGuideEA initialized successfully.");
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   // Release indicator handles
   if(g_maHandle != INVALID_HANDLE)
      IndicatorRelease(g_maHandle);

   if(g_rsiHandle != INVALID_HANDLE)
      IndicatorRelease(g_rsiHandle);

   Print("Indicator handles released. Reason: ", reason);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // Verify indicators have calculated enough bars
   if(BarsCalculated(g_maHandle) < InpMAPeriod || BarsCalculated(g_rsiHandle) < InpRSIPeriod)
     {
      Print("Indicator calculation pending...");
      return;
     }

   // Copy 3 bars of MA: buffer 0 (main line), starting from bar 0
   int copiedMA = CopyBuffer(g_maHandle, 0, 0, 3, g_maBuffer);
   if(copiedMA < 3)
     {
      PrintFormat("CopyBuffer failed for MA! Copied %d elements, Error: %d",
                  copiedMA, GetLastError());
      return;
     }

   // Copy 3 bars of RSI: buffer 0 (main line), starting from bar 0
   int copiedRSI = CopyBuffer(g_rsiHandle, 0, 0, 3, g_rsiBuffer);
   if(copiedRSI < 3)
     {
      PrintFormat("CopyBuffer failed for RSI! Copied %d elements, Error: %d",
                  copiedRSI, GetLastError());
      return;
     }

   // Read completed bar values (index 1 = previous closed bar)
   double closedMA  = g_maBuffer[1];
   double closedRSI = g_rsiBuffer[1];
   double closedPrice = iClose(_Symbol, _Period, 1);

   // Print values to Experts log
   PrintFormat("Bar [1] -> Close: %.5f | EMA(%d): %.5f | RSI(%d): %.2f",
               closedPrice, InpMAPeriod, closedMA, InpRSIPeriod, closedRSI);

   // Signal generation example:
   bool isBullish = (closedPrice > closedMA) && (closedRSI > 50.0);
   bool isBearish = (closedPrice < closedMA) && (closedRSI < 50.0);

   if(isBullish)
     {
      // Long entry trigger condition met
     }
  }

Copy this code into MetaEditor, save it in your MQL5 folder (Experts, Scripts, or Include), and compile with F7.

Generate custom MQL5 code with Pineify AI

Describe the trade execution, indicator calculations, risk management, or data processing logic you need. Pineify produces clean, typed MQL5 source code ready to compile in MetaEditor.

Frequently Asked Questions

Related MQL5 pages

Technical references

Risk and testing note

Past performance is not indicative of future results. Backtest statistics are based on historical data and do not guarantee future profits. Trading involves significant risk of loss. This content is for educational purposes only and does not constitute financial advice.