MT5 - Issues with a multiple ZigZag indicator based on the Ichimoku Kinko Hyo 5 lines.

 

Hi everyone,

I need some help with my attempt at coding a custom indicator to help me trading using the Ichimoku Kinko Hyo.

The idea is to draw 5 different ZigZag on the chart, all based on the Ichimoku Kinko Hyo.

ZigZag 1 = based on the tenkansen line (range of 9 periods/bars) ; everytime the line changes direction, a new top or bottom is marked, thus the ZigZag is created.
ZigZag 2 = based on the kijunsen line (range of 26 periods/bars)
ZigZag 3 = based on the crossings of tenkansen and kijunsen or Senkou Span A (range of 17 periods/bars)
ZigZag 4 = based on the Senkou Span B (range of 52 periods/bars)
ZigZag 5 = based on the crossings of SSA/SSB (range of 34.5 periods/bars)

I started from the ZigZag indicator example; and tweaked/kept only what I needed to create a ZigZag that would follow the change of direction of the Tenkansen. It seems like I didn't need to keep the whole ZigZag system based on Depth, Deviation and backstep. I kept only the Depth, and deleted everything related to deviation and backstep. It resulted in a ZigZag that was following the change of direction of the Tenkansen as I needed.

From there, I expected to have nothing much to do to plot a second ZigZag that would follow the change of direction of the Kijunsen instead of the Tenkansen; I copy/pasted every integer and oncalculate code from the Tenkan ZigZag and modified it so that the Kijun ZigZag has its own integer, buffers and so on.

Once done, unfortunately, the ZigZag created by my code for the Kijunsen is wrong.

On this picture, you can see the Tenkan ZigZag following the change of direction of the Tenkansen properly:


On the next one, you can see the incorrect Kijun ZigZag with the Kijunsen on which the ZigZag is supposed to be based:

And finally, both ZigZag drawn on the chart:


I played around with my code to try and find out where the issue lied but to no avail. So I came to you all for help. Here is the current code I'm using:

//+------------------------------------------------------------------+
//|                                                       ZigZag.mq5 |
//|                             Copyright 2000-2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots   2
//--- plot ZigZag
#property indicator_label1  "Tenkan ZigZag"
#property indicator_type1   DRAW_SECTION
#property indicator_color1  clrBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

#property indicator_label2  "Kijun ZigZag"
#property indicator_type2   DRAW_SECTION
#property indicator_color2  clrGreen
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2
/*
#property indicator_label3  "Kinko Hyo ZigZag"
#property indicator_type3   DRAW_SECTION
#property indicator_color3  clrNONE
#property indicator_style3  STYLE_SOLID
#property indicator_width3  2

#property indicator_label4  "Sekou Span B ZigZag"
#property indicator_type4  DRAW_SECTION
#property indicator_color4  clrNONE
#property indicator_style4  STYLE_SOLID
#property indicator_width4  2

#property indicator_label5  "Senkou Spans ZigZag"
#property indicator_type5   DRAW_SECTION
#property indicator_color5  clrNONE
#property indicator_style5  STYLE_SOLID
#property indicator_width5  2
*/
//--- input parameters
input int InpTenkan=9;
input int InpKijun=26;
input int InpKHC=17; 
input int InpSSB=52;
input double SSC=34.5;  

//--- indicator buffers
double    ZigZagTenkanBuffer[];      // main buffer
double    HighMapTenkanBuffer[];     // ZigZag high extremes (peaks)
double    LowMapTenkanBuffer[];      // ZigZag low extremes (bottoms)

int       ExtTenkanRecalc=3;         // number of last extremes for recalculation

enum EnTenkanSearchMode
  {
   tenkanExtremum=0, // searching for the first extremum
   tenkanPeak=1,     // searching for the next ZigZag peak
   tenkanBottom=-1   // searching for the next ZigZag bottom
  };
  
//--- indicator buffers
double    ZigZagKijunBuffer[];      // main buffer
double    HighMapKijunBuffer[];     // ZigZag high extremes (peaks)
double    LowMapKijunBuffer[];      // ZigZag low extremes (bottoms)

int       ExtKijunRecalc=3;         // number of last extremes for recalculation

enum EnKijunSearchMode
  {
   kijunExtremum=0, // searching for the first extremum
   kijunPeak=1,     // searching for the next ZigZag peak
   kijunBottom=-1   // searching for the next ZigZag bottom
  };

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- On-Chart Buttons Initialization Init
   ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true);
   
//--- Create button using graphical objects   
       ObjectCreate(0, "TEST", OBJ_BUTTON, 0, 0, 0);
       ObjectSetInteger(0, "TEST", OBJPROP_XDISTANCE, 30);
       ObjectSetInteger(0, "TEST", OBJPROP_YDISTANCE, 580);
       ObjectSetInteger(0, "TEST", OBJPROP_XSIZE, 300);
       ObjectSetInteger(0, "TEST", OBJPROP_YSIZE, 30);
       ObjectSetString(0, "TEST", OBJPROP_TEXT, "TEST");
       ObjectSetInteger(0, "TEST", OBJPROP_BORDER_COLOR, clrBlack);
       ObjectSetInteger(0, "TEST", OBJPROP_COLOR, clrBlack);
       ObjectSetInteger(0, "TEST", OBJPROP_STATE,0);      
//--- On-Chart Button initialization done

//--- indicator buffers mapping
   SetIndexBuffer(0,ZigZagTenkanBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,HighMapTenkanBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,LowMapTenkanBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,ZigZagKijunBuffer,INDICATOR_DATA);
   SetIndexBuffer(4,HighMapKijunBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,LowMapKijunBuffer,INDICATOR_CALCULATIONS);
//--- set short name and digits
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//--- set an empty value
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);
   //PlotIndexSetInteger(0,PLOT_SHIFT,InpTenkan-1);
   //PlotIndexSetInteger(3,PLOT_SHIFT,InpKijun-1);  
  }
//+------------------------------------------------------------------+
//| ZigZag calculation                                               |
//+------------------------------------------------------------------+
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[])
  {
   if(rates_total<100)
      return(0);
      
//--- Calculating the Tenkansen ZigZag
   int startTenkan = 0, extreme_counterTenkan = 0, extreme_searchTenkan = tenkanExtremum;
   int shiftTenkan = 0, backTenkan = 0, last_high_posTenkan = 0, last_low_posTenkan = 0;
   double valTenkan = 0, resTenkan = 0;
   double curlowTenkan = 0, curhighTenkan = 0, last_highTenkan = 0, last_lowTenkan = 0;

//--- searching for high and low extremes
   for(shiftTenkan=startTenkan; shiftTenkan<rates_total && !IsStopped(); shiftTenkan++)
     {
      //--- low
      valTenkan=low[Lowest(low,InpTenkan,shiftTenkan)];
      if(valTenkan==last_lowTenkan)
         valTenkan=0.0;
      if(low[shiftTenkan]==valTenkan)
         LowMapTenkanBuffer[shiftTenkan]=valTenkan;
      else
         LowMapTenkanBuffer[shiftTenkan]=0.0;
      //--- high
      valTenkan=high[Highest(high,InpTenkan,shiftTenkan)];
      if(valTenkan==last_highTenkan)
         valTenkan=0.0;
      if(high[shiftTenkan]==valTenkan)
         HighMapTenkanBuffer[shiftTenkan]=valTenkan;
      else
         HighMapTenkanBuffer[shiftTenkan]=0.0;
     }

//--- final selection of extreme points for ZigZag
   for(shiftTenkan=startTenkan; shiftTenkan<rates_total && !IsStopped(); shiftTenkan++)
     {
      resTenkan=0.0;
      switch(extreme_searchTenkan)
        {
         case tenkanExtremum:
            if(last_lowTenkan==0.0 && last_highTenkan==0.0)
              {
               if(HighMapTenkanBuffer[shiftTenkan]!=0)
                 {
                  last_highTenkan=high[shiftTenkan];
                  last_high_posTenkan=shiftTenkan;
                  extreme_searchTenkan=tenkanBottom;
                  ZigZagTenkanBuffer[shiftTenkan]=last_highTenkan;
                  resTenkan=1;
                 }
               if(LowMapTenkanBuffer[shiftTenkan]!=0.0)
                 {
                  last_lowTenkan=low[shiftTenkan];
                  last_low_posTenkan=shiftTenkan;
                  extreme_searchTenkan=tenkanPeak;
                  ZigZagTenkanBuffer[shiftTenkan]=last_lowTenkan;
                  resTenkan=1;
                 }
              }
            break;
         case tenkanPeak:
            if(LowMapTenkanBuffer[shiftTenkan]!=0.0 && LowMapTenkanBuffer[shiftTenkan]<last_lowTenkan && HighMapTenkanBuffer[shiftTenkan]==0.0)
              {
               ZigZagTenkanBuffer[last_low_posTenkan]=0.0;
               last_low_posTenkan=shiftTenkan;
               last_lowTenkan=LowMapTenkanBuffer[shiftTenkan];
               ZigZagTenkanBuffer[shiftTenkan]=last_lowTenkan;
               resTenkan=1;
              }
            if(HighMapTenkanBuffer[shiftTenkan]!=0.0 && LowMapTenkanBuffer[shiftTenkan]==0.0)
              {
               last_highTenkan=HighMapTenkanBuffer[shiftTenkan];
               last_high_posTenkan=shiftTenkan;
               ZigZagTenkanBuffer[shiftTenkan]=last_highTenkan;
               extreme_searchTenkan=tenkanBottom;
               resTenkan=1;
              }
            break;
         case tenkanBottom:
            if(HighMapTenkanBuffer[shiftTenkan]!=0.0 && HighMapTenkanBuffer[shiftTenkan]>last_highTenkan && LowMapTenkanBuffer[shiftTenkan]==0.0)
              {
               ZigZagTenkanBuffer[last_high_posTenkan]=0.0;
               last_high_posTenkan=shiftTenkan;
               last_highTenkan=HighMapTenkanBuffer[shiftTenkan];
               ZigZagTenkanBuffer[shiftTenkan]=last_highTenkan;
              }
            if(LowMapTenkanBuffer[shiftTenkan]!=0.0 && HighMapTenkanBuffer[shiftTenkan]==0.0)
              {
               last_lowTenkan=LowMapTenkanBuffer[shiftTenkan];
               last_low_posTenkan=shiftTenkan;
               ZigZagTenkanBuffer[shiftTenkan]=last_lowTenkan;
               extreme_searchTenkan=tenkanPeak;
              }
            break;
         default:
            return(rates_total);
        }
     }


   if(rates_total<100)
      return(0);

//--- Calculating the Kijunsen ZigZag
   int startKijun = 0, extreme_counterKijun = 0, extreme_searchKijun = kijunExtremum;
   int shiftKijun = 0, backKijun = 0, last_high_posKijun = 0, last_low_posKijun = 0;
   double valKijun = 0, resKijun = 0;
   double curlowKijun = 0, curhighKijun = 0, last_highKijun = 0, last_lowKijun = 0;

//--- searching for high and low extremes
   for(shiftKijun=startKijun; shiftKijun<rates_total && !IsStopped(); shiftKijun++)
     {
      //--- low
      valKijun=low[Lowest(low,InpKijun,shiftKijun)];
      if(valKijun==last_lowKijun)
         valKijun=0.0;
      if(low[shiftKijun]==valKijun)
         LowMapKijunBuffer[shiftKijun]=valKijun;
      else
         LowMapKijunBuffer[shiftKijun]=0.0;
      //--- high
      valKijun=high[Highest(high,InpKijun,shiftKijun)];
      if(valKijun==last_highKijun)
         valKijun=0.0;
      if(high[shiftKijun]==valKijun)
         HighMapKijunBuffer[shiftKijun]=valKijun;
      else
         HighMapKijunBuffer[shiftKijun]=0.0;
     }

//--- final selection of extreme points for ZigZag
   for(shiftKijun=startKijun; shiftKijun<rates_total && !IsStopped(); shiftKijun++)
     {
      resKijun=0.0;
      switch(extreme_searchKijun)
        {
         case kijunExtremum:
            if(last_lowKijun==0.0 && last_highKijun==0.0)
              {
               if(HighMapKijunBuffer[shiftKijun]!=0)
                 {
                  last_highKijun=high[shiftKijun];
                  last_high_posKijun=shiftKijun;
                  extreme_searchKijun=kijunBottom;
                  ZigZagKijunBuffer[shiftKijun]=last_highKijun;
                  resKijun=1;
                 }
               if(LowMapKijunBuffer[shiftKijun]!=0.0)
                 {
                  last_lowKijun=low[shiftKijun];
                  last_low_posKijun=shiftKijun;
                  extreme_searchKijun=kijunPeak;
                  ZigZagKijunBuffer[shiftKijun]=last_lowKijun;
                  resKijun=1;
                 }
              }
            break;
         case kijunPeak:
            if(LowMapKijunBuffer[shiftKijun]!=0.0 && LowMapKijunBuffer[shiftKijun]<last_lowKijun && HighMapKijunBuffer[shiftKijun]==0.0)
              {
               ZigZagKijunBuffer[last_low_posKijun]=0.0;
               last_low_posKijun=shiftKijun;
               last_lowKijun=LowMapKijunBuffer[shiftKijun];
               ZigZagKijunBuffer[shiftKijun]=last_lowKijun;
               resKijun=1;
              }
            if(HighMapKijunBuffer[shiftKijun]!=0.0 && LowMapKijunBuffer[shiftKijun]==0.0)
              {
               last_highKijun=HighMapKijunBuffer[shiftKijun];
               last_high_posKijun=shiftKijun;
               ZigZagKijunBuffer[shiftKijun]=last_highKijun;
               extreme_searchKijun=kijunBottom;
               resKijun=1;
              }
            break;
         case kijunBottom:
            if(HighMapKijunBuffer[shiftKijun]!=0.0 && HighMapKijunBuffer[shiftKijun]>last_highKijun && LowMapKijunBuffer[shiftKijun]==0.0)
              {
               ZigZagKijunBuffer[last_high_posKijun]=0.0;
               last_high_posKijun=shiftKijun;
               last_highKijun=HighMapKijunBuffer[shiftKijun];
               ZigZagKijunBuffer[shiftKijun]=last_highKijun;
              }
            if(LowMapKijunBuffer[shiftKijun]!=0.0 && HighMapKijunBuffer[shiftKijun]==0.0)
              {
               last_lowKijun=LowMapKijunBuffer[shiftKijun];
               last_low_posKijun=shiftKijun;
               ZigZagKijunBuffer[shiftKijun]=last_lowKijun;
               extreme_searchKijun=kijunPeak;
              }
            break;
         default:
            return(rates_total);
        }
     }

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|  Search for the index of the highest bar                         |
//+------------------------------------------------------------------+
int Highest(const double &array[],const int depth,const int start)
  {
   if(start<0)
      return(0);

   double max=array[start];
   int    index=start;
//--- start searching
   for(int i=start-1; i>start-depth && i>=0; i--)
     {
      if(array[i]>max)
        {
         index=i;
         max=array[i];
        }
     }
//--- return index of the highest bar
   return(index);
  }
//+------------------------------------------------------------------+
//|  Search for the index of the lowest bar                          |
//+------------------------------------------------------------------+
int Lowest(const double &array[],const int depth,const int start)
  {
   if(start<0)
      return(0);

   double min=array[start];
   int    index=start;
//--- start searching
   for(int i=start-1; i>start-depth && i>=0; i--)
     {
      if(array[i]<min)
        {
         index=i;
         min=array[i];
        }
     }
//--- return index of the lowest bar
   return(index);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---Observes cursor position, Highlight button and detect Click event

    if(id == CHARTEVENT_OBJECT_CLICK && sparam == "TEST")
     {
      if(ObjectGetInteger(ChartID(), "TEST", OBJPROP_STATE, 0) == 1) {

        } else {

      }
    }
  }

Once I manage to get the Kijun ZigZag working, the next step will be to do the same for the 3 other ZigZags, and add buttons on chart to show/hide each zigzag. However, for now, I'm stuck and cannot get that second ZigZag plotting to be populated correctly.

If you have any idea/hypotheses/solutions on this issue, I'll try them all!

Thanks in advance,

basic

 
basicleader:

Hi everyone,

I need some help with my attempt at coding a custom indicator to help me trading using the Ichimoku Kinko Hyo.

The idea is to draw 5 different ZigZag on the chart, all based on the Ichimoku Kinko Hyo.

ZigZag 1 = based on the tenkansen line (range of 9 periods/bars) ; everytime the line changes direction, a new top or bottom is marked, thus the ZigZag is created.
ZigZag 2 = based on the kijunsen line (range of 26 periods/bars)
ZigZag 3 = based on the crossings of tenkansen and kijunsen or Senkou Span A (range of 17 periods/bars)
ZigZag 4 = based on the Senkou Span B (range of 52 periods/bars)
ZigZag 5 = based on the crossings of SSA/SSB (range of 34.5 periods/bars)

I started from the ZigZag indicator example; and tweaked/kept only what I needed to create a ZigZag that would follow the change of direction of the Tenkansen. It seems like I didn't need to keep the whole ZigZag system based on Depth, Deviation and backstep. I kept only the Depth, and deleted everything related to deviation and backstep. It resulted in a ZigZag that was following the change of direction of the Tenkansen as I needed.

From there, I expected to have nothing much to do to plot a second ZigZag that would follow the change of direction of the Kijunsen instead of the Tenkansen; I copy/pasted every integer and oncalculate code from the Tenkan ZigZag and modified it so that the Kijun ZigZag has its own integer, buffers and so on.

Once done, unfortunately, the ZigZag created by my code for the Kijunsen is wrong.

On this picture, you can see the Tenkan ZigZag following the change of direction of the Tenkansen properly:


On the next one, you can see the incorrect Kijun ZigZag with the Kijunsen on which the ZigZag is supposed to be based:

And finally, both ZigZag drawn on the chart:


I played around with my code to try and find out where the issue lied but to no avail. So I came to you all for help. Here is the current code I'm using:

Once I manage to get the Kijun ZigZag working, the next step will be to do the same for the 3 other ZigZags, and add buttons on chart to show/hide each zigzag. However, for now, I'm stuck and cannot get that second ZigZag plotting to be populated correctly.

If you have any idea/hypotheses/solutions on this issue, I'll try them all!

Thanks in advance,

basic

ZigZag algorithm is hard to get your head around. As it seems, your implementation is wrong.

I myself had once a similar issue and it took me almost a week to figure it out. What I did was I took a code that worked and then rewrote my version from scratch again and again until the results matched.

I suggest you find the original implementation and do the same...