Complete MQL5 guide & code

MQL5 Close Array in Expert Advisor: CopyRates & CopyClose Guide

Learn how to read close prices, MqlRates, and historical bars in MQL5 Expert Advisors using CopyRates, CopyClose, and ArraySetAsSeries without MT4 array errors.

What this MQL5 guide covers

In MQL5 Expert Advisors, predefined MT4 arrays like Close[] and Open[] do not exist and trigger compiler errors if referenced directly.

Use CopyClose() to copy bar close values into a dynamic double array, or CopyRates() to copy full MqlRates structures with open, high, low, close, time, and tick volume.

Always set target arrays to time series order with ArraySetAsSeries(arr, true) so that index 0 is the current developing bar and index 1 is the previous closed bar.

Single bar lookups can use iClose(_Symbol, _Period, shift), while multi-bar loops benefit from copying arrays in one call.

Why Close[] Is Undeclared in MQL5 Expert Advisors

Developers transitioning from MetaTrader 4 often expect predefined time series arrays such as Close[], Open[], High[], Low[], and Time[] to be globally accessible. In MQL5, those arrays are not available inside Expert Advisors or Scripts.

Writing code like double prev = Close[1]; in an MQL5 EA results in the compiler error: Close - undeclared identifier. MQL5 separates chart data access into explicit copy functions to support multi-currency backtesting and async history management.

  • Close[], Open[], High[], Low[] exist only in custom indicators via the OnCalculate entry point.
  • Expert Advisors must explicitly fetch bars into local arrays using CopyClose() or CopyRates().
  • Single value queries can use iClose(), iOpen(), iHigh(), iLow(), and iTime() helpers.

CopyClose and CopyRates Function Signatures

MQL5 provides two primary functions for reading price history into arrays. CopyClose copies only close prices into a double array. CopyRates copies complete bar data into an array of MqlRates structures.

Both functions accept three parameter overloads: copying by start bar position and count, copying by start datetime and count, or copying between two boundary datetimes.

ParameterTypeDescription
symbol_namestringFinancial instrument symbol (e.g. _Symbol or "EURUSD")
timeframeENUM_TIMEFRAMESChart timeframe constant (e.g. _Period or PERIOD_H1)
start_posintStarting bar index (0 = current bar, 1 = previous closed bar)
countintNumber of history bars to copy into target array
rates_array[] / close_array[]MqlRates[] / double[]Target dynamic array receiving historical price records

The MqlRates Structure and Field Reference

When calling CopyRates, MQL5 fills an array of MqlRates structures. This structure packs all standard candlestick fields into a single record per bar.

Struct MemberTypeField Description
timedatetimePeriod start time for the bar
opendoubleOpen price of the candle
highdoubleHighest price reached during the period
lowdoubleLowest price reached during the period
closedoubleClose price of the candle
tick_volumelongTick volume count recorded on the bar
spreadintSpread in points recorded for the bar
real_volumelongReal volume recorded on exchange instruments

Array Indexing Direction: ArraySetAsSeries

By default, dynamic arrays in MQL5 use standard ascending indices where index 0 holds the oldest bar copied. In trading algorithms, referencing index 0 as the newest bar is far more intuitive.

Calling ArraySetAsSeries(arr, true) flips array indexing to time series order. Under time series indexing, arr[0] represents the current forming candle, arr[1] is the last completed candle, and arr[2] is two bars ago.

Performance: CopyRates vs iClose

The helper function iClose(_Symbol, _Period, shift) returns a single close price as a double. It is convenient for one-off condition checks, such as verifying whether yesterday closed above a benchmark level.

When your strategy inspects 10, 50, or 200 bars in a loop (for example, checking a rolling pivot or swing high), calling iClose repeatedly introduces individual lookup overhead. Calling CopyClose or CopyRates once retrieves all requested bars in a single memory block.

Implementation details & mechanics

Core implementation pattern

Declare dynamic array double closePrices[]. Set time series direction using ArraySetAsSeries(closePrices, true). In OnTick(), copy three bars starting from index 0 using CopyClose(_Symbol, _Period, 0, 3, closePrices). Confirm that CopyClose returns exactly 3. Evaluate completed bar closePrices[1] against moving averages or breakout levels to generate long entry signals.

Error handling & safety rules

For position exit checks and trailing stops, read closePrices[1] to avoid reacting to unfinished candle fluctuations. Dynamic arrays allocated locally or cleaned up with ArrayFree release memory immediately upon deinitialization.

MQL5 Code Implementation Code

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

//--- Input parameters
input int    InpHistoryBars = 5;       // Number of bars to inspect
input double InpPriceOffset = 0.0010;  // Offset threshold for entry check

//--- Dynamic storage for price data
MqlRates g_rates[];
double   g_closePrices[];

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   // Set both arrays as time series (Index 0 = current bar, Index 1 = closed bar)
   ArraySetAsSeries(g_rates, true);
   ArraySetAsSeries(g_closePrices, true);

   Print("Price series reader initialized. ArraySetAsSeries enabled.");
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ArrayFree(g_rates);
   ArrayFree(g_closePrices);
   PrintFormat("Price series arrays released. Reason code: %d", reason);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // Method 1: Using CopyClose to extract close[] array
   int copiedCloses = CopyClose(_Symbol, _Period, 0, InpHistoryBars, g_closePrices);
   if(copiedCloses < InpHistoryBars)
     {
      PrintFormat("CopyClose failed! Copied %d of %d requested bars. Error: %d",
                  copiedCloses, InpHistoryBars, GetLastError());
      return;
     }

   // Method 2: Using CopyRates for complete candle metrics
   int copiedRates = CopyRates(_Symbol, _Period, 0, InpHistoryBars, g_rates);
   if(copiedRates < InpHistoryBars)
     {
      PrintFormat("CopyRates failed! Copied %d of %d requested bars. Error: %d",
                  copiedRates, InpHistoryBars, GetLastError());
      return;
     }

   // Inspect bar 1 (last closed candle) to avoid intra-bar repaint
   double lastClose = g_closePrices[1];
   double lastOpen  = g_rates[1].open;
   double lastHigh  = g_rates[1].high;
   double lastLow   = g_rates[1].low;
   datetime barTime = g_rates[1].time;

   PrintFormat("Bar [1] (%s) -> O: %.5f | H: %.5f | L: %.5f | C: %.5f | Vol: %I64d",
               TimeToString(barTime, TIME_DATE|TIME_MINUTES),
               lastOpen, lastHigh, lastLow, lastClose, g_rates[1].tick_volume);

   // Simple signal evaluation based on price series
   bool isBullishClose = (lastClose > lastOpen);
   bool isHigherClose  = (g_closePrices[1] > g_closePrices[2]);

   if(isBullishClose && isHigherClose)
     {
      // Valid bullish continuation pattern identified
     }
  }

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.