ZigZag-2
Download scriptThis script is designed to create a "ZigZag" visual aid on your trading charts. Its primary purpose is to filter out the minor "noise" of constant price fluctuations to highlight the significant turning points—the major highs and lows—of a market trend.
How the Logic Works
The script processes price data through a multi-stage filtering system to determine which price points are important enough to be connected by a line. Here is the step-by-step breakdown:
1. Identifying Significant Extremes Instead of marking every single candle's high or low, the script looks back over a specific period (defined by the "Depth" setting). It searches for the highest and lowest points within that window. By doing this, it ignores small wobbles and focuses on structural peaks and valleys.
2. Filtering by Movement and Distance The script uses two main rules to decide if a new point qualifies as a significant turn:
- Deviation: It checks if the price has moved far enough to justify a new "zag." If the movement is too small, the script treats it as part of the current trend rather than a new turn.
- Backstep: This ensures that the turns are distinct from one another. It prevents the script from creating multiple peaks or valleys that are too close together in time, ensuring the resulting lines are clean and readable.
3. Dynamic Updating (The "Redraw" Logic) Because markets are live, a new high or low can appear while a trend is still forming. The script contains logic to compare the current point with the previous one:
- If a new price point appears that is higher than the most recent peak (or lower than the most recent valley), the script "updates" the previous point.
- Essentially, it realizes that the "highest" point just changed and adjusts the line accordingly in real-time.
4. Connecting the Dots Finally, the script merges these validated high and low points into a single continuous path. It ensures that the peaks and valleys alternate correctly (High → Low → High), creating a clean, zigzagging line that tracks the skeletal structure of the market's price action.
Summary for the User
Think of this tool as a "map" of the market's skeleton. While the actual price moves up and down every second, this script ignores those tiny movements and only draws a line when the price makes a meaningful change in direction. This helps traders identify the overarching trend and support/resistance levels more clearly.
//+------------------------------------------------------------------+
//| ZigZag.mq4 |
//| Copyright © 2005, MetaQuotes Software Corp. |
//| http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, 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 ExtMapBuffer[];
double ExtLowBuffer[];
double ExtHighBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
IndicatorBuffers(3);
//---- drawing settings
SetIndexStyle(0,DRAW_SECTION);
//---- indicator buffers mapping
SetIndexBuffer(0,ExtMapBuffer);
SetIndexBuffer(1,ExtLowBuffer);
SetIndexBuffer(2,ExtHighBuffer);
SetIndexEmptyValue(0,0.0);
//---- indicator short name
IndicatorShortName("ZigZag("+ExtDepth+","+ExtDeviation+","+ExtBackstep+")");
//---- initialization done
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int start()
{
int shift, back,lasthighpos,lastlowpos,index;
double val,res;
double curlow,curhigh,lasthigh,lastlow;
//----
for(shift=Bars-ExtDepth; shift>=0; shift--)
{
index=Lowest(NULL,0,MODE_LOW,ExtDepth,shift);
val=Low[index];
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=ExtLowBuffer[shift+back];
if((res!=0)&&(res>val)) ExtLowBuffer[shift+back]=0.0;
}
}
}
ExtLowBuffer[shift]=0.0;
if(val!=0.0) ExtLowBuffer[index]=val;
//--- high
index=Highest(NULL,0,MODE_HIGH,ExtDepth,shift);
val=High[index];
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=ExtHighBuffer[shift+back];
if((res!=0)&&(res<val)) ExtHighBuffer[shift+back]=0.0;
}
}
}
ExtHighBuffer[shift]=0.0;
if(val!=0.0) ExtHighBuffer[index]=val;
}
//---- final cutting
lasthigh=-1; lasthighpos=-1;
lastlow=-1; lastlowpos=-1;
//..................................................................
//....... Ýòî âcòàâëåííûé êîä äëÿ âèçóàëüíîãî òåñòèðîâàíèÿ èíäèêàòîðà
/**/ int start,start_j;
/**/start_j=ObjectGet("start",OBJPROP_TIME1);
/**/if(GetLastError()==0) start=iBarShift(NULL,0,start_j,False); else start=0;
//................êîíåö êîäà
//.....................................................................
// for(shift=Bars-ExtDepth; shift>=0; shift--)
for(shift=Bars-ExtDepth; shift>=start; shift--)
{
curlow=ExtLowBuffer[shift];
curhigh=ExtHighBuffer[shift];
if(curlow==0 && curhigh==0) continue;
//---
if(curhigh!=0)
{
if(lasthigh>0)
{
if(lasthigh<curhigh) ExtHighBuffer[lasthighpos]=0;
else ExtHighBuffer[shift]=0;
}
//---
if(lasthigh<curhigh || lasthigh<0)
{
lasthigh=curhigh;
lasthighpos=shift;
}
lastlow=-1;
}
//----
if(curlow!=0)
{
if(lastlow>0)
{
if(lastlow>curlow) ExtLowBuffer[lastlowpos]=0;
else ExtLowBuffer[shift]=0;
}
//---
if((curlow<lastlow)||(lastlow<0))
{
lastlow=curlow;
lastlowpos=shift;
}
lasthigh=-1;
}
}
//---- merge 2 buffers
lasthighpos=-1;
lastlowpos=-1;
// for(shift=Bars-1; shift>=0; shift--)
for(shift=Bars-1; shift>=start; shift--)
{
if(shift>=Bars-ExtDepth) ExtMapBuffer[shift]=0.0;
else
{
curlow=ExtLowBuffer[shift];
curhigh=ExtHighBuffer[shift];
//----
res=0;
if(curlow!=0)
{
if(lastlowpos==-1)
{
res=curlow;
lastlowpos=shift;
}
else
{
if(lasthighpos!=-1 && lastlowpos>lasthighpos)
{
res=curlow;
lastlowpos=shift;
}
}
}
if(curhigh!=0)
{
if(lasthighpos==-1)
{
res=curhigh;
lasthighpos=shift;
}
else
{
if(lastlowpos!=-1 && lasthighpos>lastlowpos)
{
res=curhigh;
lasthighpos=shift;
}
}
}
//----
ExtMapBuffer[shift]=res;
}
}
}
//+------------------------------------------------------------------+
Comments