ATR in an MT5 EA: handle, CopyBuffer, series order and the bar shift that moves lot size
Posted: Sat Oct 24, 2026 7:58 pm
ATR in an MT5 EA: handle, CopyBuffer, series order and the bar shift that moves lot size
In MT5, iATR does not return a number. It returns a handle, and you read values from it with CopyBuffer. Forgetting a line here can quietly change the stop, and so the lot size.
int h = iATR(_Symbol, PERIOD_M15, 14); // once, in OnInit
double atr[];
ArraySetAsSeries(atr, true);
CopyBuffer(h, 0, 0, 3, atr);
With the series flag set, atr[0] is the forming bar, atr[1] the last closed bar and atr[2] the one before. Without ArraySetAsSeries the array is ordered the other way, so atr[0] is the oldest of the three and atr[2] the newest. The code compiles either way and returns a plausible number.
Worked example. EURUSD, $10,000, risk 1%, stop 1.5 ATR. The closed bar's ATR is 0.00084, so 8.4 pips, and the stop is 12.6 pips. Lots = 100 / (12.6 x 10) = 0.79. If the array was not set as series and the code reads the oldest value, say 0.00079, the stop becomes 11.85 pips and the size 0.84 lots. A 6% error in position size, from an index.
Also use atr[1] for decisions, not atr[0]. The forming bar's ATR changes with every tick, so a sizing rule that reads it will give a different lot size depending on the moment the signal fires.
In MT5, iATR does not return a number. It returns a handle, and you read values from it with CopyBuffer. Forgetting a line here can quietly change the stop, and so the lot size.
int h = iATR(_Symbol, PERIOD_M15, 14); // once, in OnInit
double atr[];
ArraySetAsSeries(atr, true);
CopyBuffer(h, 0, 0, 3, atr);
With the series flag set, atr[0] is the forming bar, atr[1] the last closed bar and atr[2] the one before. Without ArraySetAsSeries the array is ordered the other way, so atr[0] is the oldest of the three and atr[2] the newest. The code compiles either way and returns a plausible number.
Worked example. EURUSD, $10,000, risk 1%, stop 1.5 ATR. The closed bar's ATR is 0.00084, so 8.4 pips, and the stop is 12.6 pips. Lots = 100 / (12.6 x 10) = 0.79. If the array was not set as series and the code reads the oldest value, say 0.00079, the stop becomes 11.85 pips and the size 0.84 lots. A 6% error in position size, from an index.
Also use atr[1] for decisions, not atr[0]. The forming bar's ATR changes with every tick, so a sizing rule that reads it will give a different lot size depending on the moment the signal fires.