Indicator behaves differently in tester

 
I've make a custom indicator, and for some reason the output is different when I am using it in the strategy tester than it is when I just drop it onto a chart.  I'm attaching a screenshot showing the indicator twice in the same window.  The top one is what I got when using the strategy tester (visual mode turned on), and the bottom one is what I see when I stopped the strategy tester and then dropped the indicator onto the chart.  You can see that there are some differences.  Any idea what would cause this?  Happy to provide the code if that helps.
Files:
idicator.jpg  454 kb
 
jt27: what would cause this?
Broken code.
 

Thanks William.  Do you see anything here that would cause an indicator to produce different outputs in the tester than when it is dropped onto a chart?

#property copyright "Copyright 2020, John Turner"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_minimum -1
#property indicator_maximum 1
#property indicator_buffers 5
#property indicator_plots   5
//--- plot tfNow
#property indicator_label1  "tfNow"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDarkTurquoise
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot tfUpOne
#property indicator_label2  "tfUpOne"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrDarkOrange
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot tfUpTwo
#property indicator_label3  "tfUpTwo"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrSpringGreen
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- plot tfUpTwo
#property indicator_label4  "tfMean"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrRed
#property indicator_style4  STYLE_DOT
#property indicator_width4  1
//--- plot tfUpTwo
#property indicator_label5  "slopeUpTwo"
#property indicator_type5   DRAW_HISTOGRAM
#property indicator_color5  clrWhiteSmoke
#property indicator_style5  STYLE_SOLID
#property indicator_width5  1

#include <jtCommonFunctions.mqh>

//--- indicator buffers
double         tfNowBuffer[];
double         tfUpOneBuffer[];
double         tfUpTwoBuffer[];
double         tfMean[];
double         slopeUpTwo[];
//--- Defines and variables

input int trendPeriodNow = 100;
input int trendPeriodOneUp = 100;
input int trendPeriodTwoUp = 20;
input bool iWriteComments = false;

int run;
bool initCalc;

//ENUM_TIMEFRAMES TimeFrame              = PERIOD_CURRENT;
//int             trendPeriod            = 20;
double          TriggerUp              = 0.05; 
double          TriggerDown            = -0.05; 
#define         MaMethod                 19
int             MaPeriod               = 8; 
bool            ColorChangeOnZeroCross = false;
bool            alertsOn               = true;
bool            alertsOnCurrentBar     = false;
bool            alertsMessage          = true;
bool            alertsSound            = false;
bool            alertsEmail            = false;
bool            alertsNotify           = false;
bool            Interpolate            = true;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,tfNowBuffer);
   SetIndexBuffer(1,tfUpOneBuffer);
   SetIndexBuffer(2,tfUpTwoBuffer);
   SetIndexBuffer(3,tfMean);
   SetIndexBuffer(4,slopeUpTwo);
   
   ArraySetAsSeries(tfNowBuffer,true);
   ArraySetAsSeries(tfUpOneBuffer,true);
   ArraySetAsSeries(tfUpTwoBuffer,true);
   ArraySetAsSeries(tfMean,true);
   ArraySetAsSeries(slopeUpTwo,true);
   
   ObjectsDeleteAll();
   
   initCalc = true;
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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 &volume[],
                const int &spread[])
  {
//---
   int i,pos;
   static int limit;
   int barOneUp;
   int barTwoUp;
   datetime baseBarTime;
   double rise;
   double tempSlope;
   
   if((rates_total <= trendPeriodNow) || (rates_total <= trendPeriodOneUp) || (rates_total <= trendPeriodTwoUp))
      return 0; 
        
   //--- initial zero
   if(prev_calculated<1)
   {
      int highestInput = trendPeriodNow;
      if(trendPeriodOneUp > highestInput)
          highestInput = trendPeriodOneUp;
      if(trendPeriodTwoUp > highestInput)
          highestInput = trendPeriodTwoUp;   
      
      for(i=0; i<highestInput; i++)
      {
         tfNowBuffer[i]=EMPTY_VALUE;
         tfUpOneBuffer[i]=EMPTY_VALUE;
         tfUpTwoBuffer[i]=EMPTY_VALUE;
         tfMean[i]=EMPTY_VALUE;
         slopeUpTwo[i]=EMPTY_VALUE;
      }
   }     
   
   //--- starting calculation
   if(prev_calculated>1)
      pos=prev_calculated-1;
   else
      pos=0;
        
   //--- last counted bar will be recounted
   limit=rates_total-prev_calculated;
   if(prev_calculated>0)
      limit++;     
    
   for(i=0; i<limit; i++)   
   //for(i=pos; i<rates_total; i++)
   {
      baseBarTime = iTime(NULL, PERIOD_CURRENT, i);
      
      if(i == 0)
      {
         barOneUp = 0;
         barTwoUp = 0;
      }
      else
      {
         barOneUp = iBarShift(NULL, oneTimeFrameUp(), baseBarTime, false);
         barTwoUp = iBarShift(NULL, twoTimeFramesUp(), baseBarTime, false);
      }
      
      tfNowBuffer[i] = iCustom(NULL, 0, "jtTrendForce", PERIOD_CURRENT, trendPeriodNow, TriggerUp, TriggerDown, MaMethod, MaPeriod, ColorChangeOnZeroCross,
                               alertsOn, alertsOnCurrentBar, alertsMessage, alertsSound, alertsEmail, alertsNotify, Interpolate, 2, i);  
                               
      tfUpOneBuffer[i] = iCustom(NULL, oneTimeFrameUp(), "jtTrendForce", PERIOD_CURRENT, trendPeriodOneUp, TriggerUp, TriggerDown, MaMethod, MaPeriod, ColorChangeOnZeroCross,
                               alertsOn, alertsOnCurrentBar, alertsMessage, alertsSound, alertsEmail, alertsNotify, Interpolate, 2, barOneUp);  

      tfUpTwoBuffer[i] = iCustom(NULL, twoTimeFramesUp(), "jtTrendForce", PERIOD_CURRENT, trendPeriodTwoUp, TriggerUp, TriggerDown, MaMethod, MaPeriod, ColorChangeOnZeroCross,
                               alertsOn, alertsOnCurrentBar, alertsMessage, alertsSound, alertsEmail, alertsNotify, Interpolate, 2, barTwoUp); 
                               
      tfMean[i] = (tfNowBuffer[i] + tfUpOneBuffer[i] + tfUpTwoBuffer[i]) / 3;    
    
   }
   
   run = twoTimeFramesUp() / _Period;
   //if(rates_total <= (run-1))
   //{
   //   return 0;
   //}
   //else
   //{
      for(i=0; i<limit; i++)
      {
         if((i+run-1) < rates_total)
            rise = tfUpTwoBuffer[i] - tfUpTwoBuffer[i+run-1];
         else rise = 0;
         tempSlope = rise / run * 20; 
         
         if(tempSlope > 0.03)
            slopeUpTwo[i] = 0.1;
         else if(tempSlope < -0.03)
            slopeUpTwo[i] = -0.1;
         else slopeUpTwo[i] = 0;
         
      }
   //}
   
   if(iWriteComments)
   {
      jtWriteComment(0, "tfNow = " + tfNowBuffer[i]);
      jtWriteComment(1, "tfUpOne = " + tfUpOneBuffer[i]);
      jtWriteComment(2, "tfUpTwo = " + tfUpTwoBuffer[i]);
      jtWriteComment(3, "tfMean = " + tfMean[i]);
      jtWriteComment(4, "tfSlopeUpTwo = " + slopeUpTwo[i]);
   } 
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
   
  }
//+------------------------------------------------------------------+


//Returns the next time frame up or down
int oneTimeFrameUp(void)
{
   int currentTimeFrame = _Period;
   switch(currentTimeFrame)
   {
      case 1:
         return 5;
         break;
      case 5:
         return 15;
         break;
      case 15:
         return 30;
         break;
      case 30:
         return 60;
         break;
      case 60:
         return 240;
         break;
      case 240:
         return 1440;
         break;
      case 1440:
         return 10080;
         break;
      case 10080:
         return 43200;
         break;
      default:
         return currentTimeFrame;
         break; 
   }
}


int twoTimeFramesUp()
{
   int currentTimeFrame = _Period;

   switch(currentTimeFrame)
   {
      case 1:
         return 15;
         break;
      case 5:
         return 30;
         break;
      case 15:
         return 60;
         break;
      case 30:
         return 240;
         break;
      case 60:
         return 1440;
         break;
      case 240:
         return 10080;
         break;
      case 1440:
         return 43200;
         break;
      default:
         return currentTimeFrame;
         break; 
   }
}
 

On MT4: Unless the current chart is that specific symbol(s)/TF(s) referenced, you must handle 4066/4073 errors before accessing candle/indicator values.
          Download history in MQL4 EA - Forex Calendar - MQL4 programming forum - Page 3 #26 № 4

Reason: