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 copies indicator values into double arrays. Dynamic arrays can resize; a suitably sized static array is useful when the requested count is known.

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

ArraySetAsSeries changes logical indexing for dynamic one-dimensional arrays. Index 0 is the newest copied sample, which is the current candle only when copying starts at position 0.

Require the requested number of copied values before reading them. A return of -1 indicates an error; inspect the diagnostic instead of assuming every failure means calculation is pending.

CopyBuffer Function Signatures and Overloads

MQL5 indicators store calculated outputs in internal buffers. Indicators on the same symbol can share a thread, so do not assume one independent thread per indicator. 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_numintIndicator-specific buffer index; check that indicator’s documented mapping
start_posintStarting bar position (0 = current bar, 1 = previous closed bar)
countintNumber of elements to copy into the target array
buffer_array[]double[]Target double array receiving the copied values

Array Indexing Direction: ArraySetAsSeries

CopyBuffer stores the oldest copied value first in physical memory, regardless of the array’s series flag. Choose logical indexing deliberately: a normal array reads the oldest sample at index 0; a series array reads the newest copied sample there.

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. Neither direction is universally required.
  • Static or multidimensional arrays cannot use the AS_SERIES flag. Use explicit indices for those arrays.

Common CopyBuffer Pitfalls and Error Handling

Unavailable history or indicator values can require loading or calculation. Error 4806 means requested indicator data was not found; 4807 means an invalid indicator handle and should not be treated as a temporary warm-up condition.

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

This EA initializes configurable MA and RSI handles in OnInit. OnTick copies three samples starting at position 0 into series arrays, checks both counts, then reads index 1 for the completed bar. It logs values and evaluates illustrative conditions; it does not submit orders.

Error handling & safety rules

Release valid handles in OnDeinit. This example has no exit or order-management implementation. It logs on each tick and uses completed values at index 1 because its copy starts at position 0; another starting position requires a different bar-to-index interpretation.

MQL5 Code Implementation

//+------------------------------------------------------------------+
//|                                            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 | MA(%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 generates editable MQL5 source code. Review its logic, request a syntax check, and compile and test the final file in MetaEditor.

Frequently Asked Questions

Related MQL5 pages

Technical references

Risk and testing note

These educational examples require independent compilation and testing. A compile pass or an illustrative setting does not establish execution correctness or profitability. Any reported performance must be supported by reproducible data and test settings; past results do not predict future returns. Trading involves significant risk of loss. This content is not financial advice.