iMA does not return the right value

 

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,


Alert("Symbole : ", _Symbol);
Alert("Timeframe : ", PERIOD_CURRENT);
int handle = iMA(_Symbol, PERIOD_CURRENT, 21, 0, MODE_SMA, MODE_CLOSE);
double ma_arr[];
CopyBuffer(handle, 0, 1, 1, ma_arr);
Alert(ma_arr[0]);

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.

 
iamtitouche: 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.

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.

 
Fernando Carreiro #:

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:

Example 1

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:

Example 2

So something is certainly not working as expected with the iMA function.

Documentation on MQL5: Timeseries and Indicators Access / CopyBuffer
Documentation on MQL5: Timeseries and Indicators Access / CopyBuffer
  • www.mql5.com
Gets data of a specified buffer of a certain indicator in the necessary quantity. Counting of elements of copied data (indicator buffer with the...
 
Imre #:

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.


When copy more then one bar in copybuffer (you are copying 2), then you need to set the buffer to series. That's your problem because you didn't set the ma buffer as series 
 
Conor Mcnamara #:

When copy more then one bar in copybuffer (you are copying 2), then you need to set the buffer to series. That's your problem because you didn't set the ma buffer as series 
He did set the buffer to series.
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);
   }
}
 
MAHA #:
He did set the buffer to series.

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

 
Conor Mcnamara #:

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.