Post-zigzag

Download script
Author: Copyright � 2011, rockyhoangdn
Post-zigzag

This script is designed to analyze price movements on a trading chart and identify significant structural turning points, commonly known as "swings" or "peaks and valleys." By filtering out minor market noise, it helps traders visualize the core trend of the market by connecting major highs and lows.

How the Logic Works

The script operates through a multi-stage filtering process to ensure that only meaningful price movements are highlighted:

1. Preliminary Data Filtering The tool first scans the recent price history using three specific parameters provided by the user: Depth, Deviation, and Backstep.

  • It looks for the highest highs and lowest lows within a specific window of time (Depth).
  • It enforces a minimum price change (Deviation) to ensure that tiny, insignificant fluctuations are ignored.
  • The "Backstep" logic acts as a secondary check to ensure that if multiple price points occur in very quick succession, only the most prominent one is retained.

2. Identification of Peaks and Valleys Once the minor noise is removed, the script categorizes every valid point into either a potential "High Map" (a peak) or a "Low Map" (a valley). It effectively creates a map of the skeleton of the price movement without the extra "fat" of daily volatility.

3. Trend Recognition and Refinement The core logic then moves into a "state-based" tracking system. The script identifies which direction the market is currently moving:

  • Upward Trend: If the script detects a new low that is lower than the previous known low, it updates the "valley" point.
  • Downward Trend: If it detects a new high that is higher than the previous known high, it updates the "peak" point.

4. Dynamic Updating (The "Post-Zigzag" Logic) One of the key features of this script is its ability to "rethink" recent movements. As new price data comes in, the script checks if the current price has surpassed a previously identified peak or valley. If the price continues to move past a point that was recently marked as a turning point, the script deletes the old point and moves the marker to the new, more extreme price. This ensures that the visual line accurately reflects the "true" highest high or lowest low of a specific move until the trend actually reverses.

Summary for the User

Instead of showing every single candle's movement, this script acts as a filter. It waits for the price to make a significant enough move to be considered a "turn." It then draws a line connecting these turns, allowing you to see the underlying "zigzag" of the market trend, making it easier to identify support levels, resistance levels, and overall market momentum.

Miscellaneous
Implements a curve of type %1
17 Views
0 Downloads
0 Favorites
Post-zigzag
//+------------------------------------------------------------------+
//|                                                  Post-zigzag.mq4 |
//|                      Copyright © 2011,    rockyhoangdn@gmail.com |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2011, rockyhoangdn"
#property link      "mailto:rockyhoangdn@gmail.com"
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 Red
#property indicator_color2 RoyalBlue
#property indicator_color3 Yellow

//---- indicator parameters
extern int ExtDepth=12;
extern int ExtDeviation=5;
extern int ExtBackstep=3;
//---- indicator buffers
double ZigzagBuffer[];
double HighMapBuffer[];
double LowMapBuffer[];
double TopBuffer[];
double BotomBuffer[];
int level=3; // recounting's depth 
bool downloadhistory=false;
string trend ="";

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   IndicatorBuffers(5);
//---- drawing settings
   SetIndexStyle(0,DRAW_SECTION);
   SetIndexStyle(3,DRAW_SECTION);
   SetIndexStyle(4,DRAW_SECTION);
   
//---- indicator buffers mapping
   SetIndexBuffer(0,ZigzagBuffer);
   SetIndexBuffer(1,HighMapBuffer);
   SetIndexBuffer(2,LowMapBuffer);
   SetIndexBuffer(3,BotomBuffer);
   SetIndexBuffer(4,TopBuffer);
   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);
      ArrayInitialize(TopBuffer,0.0);
      ArrayInitialize(BotomBuffer,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)];
      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=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;
      //--- high
      val=High[iHighest(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=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;
     }

   // 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];
                  lasthighpos=shift;
                  whatlookfor=-1;
                  ZigzagBuffer[shift]=lasthigh;
                  TopBuffer[shift]=lasthigh+0;
				      trend="down";
                  res=1;
                 }
               if (LowMapBuffer[shift]!=0)
                 {
                  lastlow=Low[shift];
                  lastlowpos=shift;
                  whatlookfor=1;
                  ZigzagBuffer[shift]=lastlow;
                  BotomBuffer[shift]=lastlow+0;
				      trend="up";
                  res=1;
                 }
              }
             break;  
         case 1: // look for peak
            if (LowMapBuffer[shift]!=0.0 && LowMapBuffer[shift]<lastlow && HighMapBuffer[shift]==0.0)
              {
               ZigzagBuffer[lastlowpos]=0.0;
               BotomBuffer[lastlowpos]=0.0;
               lastlowpos=shift;
               lastlow=LowMapBuffer[shift];
               ZigzagBuffer[shift]=lastlow;
               BotomBuffer[shift]=lastlow+0;
			      trend="up";
               res=1;
              }
            if (HighMapBuffer[shift]!=0.0 && LowMapBuffer[shift]==0.0)
              {
               lasthigh=HighMapBuffer[shift];
               lasthighpos=shift;
               ZigzagBuffer[shift]=lasthigh;
			      TopBuffer[shift]=lasthigh+0;
			      trend="down";
               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;
               TopBuffer[lasthighpos]=0.0;
               
               lasthighpos=shift;
               lasthigh=HighMapBuffer[shift];
               ZigzagBuffer[shift]=lasthigh;
			      TopBuffer[shift]=lasthigh+0;
			      trend="down";
              }
            if (LowMapBuffer[shift]!=0.0 && HighMapBuffer[shift]==0.0)
              {
               lastlow=LowMapBuffer[shift];
               lastlowpos=shift;
               ZigzagBuffer[shift]=lastlow;
			      
			      BotomBuffer[shift]=lastlow+0;
			      trend="up";
               whatlookfor=1;
              }   
            break;               
         default: return; 
        }
     }
   
//----
   return(0);
  }
//+------------------------------------------------------------------+

Comments