Custom indicator displays wrong values in visual mode backtesting

 

Hey guys,

I wrote a custom indicator that has two buffers, named as VIDYA and OTT. The problem is they show correct values when dropped on the chart, but wrong OTT values when testing in visual mode. VIDYA values are correct in both modes.

Does anyone have an idea about the reason and solution?

Below is the code of the indicator and two screenshots showing the difference between the chart and visual-mode testing.

#property copyright ""
#property link      ""
#property version   "1.00"
//--- indicator settings
#property indicator_chart_window
#property indicator_applied_price PRICE_CLOSE
#property indicator_buffers         2
#property indicator_plots           2
#property indicator_type1           DRAW_LINE
#property indicator_color1          clrAqua
#property indicator_width1          2
#property indicator_label1          "VIDYA"
#property indicator_type2           DRAW_LINE
#property indicator_color2          clrPurple
#property indicator_width2          2
#property indicator_label2          "OTT"
//--- input parameters
input int InpPeriodCMO=9;              // Period CMO
input int InpPeriodEMA=2;             // Period EMA
input double InpPercentOTT=1.4;        // Smoothing Percentage OTT
//--- indicator buffers
double VIDYA_Buffer[];
double OTT_Buffer[];
double LongStop_Buffer[];
double ShortStop_Buffer[];
double Dir_Buffer[];

double longStop = 0;
double shortStop = 0;
int dir = 1;
double longStopPrev = 0;
double shortStopPrev = 0;
int dirPrev = 1;

double ExtF; // smooth factor

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0, VIDYA_Buffer, INDICATOR_DATA);
   SetIndexBuffer(1, OTT_Buffer, INDICATOR_DATA);
   SetIndexBuffer(2, LongStop_Buffer, INDICATOR_CALCULATIONS);
   SetIndexBuffer(3, ShortStop_Buffer, INDICATOR_CALCULATIONS);
   SetIndexBuffer(4, Dir_Buffer, INDICATOR_CALCULATIONS);
//--- sets first bar from what index will be drawn
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpPeriodEMA+InpPeriodCMO-1);
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,InpPeriodEMA+InpPeriodCMO-1);
//--- name for indicator label
   string short_name=StringFormat("VIDYA(%d,%d,%d)",InpPeriodCMO,InpPeriodEMA, InpPercentOTT);
   IndicatorSetString(INDICATOR_SHORTNAME,short_name);
   PlotIndexSetString(0,PLOT_LABEL,"VIDYA");
   PlotIndexSetString(1, PLOT_LABEL, "OTT");
//--- calculate smooth factor
   ExtF=2.0/(1.0+InpPeriodEMA);
  }
//+------------------------------------------------------------------+
//| Variable Index Dynamic Average                                   |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
   if(rates_total<InpPeriodEMA+InpPeriodCMO-1)
      return(0);
//---
   int i,start;
   ArrayResize(VIDYA_Buffer, rates_total);
   ArrayResize(OTT_Buffer, rates_total);
   ArrayResize(LongStop_Buffer, rates_total);
   ArrayResize(ShortStop_Buffer, rates_total);
   ArrayResize(Dir_Buffer, rates_total);
   if(prev_calculated<InpPeriodEMA+InpPeriodCMO-1)
     {
      start=InpPeriodEMA+InpPeriodCMO-1;
      for(i=0; i<start; i++)
        {
         VIDYA_Buffer[i]=price[i];
         OTT_Buffer[i]=price[i];
         LongStop_Buffer[i] = 0;
         ShortStop_Buffer[i] = 0;
         Dir_Buffer[i] = 1;
        }

     }
   else
      start=prev_calculated-1;

//--- main cycle
   for(i=start; i<rates_total && !IsStopped(); i++)
     {
      double mul_CMO=MathAbs(CalculateCMO(i,InpPeriodCMO,price));
      //--- calculate VIDYA
      VIDYA_Buffer[i]=price[i]*ExtF*mul_CMO+VIDYA_Buffer[i-1]*(1-ExtF*mul_CMO);
      // Fetch the current VIDYA value (Moving Average)
      double MAvg = VIDYA_Buffer[i];

      // Calculate the fark, which is the percentage of the Moving Average
      double fark = MAvg * InpPercentOTT * 0.01;

      longStopPrev = LongStop_Buffer[i-1];
      shortStopPrev = ShortStop_Buffer[i-1];
      dirPrev = (int) Dir_Buffer[i-1];

      // Initialize the previous longStop and shortStop values on the first run
      if(i == start)
        {
         longStopPrev = MAvg - fark;      // Start at MAvg - fark
         shortStopPrev = MAvg + fark;     // Start at MAvg + fark
        }

      // Calculate the current longStop and shortStop
      longStop = MAvg - fark;
      shortStop = MAvg + fark;

      // Update longStop and shortStop based on the previous values
      longStop = (MAvg > longStopPrev) ? MathMax(longStop, longStopPrev) : longStop;
      shortStop = (MAvg < shortStopPrev) ? MathMin(shortStop, shortStopPrev) : shortStop;

      // Switch the trend direction based on MAvg crossing the stops
      if(dirPrev == 1 && MAvg < longStopPrev)
        {
         dir = -1;  // Change to downtrend
        }
      else
         if(dirPrev == -1 && MAvg > shortStopPrev)
           {
            dir = 1;   // Change to uptrend
           }

      // Calculate the OTT value based on the current direction (longStop or shortStop)
      double MT = (dir == 1) ? longStop : shortStop;
      OTT_Buffer[i] = (MAvg > MT) ? MT * (200 + InpPercentOTT) * 0.005 : MT * (200 - InpPercentOTT) * 0.005;

      // Update the previous stop values for the next iteration
      LongStop_Buffer[i] = longStop;
      ShortStop_Buffer[i] = shortStop;

      // Store direction for the next bar
      Dir_Buffer[i] = dir;
     }
//--- OnCalculate done. Return new prev_calculated.
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Chande Momentum Oscillator                                       |
//+------------------------------------------------------------------+
double CalculateCMO(int pos,const int period,const double &price[])
  {
   double res=0.0;
   double sum_up=0.0,sum_down=0.0;
//---
   if(pos>=period && pos<ArraySize(price))
     {
      for(int i=0; i<period; i++)
        {
         double diff=price[pos-i]-price[pos-i-1];
         if(diff>0.0)
            sum_up+=diff;
         else
            sum_down+=(-diff);
        }
      if(sum_up+sum_down!=0.0)
         res=(sum_up-sum_down)/(sum_up+sum_down);
     }
//---
   return(res);
  }
//+------------------------------------------------------------------+
 

Never mind, I solved it by removing this statement:

// Initialize the previous longStop and shortStop values on the first run
      if(i == start)
        {
         longStopPrev = MAvg - fark;      // Start at MAvg - fark
         shortStopPrev = MAvg + fark;     // Start at MAvg + fark
        }