Indicator value retreived by EA code lags 5 minutes behind what shows on the chart

 

Hi all.

I just got my first EA up and running and I am finding that the indicator values lag about 5 minutes behind the values displayed on the chart.

I see a bit of chatter about this. Is this a common thing?

I saw one post that suggested coding a custom indicator. I managed to find the code for one of the indicators I am using and I compiled it and replaced the original copy. That made no difference.

I have managed to find code for the other indicators. Do I need to go as far as implement the indicators within the EA?

How do people deal with this?

 

Now I'm not sure that the values the EA retrieves are lagging behind the chart. I just saw a value for CCI which doesn't even appear on the chart during the displayed times.

I am going to post the code I use to test retrieving the indicator values. I was using iCustom for all 3 indicators, then changed two of them to the standard Indicator functions. No change. I have changed them back to be consistent with using the indicators in the indicator folder.


//+------------------------------------------------------------------+
//|                                              test_indicators.mq5 |
//|                    Copyright 2024, David Waddington.             |
//|                    https://www.mql5.com/en/users/davewaddington  |
//+------------------------------------------------------------------+

#include <Trade\Trade.mqh>       // Standard library for trading operations
#include <Trade\SymbolInfo.mqh>  // Standard library for symbol information
#include <Expert\Money\MoneyFixedRisk.mqh>
#include <Indicators\Oscilators.mqh>
#include <Trade\PositionInfo.mqh>


// Global Input Variables
input int TEMA_Period = 9;        // TEMA period
input int VWAP_Period = 9;       // VWAP bands period
input int CCI_Period = 9;         // CCI period

// Global Indicator values
double TEMA_Value;
double VWAP_Value;
double CCI_Value;

// Global variables to store indicator handles
int TEMA_Handle;
int VWAP_Handle;
int CCI_Handle;

// Global variables to store indicator buffers 
double tema_buffer[], vwap_buffer[], cci_buffer[];


        

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {

         // Get TEMA Handle        
//         TEMA_Handle = iTEMA(Symbol(),0,TEMA_Period,0,PRICE_CLOSE);  
         TEMA_Handle = iCustom(NULL,0,"TEMA",
                                TEMA_Period,          // Period
                                0,                    // Offset
                                MODE_SMA,             // Calculation method
                                PRICE_CLOSE           // Calculating on Close prices
                       );
                       
         if(TEMA_Handle == INVALID_HANDLE)
               {
                       Print("Couldn't load the TEMA indicator.");
                       return INIT_FAILED;
               }

         Print("TEMA_Handle ", TEMA_Handle, " loaded successfully."); // this is not necessary and may reduce the code speed in optimizations, but may help you debugging errors like this sometimes

         // Get VWAP Handle    
         VWAP_Handle = iCustom(NULL,0,"vwap_bands",
                                VWAP_Period,          // Period
                                PRICE_CLOSE,           // Calculating on Close prices
                                0,                    // UseRealVolume
                                0,                    // DeviationSample
                                1.0,                // DeviationMuliplier1
                                2.0,                // DeviationMuliplier2
                                2.5                // DeviationMuliplier3
                       );

         if(VWAP_Handle == INVALID_HANDLE)
               {
                       Print("Couldn't load the VWAP indicator.");
                       return INIT_FAILED;
               }

         Print("VWAP_Handle ", VWAP_Handle, " loaded successfully."); // this is not necessary and may reduce the code speed in optimizations, but may help you debugging errors like this sometimes
   
         // Get CCI Handle    
//         CCI_Handle = iCCI(Symbol(),0,CCI_Period,PRICE_TYPICAL);         
         CCI_Handle = iCustom(NULL,0,"CCI",
                                CCI_Period,           // Period
                                PRICE_TYPICAL         // Calculating on Typical prices
                       ); 

         if(CCI_Handle == INVALID_HANDLE)
               {
                       Print("Couldn't load the CCI indicator.");
                       return INIT_FAILED;
               }

         Print("CCI_Handle ", CCI_Handle, " loaded successfully."); // this is not necessary and may reduce the code speed in optimizations, but may help you debugging errors like this sometimes

         // Setting the indexing in arrays the same as in timeseries, i.e. array element with zero
         // index will store the values of the last bar, with 1th index - the last but one, etc.
         ArraySetAsSeries(tema_buffer, true);
         ArraySetAsSeries(vwap_buffer, true);
         ArraySetAsSeries(cci_buffer, true);
      
         UpdateIndicators();     //Update Indicators
      
         string debugComment = StringFormat("TEMA = %d, VWAP = %d, CCI = %d", TEMA_Value, VWAP_Value, CCI_Value);
         printf(debugComment);
         Comment(debugComment);
                             
         return INIT_SUCCEEDED;
  }
  
  
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{

   UpdateIndicators();     //Update Indicators
 
   string debugComment = StringFormat("TEMA = %.2f, VWAP = %.2f, CCI = %.2f", TEMA_Value, VWAP_Value, CCI_Value);
//   printf(debugComment);
   Comment(debugComment);
   

}

             


void UpdateIndicators()
{

   
   // Using indicators handles, let's copy the values of indicator
   // buffers to arrays, specially prepared for this purpose
      if (CopyBuffer(TEMA_Handle,0,0,1,tema_buffer) < 0){Print("CopyBuffer TEMA error =",GetLastError());}
      if (CopyBuffer(VWAP_Handle,3,0,1,vwap_buffer) < 0){Print("CopyBuffer VWAP error =",GetLastError());}
      if (CopyBuffer(CCI_Handle,0,0,1,cci_buffer) < 0){Print("CopyBuffer CCI error =",GetLastError());}
      
      TEMA_Value = tema_buffer[0];
      VWAP_Value = vwap_buffer[0];
      CCI_Value = cci_buffer[0];
      

}


Here is the code for vwap_bands:

//------------------------------------------------------------------
#property copyright "© mladen, 2016, MetaQuotes Software Corp."
#property link      "www.forex-tsd.com, www.mql5.com"
#property version   "1.00"
//------------------------------------------------------------------
#property indicator_chart_window
#property indicator_buffers 8
#property indicator_plots   7
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrLimeGreen
#property indicator_width1  2
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrLimeGreen
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrLimeGreen
#property indicator_style3  STYLE_DOT
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrSilver
#property indicator_style4  STYLE_DOT
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrSandyBrown
#property indicator_style5  STYLE_DOT
#property indicator_type6   DRAW_LINE
#property indicator_color6  clrSandyBrown
#property indicator_type7   DRAW_LINE
#property indicator_color7  clrSandyBrown
#property indicator_width7  2

//
//
//
//
//

enum enPrices
{
   pr_close,      // Close
   pr_open,       // Open
   pr_high,       // High
   pr_low,        // Low
   pr_median,     // Median
   pr_typical,    // Typical
   pr_weighted,   // Weighted
   pr_average,    // Average (high+low+open+close)/4
   pr_medianb,    // Average median body (open+close)/2
   pr_tbiased,    // Trend biased price
   pr_tbiased2,   // Trend biased (extreme) price
   pr_haclose,    // Heiken ashi close
   pr_haopen ,    // Heiken ashi open
   pr_hahigh,     // Heiken ashi high
   pr_halow,      // Heiken ashi low
   pr_hamedian,   // Heiken ashi median
   pr_hatypical,  // Heiken ashi typical
   pr_haweighted, // Heiken ashi weighted
   pr_haaverage,  // Heiken ashi average
   pr_hamedianb,  // Heiken ashi median body
   pr_hatbiased,  // Heiken ashi trend biased price
   pr_hatbiased2  // Heiken ashi trend biased (extreme) price
};

input int        AvgPeriod           = 20;          // Volume weighted average period
input enPrices   Price               = pr_close;    // Price
input bool       UseRealVolume       = false;       // Use real volume?
input bool       DeviationSample     = false;       // Deviation with sample correction?
input double     DeviationMuliplier1 = 1;           // First band(s) deviation
input double     DeviationMuliplier2 = 2;           // Second band(s) deviation
input double     DeviationMuliplier3 = 2.5;         // Third band(s) deviation

double  bandm[],bandu1[],bandu2[],bandu3[],bandd1[],bandd2[],bandd3[],prices[];

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

void OnInit()
{
   SetIndexBuffer(0,bandu3 ,INDICATOR_DATA);
   SetIndexBuffer(1,bandu2 ,INDICATOR_DATA);
   SetIndexBuffer(2,bandu1 ,INDICATOR_DATA);
   SetIndexBuffer(3,bandm  ,INDICATOR_DATA);
   SetIndexBuffer(4,bandd1 ,INDICATOR_DATA);
   SetIndexBuffer(5,bandd2 ,INDICATOR_DATA);
   SetIndexBuffer(6,bandd3 ,INDICATOR_DATA);
   SetIndexBuffer(7,prices ,INDICATOR_CALCULATIONS);
      IndicatorSetString(INDICATOR_SHORTNAME,"VWAP bands ("+(string)AvgPeriod+")");
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime& time[],
                const double& open[],
                const double& high[],
                const double& low[],
                const double& close[],
                const long& tick_volume[],
                const long& real_volume[],
                const int& spread[])
{
   if (Bars(_Symbol,_Period)<rates_total) return(-1);
   
   //
   //
   //
   //
   //
   
   int i=(int)MathMax(prev_calculated-1,0); for (; i<rates_total && !_StopFlag; i++)
   {
      prices[i] = getPrice(Price,open,close,high,low,i,rates_total);
         double sum1=0,sum2=0, deviation = iDeviation(prices[i],AvgPeriod,DeviationSample,i,rates_total);
                      for (int k=0; k<AvgPeriod && (i-k)>=0; k++)
                      {
                         double volume = (UseRealVolume) ? (double)real_volume[i-k] : (double)tick_volume[i-k];
                            sum1 += volume*prices[i-k];
                                 sum2 += volume;
                      }
                      bandm[i]  = (sum2!=0) ? sum1/sum2 : prices[i]; //PrintFormat("bandm = %.2f", bandm[i]);
                      bandu1[i] = (DeviationMuliplier1>0) ? bandm[i]+DeviationMuliplier1*deviation : EMPTY_VALUE;
                      bandd1[i] = (DeviationMuliplier1>0) ? bandm[i]-DeviationMuliplier1*deviation : EMPTY_VALUE;
                      bandu2[i] = (DeviationMuliplier2>0) ? bandm[i]+DeviationMuliplier2*deviation : EMPTY_VALUE;
                      bandd2[i] = (DeviationMuliplier2>0) ? bandm[i]-DeviationMuliplier2*deviation : EMPTY_VALUE;
                      bandu3[i] = (DeviationMuliplier3>0) ? bandm[i]+DeviationMuliplier3*deviation : EMPTY_VALUE;
                      bandd3[i] = (DeviationMuliplier3>0) ? bandm[i]-DeviationMuliplier3*deviation : EMPTY_VALUE;
   }         
   return(i);
}

//------------------------------------------------------------------
//                                                                  
//------------------------------------------------------------------
// 
//
//
//
//

double workDev[];
double iDeviation(double value, int length, bool isSample, int i, int bars)
{
   if (ArraySize(workDev)!=bars) ArrayResize(workDev,bars); workDev[i] = value;
                 
   //
   //
   //
   //
   //
   
      double oldMean   = value;
      double newMean   = value;
      double squares   = 0; int k;
      for (k=1; k<length && (i-k)>=0; k++)
      {
         newMean  = (workDev[i-k]-oldMean)/(k+1)+oldMean;
         squares += (workDev[i-k]-oldMean)*(workDev[i-k]-newMean);
         oldMean  = newMean;
      }
      return(MathSqrt(squares/MathMax(k-isSample,1)));
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
//

#define _pricesInstances 1
#define _pricesSize      4
double workHa[][_pricesInstances*_pricesSize];
double getPrice(int tprice, const double& open[], const double& close[], const double& high[], const double& low[], int i,int _bars, int instanceNo=0)
{
  if (tprice>=pr_haclose)
   {
      if (ArrayRange(workHa,0)!= _bars) ArrayResize(workHa,_bars); instanceNo*=_pricesSize;
         
         //
         //
         //
         //
         //
         
         double haOpen;
         if (i>0)
                haOpen  = (workHa[i-1][instanceNo+2] + workHa[i-1][instanceNo+3])/2.0;
         else   haOpen  = (open[i]+close[i])/2;
         double haClose = (open[i] + high[i] + low[i] + close[i]) / 4.0;
         double haHigh  = MathMax(high[i], MathMax(haOpen,haClose));
         double haLow   = MathMin(low[i] , MathMin(haOpen,haClose));

         if(haOpen  <haClose) { workHa[i][instanceNo+0] = haLow;  workHa[i][instanceNo+1] = haHigh; } 
         else                 { workHa[i][instanceNo+0] = haHigh; workHa[i][instanceNo+1] = haLow;  } 
                                workHa[i][instanceNo+2] = haOpen;
                                workHa[i][instanceNo+3] = haClose;
         //
         //
         //
         //
         //
         
         switch (tprice)
         {
            case pr_haclose:     return(haClose);
            case pr_haopen:      return(haOpen);
            case pr_hahigh:      return(haHigh);
            case pr_halow:       return(haLow);
            case pr_hamedian:    return((haHigh+haLow)/2.0);
            case pr_hamedianb:   return((haOpen+haClose)/2.0);
            case pr_hatypical:   return((haHigh+haLow+haClose)/3.0);
            case pr_haweighted:  return((haHigh+haLow+haClose+haClose)/4.0);
            case pr_haaverage:   return((haHigh+haLow+haClose+haOpen)/4.0);
            case pr_hatbiased:
               if (haClose>haOpen)
                     return((haHigh+haClose)/2.0);
               else  return((haLow+haClose)/2.0);        
            case pr_hatbiased2:
               if (haClose>haOpen)  return(haHigh);
               if (haClose<haOpen)  return(haLow);
                                    return(haClose);        
         }
   }
   
   //
   //
   //
   //
   //
   
   switch (tprice)
   {
      case pr_close:     return(close[i]);
      case pr_open:      return(open[i]);
      case pr_high:      return(high[i]);
      case pr_low:       return(low[i]);
      case pr_median:    return((high[i]+low[i])/2.0);
      case pr_medianb:   return((open[i]+close[i])/2.0);
      case pr_typical:   return((high[i]+low[i]+close[i])/3.0);
      case pr_weighted:  return((high[i]+low[i]+close[i]+close[i])/4.0);
      case pr_average:   return((high[i]+low[i]+close[i]+open[i])/4.0);
      case pr_tbiased:   
               if (close[i]>open[i])
                     return((high[i]+close[i])/2.0);
               else  return((low[i]+close[i])/2.0);        
      case pr_tbiased2:   
               if (close[i]>open[i]) return(high[i]);
               if (close[i]<open[i]) return(low[i]);
                                     return(close[i]);        
   }
   return(0);
}

I tried putting in some trace to see what values for bandm were being saved:

                      bandm[i]  = (sum2!=0) ? sum1/sum2 : prices[i]; PrintFormat("bandm = %.2f", bandm[i]);

The values were all over the place, from the vicinity of the value the charts shows, down to near 1. 

 

Can you elaborate a little bit more on what do you mean by lagging? I mean, I tested the code (with the built-in CCI and TEMA) and there's no lagging here:



The values from the last bar are being correctly passed to the comment on the top of the chart.


ps: if you want to show more decimal places, change the %.2f in the StringFormat to any number of decimal places you want.

 
Emanuel Cavalcante Amorim Filho #:

Can you elaborate a little bit more on what do you mean by lagging? I mean, I tested the code (with the built-in CCI and TEMA) and there's no lagging here:



The values from the last bar are being correctly passed to the comment on the top of the chart.


ps: if you want to show more decimal places, change the %.2f in the StringFormat to any number of decimal places you want.

Hi Emanuel. Thanks for your help again.

Well, this is odd. I just rebooted and, yes, now when I look it appears the values do seem to match. 

I wasn't too worried about the decimal places because it's just for debugging. Thanks for setting straight on how to handle those values in StringFormat.

Thanks for responding. 

 

Now the values are different again. It's for all three indicators, not just vwap_hands.

I am developing on Linux using Wine. I wonder if that could be producing issues. I have also found other issues. When I place a trade I display the trade parameters in the Experts log, including stop loss and take profit. I found that when I updated SL and TP in the code, they did not show as changed in the trace for some time.

I recently acquired a Windows laptop. I will move to there for development and see if that fixes things. I have a Windows VPS I can  put it on eventually.