Your code is getting the current bar, which is still incomplete and constantly changing the close price. Consider the previous bar instead which has already closed and no longer changes.
Also, show a screenshot of how you you are reading the values on the chart.
There might be also missing ArraySetAsSeries(true) – this way you will be ensured that the index you use is counted as series of bars (so 0 is the current one and 1 is the last closed etc).
Right now, it’s possible that you get the verse first bar in the history – which is of course completely useless.
Perhaps you should read the manual, especially the examples.
How To Ask Questions The Smart Way. (2004)
How To Interpret Answers.
RTFM and STFW: How To Tell You've Seriously Screwed Up.
They all (including iCustom) return a handle (an int). You get that in OnInit. In OnTick/OnCalculate (after the indicator has updated its buffers), you use the handle, shift and count to get the data.
Technical Indicators - Reference on algorithmic/automated trading language for MetaTrader 5
Timeseries and Indicators Access / CopyBuffer - Reference on algorithmic/automated trading language for MetaTrader 5
How to start with MQL5 - General - MQL5 programming forum - Page 3 #22 (2020)
How to start with MQL5 - MetaTrader 5 - General - MQL5 programming forum - Page 7 #61 (2020)
MQL5 for Newbies: Guide to Using Technical Indicators in Expert Advisors - MQL5 Articles (2010)
How to call indicators in MQL5 - MQL5 Articles (2010)
Your code is getting the current bar, which is still incomplete and constantly changing the close price. Consider the previous bar instead which has already closed and no longer changes.
Also, show a screenshot of how you you are reading the values on the chart.
Actually, he is getting the last bar not the current one because he put "1" as "start_pos" parameter in the CopyBuffer function (not "0"), so his code should actually get the value for the last bar.
I have the same problem and I am pretty sure my code is good. Here it is with proof that it is returning incorrect in some cases:
The code - example 1: EMA 20 :
int maHandle; int OnInit(){ maHandle = iMA(_Symbol, PERIOD_D1, 20, 0, MODE_EMA, PRICE_CLOSE); return(INIT_SUCCEEDED); } void OnDeinit(const int reason){ IndicatorRelease(maHandle); } void OnTick(){ if(isNewCandleD1()){ double maArray[]; ArraySetAsSeries(maArray, true); CopyBuffer(maHandle,0,0,2,maArray); double ma = maArray[1]; Print(iTime(_Symbol,PERIOD_D1,1), " : MA: ", ma); } } bool isNewCandleD1(){ bool newCandle = false; static datetime dtBarCurrentD1 = WRONG_VALUE; datetime dtBarPrevious = dtBarCurrentD1; dtBarCurrentD1 = iTime( _Symbol, PERIOD_D1, 0 ); bool bNewBarEvent = ( dtBarCurrentD1 != dtBarPrevious ); if(bNewBarEvent && dtBarPrevious != WRONG_VALUE ){ newCandle = true; } return newCandle; }
In this case the values are correct:
Now let's change the period to 200:
The code - example 2: EMA 200 :
int maHandle; int OnInit(){ maHandle = iMA(_Symbol, PERIOD_D1, 200, 0, MODE_EMA, PRICE_CLOSE); return(INIT_SUCCEEDED); } void OnDeinit(const int reason){ IndicatorRelease(maHandle); } void OnTick(){ if(isNewCandleD1()){ double maArray[]; ArraySetAsSeries(maArray, true); CopyBuffer(maHandle,0,0,2,maArray); double ma = maArray[1]; Print(iTime(_Symbol,PERIOD_D1,1), " : MA: ", ma); } } bool isNewCandleD1(){ bool newCandle = false; static datetime dtBarCurrentD1 = WRONG_VALUE; datetime dtBarPrevious = dtBarCurrentD1; dtBarCurrentD1 = iTime( _Symbol, PERIOD_D1, 0 ); bool bNewBarEvent = ( dtBarCurrentD1 != dtBarPrevious ); if(bNewBarEvent && dtBarPrevious != WRONG_VALUE ){ newCandle = true; } return newCandle; }
In this case the values are incorrect:
So something is certainly not working as expected with the iMA function.

- www.mql5.com
Actually, he is getting the last bar not the current one because he put "1" as "start_pos" parameter in the CopyBuffer function (not "0"), so his code should actually get the value for the last bar.
I have the same problem and I am pretty sure my code is good. Here it is with proof that it is returning incorrect in some cases:
The code - example 1: EMA 20 :
In this case the values are correct:
Now let's change the period to 200:
The code - example 2: EMA 200 :
In this case the values are incorrect:
So something is certainly not working as expected with the iMA function.
void OnTick(){ if(isNewCandleD1()){ double maArray[]; ArraySetAsSeries(maArray, true); CopyBuffer(maHandle,0,0,2,maArray); double ma = maArray[1]; Print(iTime(_Symbol,PERIOD_D1,1), " : MA: ", ma); } }
I didn't see it there. Anyway, it makes more sense to be in the initializer. The condition also depends on iTime to give an accurate result, and this can give an inaccurate shift, you could use CopyTime instead
I didn't see it there. Anyway, it makes more sense to be in the initializer. The condition also depends on iTime to give an accurate result, and this can give an inaccurate shift, you could use CopyTime instead
Re: makes more sense to be in the initializer
I don't think so, especially because I would unnecessarily have to declare the variable as global. Anyways, make no difference from the issue's perspective.
Re: iTime vs. CopyTime
iTime gave the correct time, it's printed in the log and seen in my screenshots too.

- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
When I call an indicator like the simple moving average it's not the same as the line shows on the chart.
Here's my code,
For example here, the Alert shows 131,960 while the line shows 132,073. I already check if the indicator is the same one as the one in the code and I also know it's not an index problem because the value printed is not the one on any af the bar of the chart.