ZigZagClose

Download script
Author: Copyright � 2007, MetaQuotes Software Corp.
ZigZagClose

This script is designed to create a visual "Zigzag" indicator on a trading chart. Its primary purpose is to filter out minor market noise and highlight the significant structural movements of price by identifying major highs and lows.

Core Logic and Functionality

1. Identifying Significant Turning Points The script scans historical price data to find meaningful peaks (highs) and valleys (lows). Rather than marking every tiny price fluctuation, it uses three specific parameters to determine what qualifies as a significant move:

  • Depth: This defines the minimum distance or "strength" a price must move to be considered a new point.
  • Deviation: This acts as a buffer to ensure that small, insignificant wobbles do not trigger a new line.
  • Backstep: This ensures the script looks back at a specific number of candles to verify that a high or low is truly the most prominent point in that local area.

2. Data Filtering and Mapping The logic operates by scanning the market history in reverse. It looks for the highest and lowest closing prices within the "Depth" range. If it finds a price point that meets the required movement criteria, it marks that location as a potential high or low.

  • If a new low is found that is deeper than a previous one, the script "cleans" the data by removing the older, shallower point.
  • The same logic applies to highs: if a higher peak is discovered, it replaces the previous lower one.

3. The "Zigzag" Connection Once the significant high and low points are identified, the script performs a final pass to connect them visually. It treats the market as a series of alternating movements:

  • If the last confirmed point was a Low, the script begins searching for a new High.
  • If the last confirmed point was a High, it looks for a new Low.

When a new, more extreme peak or valley is found that exceeds the previous one, the script updates the drawing. It removes the old, intermediate point and replaces it with the new, more significant one. This creates the characteristic "zigzag" line effect, where only the most important price turns remain visible on your screen.

Summary for the User

In simple terms, this tool acts like a filter for your eyes. It ignores the constant "jitter" of the market and draws a clear path showing the actual trend. By connecting only the major highs and lows, it helps you see the underlying structure of the price action, making it easier to identify overall trends and key support or resistance levels.

Miscellaneous
Implements a curve of type %1
14 Views
0 Downloads
0 Favorites
ZigZagClose
//+------------------------------------------------------------------+
//|                                                       Zigzag.mq4 |
//|                 Copyright © 2005-2007, MetaQuotes Software Corp. |
//|                                       http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net/"

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Red
//---- indicator parameters
extern int ExtDepth=12;
extern int ExtDeviation=5;
extern int ExtBackstep=3;
//---- indicator buffers
double ZigzagBuffer[];
double HighMapBuffer[];
double LowMapBuffer[];
int level=3; // recounting's depth 
bool downloadhistory=false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   IndicatorBuffers(3);
//---- drawing settings
   SetIndexStyle(0,DRAW_SECTION);
//---- indicator buffers mapping
   SetIndexBuffer(0,ZigzagBuffer);
   SetIndexBuffer(1,HighMapBuffer);
   SetIndexBuffer(2,LowMapBuffer);
   SetIndexEmptyValue(0,0.0);

//---- indicator short name
   IndicatorShortName("ZigZag("+ExtDepth+","+ExtDeviation+","+ExtBackstep+")");
//---- initialization done
   return(0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
  {
   int i, counted_bars = IndicatorCounted();
   int limit,counterZ,whatlookfor;
   int shift,back,lasthighpos,lastlowpos;
   double val,res;
   double curlow,curhigh,lasthigh,lastlow;

   if (counted_bars==0 && downloadhistory) // history was downloaded
     {
      ArrayInitialize(ZigzagBuffer,0.0);
      ArrayInitialize(HighMapBuffer,0.0);
      ArrayInitialize(LowMapBuffer,0.0);
     }
   if (counted_bars==0) 
     {
      limit=Bars-ExtDepth;
      downloadhistory=true;
     }
   if (counted_bars>0) 
     {
      while (counterZ<level && i<100)
        {
         res=ZigzagBuffer[i];
         if (res!=0) counterZ++;
         i++;
        }
      i--;
      limit=i;
      if (LowMapBuffer[i]!=0) 
        {
         curlow=LowMapBuffer[i];
         whatlookfor=1;
        }
      else
        {
         curhigh=HighMapBuffer[i];
         whatlookfor=-1;
        }
      for (i=limit-1;i>=0;i--)  
        {
         ZigzagBuffer[i]=0.0;  
         LowMapBuffer[i]=0.0;
         HighMapBuffer[i]=0.0;
        }
     }
      
   for(shift=limit; shift>=0; shift--)
     {
      //## val=Low[iLowest(NULL,0,MODE_LOW,ExtDepth,shift)];
      val=Close[iLowest(NULL,0,MODE_CLOSE,ExtDepth,shift)];
      if(val==lastlow) val=0.0;
      else 
        { 
         lastlow=val; 
         //## if((Low[shift]-val)>(ExtDeviation*Point)) val=0.0;
         if((Close[shift]-val)>(ExtDeviation*Point)) val=0.0;
         else
           {
            for(back=1; back<=ExtBackstep; back++)
              {
               res=LowMapBuffer[shift+back];
               if((res!=0)&&(res>val)) LowMapBuffer[shift+back]=0.0; 
              }
           }
        } 
      //## if (Low[shift]==val) LowMapBuffer[shift]=val; else LowMapBuffer[shift]=0.0;
      if (Close[shift]==val) LowMapBuffer[shift]=val; else LowMapBuffer[shift]=0.0;
      //--- high
      //## val=High[iHighest(NULL,0,MODE_HIGH,ExtDepth,shift)];
      val=Close[iHighest(NULL,0,MODE_CLOSE,ExtDepth,shift)];
      if(val==lasthigh) val=0.0;
      else 
        {
         lasthigh=val;
         //## if((val-High[shift])>(ExtDeviation*Point)) val=0.0;
         if((val-Close[shift])>(ExtDeviation*Point)) val=0.0;
         else
           {
            for(back=1; back<=ExtBackstep; back++)
              {
               res=HighMapBuffer[shift+back];
               if((res!=0)&&(res<val)) HighMapBuffer[shift+back]=0.0; 
              } 
           }
        }
      //## if (High[shift]==val) HighMapBuffer[shift]=val; else HighMapBuffer[shift]=0.0;
      if (Close[shift]==val) HighMapBuffer[shift]=val; else HighMapBuffer[shift]=0.0;
     }

   // final cutting 
   if (whatlookfor==0)
     {
      lastlow=0;
      lasthigh=0;  
     }
   else
     {
      lastlow=curlow;
      lasthigh=curhigh;
     }
   for (shift=limit;shift>=0;shift--)
     {
      res=0.0;
      switch(whatlookfor)
        {
         case 0: // look for peak or lawn 
            if (lastlow==0 && lasthigh==0)
              {
               if (HighMapBuffer[shift]!=0)
                 {
                  //## lasthigh=High[shift];
                  lasthigh=Close[shift];
                  lasthighpos=shift;
                  whatlookfor=-1;
                  ZigzagBuffer[shift]=lasthigh;
                  res=1;
                 }
               if (LowMapBuffer[shift]!=0)
                 {
                  //## lastlow=Low[shift];
                  lastlow=Close[shift];
                  lastlowpos=shift;
                  whatlookfor=1;
                  ZigzagBuffer[shift]=lastlow;
                  res=1;
                 }
              }
             break;  
         case 1: // look for peak
            if (LowMapBuffer[shift]!=0.0 && LowMapBuffer[shift]<lastlow && HighMapBuffer[shift]==0.0)
              {
               ZigzagBuffer[lastlowpos]=0.0;
               lastlowpos=shift;
               lastlow=LowMapBuffer[shift];
               ZigzagBuffer[shift]=lastlow;
               res=1;
              }
            if (HighMapBuffer[shift]!=0.0 && LowMapBuffer[shift]==0.0)
              {
               lasthigh=HighMapBuffer[shift];
               lasthighpos=shift;
               ZigzagBuffer[shift]=lasthigh;
               whatlookfor=-1;
               res=1;
              }   
            break;               
         case -1: // look for lawn
            if (HighMapBuffer[shift]!=0.0 && HighMapBuffer[shift]>lasthigh && LowMapBuffer[shift]==0.0)
              {
               ZigzagBuffer[lasthighpos]=0.0;
               lasthighpos=shift;
               lasthigh=HighMapBuffer[shift];
               ZigzagBuffer[shift]=lasthigh;
              }
            if (LowMapBuffer[shift]!=0.0 && HighMapBuffer[shift]==0.0)
              {
               lastlow=LowMapBuffer[shift];
               lastlowpos=shift;
               ZigzagBuffer[shift]=lastlow;
               whatlookfor=1;
              }   
            break;               
         default: return; 
        }
     }

   return(0);
  }
//+------------------------------------------------------------------+

Comments