CopyBuffer in MQL5: Read Closed Bars Without Reversing Your Signals

Timeline showing bar 2 copied to static array index 0 and bar 1 to index 1; current bar 0 is excluded.

Technical revision: 1 October 2026 · Educational material

A common MQL5 fault is to read two indicator values correctly, then interpret their array positions backward. Another is to evaluate an unfinished candle while describing the rule as a closed-bar signal. Both faults can change an EA’s entries without producing a compiler error.

First choose the bars

Shift 0 refers to the current, unfinished bar. Shift 1 is the last closed bar; shift 2 is the closed bar before it. A crossing between the two completed bars needs start_pos=1 and count=2.

For a fixed-size array such as double values[2], the older copied value is placed first in physical storage. In this particular read, values[0] is bar 2 and values[1] is bar 1. Do not try to change a static array’s series flag.

Use a numerical test before using a chart

Closed bar Fast EMA Slow EMA Static array index
Bar 2, older 100 101 0
Bar 1, newer 103 102 1

The fast EMA was below the slow EMA and is now above it, so this is an upward crossing. Reversing the indices would interpret the same observations as a downward crossing.

double fast[2],slow[2];
if(CopyBuffer(fast_handle,0,1,2,fast)!=2 ||
   CopyBuffer(slow_handle,0,1,2,slow)!=2) return;

bool crossed_up=(fast[0]<=slow[0] && fast[1]>slow[1]);
bool crossed_down=(fast[0]>=slow[0] && fast[1]<slow[1]);

Require a complete and valid read

This excerpt assumes initialized handles. Check calculation readiness, require the requested copied count, and reject EMPTY_VALUE or non-finite numbers. A positive count of 1 is not enough when your rule requires 2 observations.

When history is not ready, keep the bar eligible for a later tick. After a complete read, commit the new-bar timestamp and apply the explicitly chosen execution policy. The downloadable EA uses one entry attempt per processed bar; it does not continuously retry rejected orders.

Distinguish physical storage from series indexing

Dynamic arrays may use series indexing, which changes logical access direction. The simplest initial example is a small static array with comments naming the bars. If you later change the destination type or series flag, test the mapping again instead of reusing assumptions.

When reading several timeframes, also confirm which completed higher-timeframe bar was available at the decision time. Correct array ordering alone does not eliminate look-ahead bias.

A short verification sequence

  1. Log the opening times of bars 1 and 2 alongside both EMA values.
  2. Check one upward crossing, one downward crossing and one non-crossing numerically.
  3. Confirm that changes to bar 0 cannot alter the already processed signal.
  4. Delay history loading and verify that the new-bar gate does not consume an incomplete read.
  5. Compare logged entries with the same closed values in a visual tester run.

The full example is FtsClosedBarMAEA.mq5. Continue with validation after verifying the signal itself.

Reference: official CopyBuffer documentation.

By Forex Real Trader

You May Also Like