Custom Ichimoku based indicator not updating: Help needed with code

 

Hi,

I am a newbie here.

Situation:

I am trying to code an Ichimoku based custom indicator to provide a buy or sell signal based on:

  1. Tenkan-Kijun crossover
  2. Chikou (26 periods back) crossover with price (26 periods back). If Chikou is not clearly above the high or below the low of the respective candle, it should not generate either a buy or sell signal.
  3. If both the signals are concordant, a buy or sell arrow is generated.

Problem:

The indicator updates normally if I check for the conditions:

 if (TKBias >= 0)

but not if I check for:

 if (TKBias >= 0 && ChikouBias > 0)

and vice versa for the sell conditions, replacing the > with <.

Essentially, new arrows do not appear unless I manually refresh.


However, seems to work okay in the strategy tester.


Request:

Could someone tell me what I am doing wrong so that the indicator stops updating unless refreshed manually if I check for the Chikou Bias? Thank you in advance.


Code inserted inline and also attached.

#property strict

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Green
#property indicator_color2 Red


//--- input parameters
input int TenkanPeriod=9;     // Tenkan-sen
input int KijunPeriod=26;     // Kijun-sen
input int SenkouPeriod=52;    // Senkou Span B
input int ATRPeriod=14;       // ATR Period       
input int ATRDivisor=4;       // ATR Divisor

double BuyBuffer[], SellBuffer[];
int FlagBuy=0, FlagSell=0, FlagZeroBias=0;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
      {
         //---- indicators
         SetIndexStyle(0, DRAW_ARROW, EMPTY, 5);
         SetIndexArrow(0, 233);
         SetIndexBuffer(0, BuyBuffer);
      
         SetIndexStyle(1, DRAW_ARROW, EMPTY, 5);
         SetIndexArrow(1, 234);
         SetIndexBuffer(1, SellBuffer);
         //----
      return(0);
      }


//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
   {
      //---- 
      
      
      //----
      return(0);
   }


//+------------------------------------------------------------------+
//| 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 limit, i;
      
      
      double TKCross=0;
      double TKBias=0, ChikouBias=0;
      double ATRVal=0;
      double TenkanCurr,TenkanPrev,KijunCurr,KijunPrev,ChikouLagCurr,ChikouLagPrev,SenkouALeadCurr,SenkouALeadPrev,SenkouBLeadCurr,SenkouBLeadPrev;
      
      int MaxLookback=MathMax(MathMax(TenkanPeriod,KijunPeriod),MathMax(SenkouPeriod,ATRPeriod));
      int counted_bars=IndicatorCounted();
      //---- check for possible errors
      if(counted_bars<0) return(-1);
      //---- last counted bar will be recounted
      if(counted_bars>0) counted_bars--;

      limit=rates_total-MathMax(MaxLookback,prev_calculated);
   
      for(i = limit-1; i > 0; i--)
         {
            TenkanCurr=iIchimoku(NULL,0,TenkanPeriod,KijunPeriod,SenkouPeriod,MODE_TENKANSEN,i);
            TenkanPrev=iIchimoku(NULL,0,TenkanPeriod,KijunPeriod,SenkouPeriod,MODE_TENKANSEN,i+1);
            KijunCurr=iIchimoku(NULL,0,TenkanPeriod,KijunPeriod,SenkouPeriod,MODE_KIJUNSEN,i);
            KijunPrev=iIchimoku(NULL,0,TenkanPeriod,KijunPeriod,SenkouPeriod,MODE_KIJUNSEN,i+1);
            ChikouLagCurr=iIchimoku(NULL,0,TenkanPeriod,KijunPeriod,SenkouPeriod,MODE_CHIKOUSPAN,i+KijunPeriod);
            ChikouLagPrev=iIchimoku(NULL,0,TenkanPeriod,KijunPeriod,SenkouPeriod,MODE_CHIKOUSPAN,i+KijunPeriod+1);
            SenkouALeadCurr=iIchimoku(NULL,0,TenkanPeriod,KijunPeriod,SenkouPeriod,MODE_SENKOUSPANA,i-KijunPeriod);
            SenkouALeadPrev=iIchimoku(NULL,0,TenkanPeriod,KijunPeriod,SenkouPeriod,MODE_SENKOUSPANA,i-KijunPeriod+1);
            SenkouBLeadCurr=iIchimoku(NULL,0,TenkanPeriod,KijunPeriod,SenkouPeriod,MODE_SENKOUSPANB,i-KijunPeriod);
            SenkouBLeadPrev=iIchimoku(NULL,0,TenkanPeriod,KijunPeriod,SenkouPeriod,MODE_SENKOUSPANB,i-KijunPeriod+1);
            
            //Calculate TK Cross
            TKCross=CalculateTKCross(TenkanPeriod,KijunPeriod,SenkouPeriod,i);
        
            TKBias=TenkanCurr-KijunCurr;
               
            if (TKCross > 0)
               {
                  FlagBuy=0;
                  FlagSell=1;
               }
            else if (TKCross < 0)
               {
                  FlagSell=0;
                  FlagBuy=1;
               }
             
            
            //Calculate Chikou bias
            ChikouBias=CalculateChikouLagPriceBias(TenkanPeriod,KijunPeriod,SenkouPeriod,i);
                         
            
            Print ("Bar: "+IntegerToString(i)
                  +" TK Cross "+DoubleToStr(NormalizeDouble(TKCross,1),1)
                  +" TK Bias "+DoubleToString(NormalizeDouble(TKBias,Digits))
                  +" Chikou Bias("+IntegerToString(i+KijunPeriod)+") "+DoubleToString(NormalizeDouble(ChikouBias,Digits))
                  );
                  
               
            
            ATRVal=iATR(NULL,0,ATRPeriod,i);
            
            
            
            if (TKBias >= 0 && ChikouBias > 0)
               {
                  if (i > 0 && FlagBuy == 0)
                     {
                        BuyBuffer[i] = CalculateArrowPlacement(1,iIchimoku(NULL,0,TenkanPeriod,KijunPeriod,SenkouPeriod,MODE_KIJUNSEN,i),ATRPeriod,0.75,i);
                        FlagBuy=1;
                        FlagSell=0;
                     }
               }
            else if (TKBias <= 0 && ChikouBias < 0)
               {
                  if (i > 0 && FlagSell == 0)
                     {
                        SellBuffer[i] = CalculateArrowPlacement(-1,iIchimoku(NULL,0,TenkanPeriod,KijunPeriod,SenkouPeriod,MODE_KIJUNSEN,i),ATRPeriod,0.75,i);
                        FlagSell=1;
                        FlagBuy=0;
                     }
               } 
         }

      return(rates_total-1);
   }


//--- Calculate TK Cross
double CalculateTKCross(int TenkanPd, int KijunPd, int SenkouPd, int n)
   {
      double TCurr=iIchimoku(NULL,0,TenkanPd,KijunPd,SenkouPd,MODE_TENKANSEN,n);
      double TPrev=iIchimoku(NULL,0,TenkanPd,KijunPd,SenkouPd,MODE_TENKANSEN,n+1);
      double KCurr=iIchimoku(NULL,0,TenkanPd,KijunPd,SenkouPd,MODE_KIJUNSEN,n);
      double KPrev=iIchimoku(NULL,0,TenkanPd,KijunPd,SenkouPd,MODE_KIJUNSEN,n+1);
      
      double TKX=CalculateCross (TCurr,TPrev,KCurr,KPrev);
      
      if (TKX != 0) TKX=(2*TKX+KumoValRelation(KPrev,n+1,TenkanPd,KijunPd,SenkouPd))/3;
      
      return(TKX);
   }

//--- Calculate generic cross
int CalculateCross (double CurrentA, double PreviousA, double CurrentB, double PreviousB)
   {
      int CrossVal=0;
      
      if (CurrentA > CurrentB && PreviousA <= PreviousB) CrossVal=1;
      else if (CurrentA < CurrentB && PreviousA >= PreviousB) CrossVal=-1;
            
      return(CrossVal);
   }


//--- Calculate Chikou-Lagging Price Bias
double CalculateChikouLagPriceBias(int TenkanPd, int KijunPd, int SenkouPd, int n)
   {
      double Chikou_v_Price=0;
      
      double PriceLagHigh=High[n+KijunPd];
      double PriceLagLow=Low[n+KijunPd];
      double ChikouLag=iIchimoku(NULL,0,TenkanPd,KijunPd,SenkouPd,MODE_CHIKOUSPAN,n+KijunPd);
         
      if (ChikouLag >= PriceLagLow && ChikouLag <= PriceLagHigh) Chikou_v_Price=0;
      else if (ChikouLag > PriceLagHigh) Chikou_v_Price=1;
      else if (ChikouLag < PriceLagLow) Chikou_v_Price=-1;
      
      return(Chikou_v_Price);
   }

//--- Calculate position of a generic value in relation to Kumo        |
double KumoValRelation (double Val, int n, int TenkanPd, int KijunPd, int SenkouPd)
   {
      double SenkA, SenkB, KumoTop, KumoBot;
      double Val_v_Kumo=0;
      
      SenkA = iIchimoku(NULL,0,TenkanPd,KijunPd,SenkouPd,MODE_SENKOUSPANA,n);
      SenkB = iIchimoku(NULL,0,TenkanPd,KijunPd,SenkouPd,MODE_SENKOUSPANB,n);
      
      if (SenkA == SenkB)
         {
            KumoTop=SenkB;
            KumoBot=KumoTop;
         }
      else
         {
            KumoTop=MathMax(SenkA,SenkB);
            KumoBot=MathMin(SenkA,SenkB);
         }
         
      if (Val > KumoTop) Val_v_Kumo=1;
      else if (Val < KumoBot) Val_v_Kumo=-1;
      else if ((Val <= KumoTop) && (Val >= KumoBot)) Val_v_Kumo=0;
      
      return (Val_v_Kumo);
   }

//--- Calculate arrow placement
double CalculateArrowPlacement (int Bias, double Baseline, int ATRPd, double ATRMultiplier, int n)
   {
      double ArrowVal=0;
      double ATRVal=iATR(NULL,0,ATRPd,n);
      
      if (Bias > 0) ArrowVal=MathMin(Low[n],Baseline)-ATRVal*ATRMultiplier;
      else if (Bias < 0) ArrowVal=MathMax(High[n],Baseline)+ATRVal*ATRMultiplier;
      
      return(ArrowVal);
   }


Files:
 
i >= 0
 
kypa:

Thanks, kypa.


The reason for 

i > 0

is to keep the indicator non-repainting.


Also, with

i >= 0

I found that the Chikou some of the indicator values were not being calculated.

 

Updating on last not yet completed bar is not repainting. In fact if you don't recalculate your indicators with it you will have repaining.

Chikou not calculating probably has to do with checking Chikou for a past bar, not for the current one. I think it's only the plot which is shifted, not the buffer values.

 
kypa:

Updating on last not yet completed bar is not repainting. In fact if you don't recalculate your indicators with it you will have repaining.

Chikou not calculating probably has to do with checking Chikou for a past bar, not for the current one. I think it's only the plot which is shifted, not the buffer values.


For some reason, it has started updating today without any change to the code.

In any case, the arrows need to appear on the last completed bar (i=1), so I am happy to wait until the function is recalled once the current bar becomes the last bar. Seems to be working fine now.

Thanks again.

Btw, the buffer values for Chikou are shifted by the Kijun period. I did my due diligence by looking 26 bars back for each bar, printing the Chikou values and also looking at the MT4 Ichimoku custom indicator code.