ZigZagHistory

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

This script is designed to identify and visualize significant price movements in a financial market by filtering out minor fluctuations (market noise) and highlighting the core structural shifts. It works by automatically connecting major highs and lows to form a "ZigZag" pattern on your trading chart.

Core Operational Logic

1. Filtering Market Noise The script does not plot every single price movement. Instead, it uses three primary settings—Depth, Deviation, and Backstep—to determine which price points are significant enough to be recorded.

  • Depth determines how far back the script looks to find a previous point.
  • Deviation ensures that a new point is only recognized if the price has moved by a specific minimum amount.
  • Backstep acts as a refinement tool to ensure that multiple peaks or valleys occurring very close to one another are consolidated into a single definitive point.

2. Tracking Highs and Lows The logic constantly scans the historical data to map out two distinct categories of data:

  • High Maps: These identify potential "peaks" where price reached a local maximum.
  • Low Maps: These identify potential "valleys" where price reached a local minimum.

During this process, the script calculates a "Midpoint" for every movement, which helps in defining the center of the price action between a high and a low.

3. Identifying Structural Shifts (The ZigZag Path) Once the highs and lows are mapped, the script performs a "final cutting" process to decide which points actually form the ZigZag line. It follows a specific logic flow:

  • If the market is currently trending upward, the script actively looks for a new, lower low to signal a potential reversal.
  • If the market is trending downward, it looks for a new, higher high.
  • As it processes these points, if it finds a "better" peak (higher) or valley (lower) than the one previously recorded in that sequence, it will overwrite the old point with the new one. This ensures that the resulting line accurately reflects the most extreme price boundaries of a specific trend move.

4. Visual Representation The final output is a continuous path on your chart. It effectively "cleans up" the visual history of a currency pair or stock, allowing you to see the underlying trend structure (the sequence of major highs and lows) without being distracted by the constant minor ticks of daily price volatility.

Miscellaneous
Implements a curve of type %1
10 Views
0 Downloads
0 Favorites
ZigZagHistory
//+------------------------------------------------------------------+
//|                                                ZigzagHistory.mq4 |
//|                 Copyright © 2005-2007, MetaQuotes Software Corp. |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."

#property indicator_chart_window
#property indicator_buffers 6
#property indicator_color1 Red
#property indicator_color4 Green
#property indicator_color5 Green
#property indicator_color6 DimGray
//---- indicator parameters
extern int ExtDepth=10;
extern int ExtDeviation=5;
extern int ExtBackstep=3;
//---- indicator buffers
double ZigzagBuffer[];
double HighMapBuffer[];
double LowMapBuffer[];
double Hi[];
double Lo[];
double Mid[];
int level=3; // recounting's depth 
bool downloadhistory=false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   IndicatorBuffers(6);
//---- drawing settings
//---- indicator buffers mapping
   SetIndexBuffer(0,ZigzagBuffer); SetIndexStyle(0,DRAW_SECTION);
   SetIndexBuffer(1,HighMapBuffer); SetIndexStyle(1,DRAW_NONE);
   SetIndexBuffer(2,LowMapBuffer); SetIndexStyle(2,DRAW_NONE);
   SetIndexBuffer(3,Hi); SetIndexStyle(3,DRAW_LINE);
   SetIndexBuffer(4,Lo); SetIndexStyle(4,DRAW_LINE);
   SetIndexBuffer(5,Mid); SetIndexStyle(5,DRAW_LINE);
   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(Hi,0.0);
      ArrayInitialize(Lo,0.0);
      ArrayInitialize(Mid,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; Lo[shift]=val; }	
      else {	LowMapBuffer[shift]=0.0; Lo[shift] = Lo[shift+1];}
      //--- 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; Hi[shift]=val; }
      else {	HighMapBuffer[shift]=0.0; Hi[shift]=Hi[shift+1]; }
     }

	for (shift=limit;shift>=0;shift--)  Mid[shift] = (Hi[shift]+Lo[shift])/2;

   // 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;
                  res=1;
                 }
               if (LowMapBuffer[shift]!=0)
                 {
                  lastlow=Low[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