ZigZagExt

This script functions as a visual market trend tracker, specifically designed to identify significant "peaks" and "valleys" in price movement on a trading chart. By filtering out minor market noise, it helps traders visualize the core structure of price action through a series of connected points.

Core Operational Logic

The tool operates using a two-step mathematical process to ensure that only meaningful price movements are displayed:

1. Initial Filtering and Identification The script constantly scans recent price data to find the highest highs and lowest lows within a specific window. It doesn't just mark every single movement; instead, it applies several filters:

  • Magnitude Check: It looks for a minimum level of price movement (the "Deviation") to ensure that small, insignificant fluctuations are ignored.
  • Proximity Check: It uses a "Backstep" logic to ensure that points plotted very close to one another are consolidated, preventing the chart from becoming cluttered with repetitive marks.

2. Dynamic Peak and Valley Refining Once potential high and low points are identified, the script performs a secondary "refining" pass. This is the intelligence of the tool:

  • High Point Validation: If the script finds a new high that is higher than the previously recorded peak, it updates the peak to the new location. Conversely, if it finds a lower point, it ensures the previous high remains the primary reference.
  • Low Point Validation: Similarly, it identifies the deepest lows. If a new low is detected that is deeper than the last one, it prioritizes that new low.
  • Alternating Structure: The logic enforces an alternating pattern between highs and lows. This prevents the indicator from drawing two consecutive "highs" or "lows," ensuring the resulting line correctly represents the "zig-zag" path of the market's direction.

How it Appears on the Chart

The final result is a clean, visual representation of price trends. It maps out the significant turning points where the market shifts from an upward trend to a downward trend (or vice versa). By stripping away the minor "jitter" of the market, it allows users to see the overarching skeletal structure of the price movement, making it easier to identify support levels, resistance areas, and trend reversals.

Miscellaneous
Implements a curve of type %1
9 Views
0 Downloads
0 Favorites
ZigZagExt

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Red
#property indicator_color2 Blue
//---- indicator parameters
extern int ExtDepth=12;
extern int ExtDeviation=5;
extern int ExtBackstep=3;
extern int ExtPeriod=300;
//---- indicator buffers
double ExtMapBuffer[];
double ExtMapBuffer2[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   IndicatorBuffers(2);
//---- drawing settings
   SetIndexStyle(0,DRAW_SECTION);
   SetIndexStyle(1,DRAW_SECTION);
//---- indicator buffers mapping
   SetIndexBuffer(0,ExtMapBuffer);
   SetIndexBuffer(1,ExtMapBuffer2);
   SetIndexEmptyValue(0,0.0);
   SetIndexEmptyValue(1,0.0);
   ArraySetAsSeries(ExtMapBuffer,true);
   ArraySetAsSeries(ExtMapBuffer2,true);
//---- indicator short name
   IndicatorShortName("ZigZag("+ExtDepth+","+ExtDeviation+","+ExtBackstep+")");
//---- initialization done
   return(0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
  {
   int    shift, back,lasthighpos,lastlowpos;
   double val,res;
   double curlow,curhigh,lasthigh,lastlow;   

   int BarsLimit;
   if( ExtPeriod == 0)
      BarsLimit = Bars;
   else
      BarsLimit = MathMin(Bars, ExtPeriod);

   for(shift=BarsLimit-ExtDepth; shift>=0; shift--)
     {
      val=Low[Lowest(NULL,0,MODE_LOW,ExtDepth,shift)];
      if(val==lastlow) val=0.0;
      else 
        { 
         lastlow=val; 
         if((Low[shift]-val)>(ExtDeviation*Point)) val=0.0;
         else
           {
            for(back=1; back<=ExtBackstep; back++)
              {
               res=ExtMapBuffer[shift+back];
               if((res!=0)&&(res>val)) ExtMapBuffer[shift+back]=0.0; 
              }
           }
        } 
      ExtMapBuffer[shift]=val;
      //--- high
      val=High[Highest(NULL,0,MODE_HIGH,ExtDepth,shift)];
      if(val==lasthigh) val=0.0;
      else 
        {
         lasthigh=val;
         if((val-High[shift])>(ExtDeviation*Point)) val=0.0;
         else
           {
            for(back=1; back<=ExtBackstep; back++)
              {
               res=ExtMapBuffer2[shift+back];
               if((res!=0)&&(res<val)) ExtMapBuffer2[shift+back]=0.0; 
              } 
           }
        }
      ExtMapBuffer2[shift]=val;
     }

   // final cutting 
   lasthigh=-1; lasthighpos=-1;
   lastlow=-1;  lastlowpos=-1;
   
   for(shift=BarsLimit-ExtDepth; shift>=0; shift--)
     {
      curlow=ExtMapBuffer[shift];
      curhigh=ExtMapBuffer2[shift];
      if((curlow==0)&&(curhigh==0)) continue;
      //---
      if(curhigh!=0)
        {
         if(lasthigh>0) 
           {
            if(lasthigh<curhigh) ExtMapBuffer2[lasthighpos]=0;
            else ExtMapBuffer2[shift]=0;
           }
         //---
         if(lasthigh<curhigh || lasthigh<0)
           {
            lasthigh=curhigh;
            lasthighpos=shift;
           }
         lastlow=-1;
        }
      //----
      if(curlow!=0)
        {
         if(lastlow>0)
           {
            if(lastlow>curlow) ExtMapBuffer[lastlowpos]=0;
            else ExtMapBuffer[shift]=0;
           }
         //---
         if((curlow<lastlow)||(lastlow<0))
           {
            lastlow=curlow;
            lastlowpos=shift;
           } 
         lasthigh=-1;
        }
     }
/*   for(shift=BarsLimit-1; shift>=0; shift--)
     {
      if(shift>=Bars-ExtDepth) ExtMapBuffer[shift]=0.0;
      else
        {
         res=ExtMapBuffer2[shift];
         if(res!=0.0) ExtMapBuffer[shift]=res;
        }
     }*/
  }

Comments