ZigZagLastLeg_
Download scriptThis script is designed to create a "ZigZag" visual aid on a trading chart. Its primary purpose is to filter out the "noise" of minor price fluctuations to highlight the significant structural movements of the market—essentially connecting the most important highs and lows in a continuous line.
How the Logic Works
The script operates by analyzing historical price data based on three main custom settings: Depth, Deviation, and Backstep. Here is the step-by-step process it follows to draw the lines:
1. Identifying Potential Extremes (Mapping) Instead of reacting to every tiny tick in price, the script first scans through the chart looking for significant "peaks" and "valleys."
- It looks back over a specific number of bars (Depth) to find the highest high and lowest low.
- It then checks if these points meet a minimum price difference (Deviation). If a price movement is too small, the script ignores it.
- The Backstep setting ensures that there is enough distance between identified points so that two peaks or valleys placed right next to each other aren't counted as separate significant events.
2. Establishing the Trend Direction Once the potential peaks and valleys are mapped out, the script determines the current direction of the price action. It identifies whether the market is currently in an "upward" move (searching for a new high/peak) or a "downward" move (searching for a new low/valley).
3. Filtering and Connecting the Points This is the core logic of the script. It moves backward through time to build the actual ZigZag line:
- If looking for a High: If it finds a price point that is higher than the previous peak, it updates the line to that new high. If it finds a lower low first, it notes it but keeps looking for a higher peak.
- If looking for a Low: If it finds a price point that is lower than the previous valley, it updates the line.
- Self-Correction: If a new "extreme" point is found that is more significant than the one previously recorded, the script essentially "erases" the old point and moves the line to the new, more accurate extreme.
4. Final Visualization After calculating these points, the script draws a continuous line connecting them on your chart. This allows you to see the skeletal structure of the market trends—clearly showing where major price reversals occur while ignoring the minor "wiggles" in between.
//+------------------------------------------------------------------+
//| 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 2
#property indicator_color1 Red
#property indicator_color2 Gold
//---- indicator parameters
extern int ExtDepth=12;
extern int ExtDeviation=5;
extern int ExtBackstep=3;
//---- indicator buffers
double ZigzagBuffer[];
double LastLegBuffer[];
double HighMapBuffer[];
double LowMapBuffer[];
int level=3; // recounting's depth
bool downloadhistory=false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
IndicatorBuffers(4);
//---- drawing settings
SetIndexStyle(0,DRAW_SECTION);
SetIndexStyle(1,DRAW_SECTION);
//---- indicator buffers mapping
SetIndexBuffer(0,ZigzagBuffer);
SetIndexBuffer(1,LastLegBuffer);
SetIndexBuffer(2,HighMapBuffer);
SetIndexBuffer(3,LowMapBuffer);
SetIndexEmptyValue(0,0.0);
SetIndexEmptyValue(1,0.0);
//---- indicator short name
IndicatorShortName("ZigZag("+ExtDepth+","+ExtDeviation+","+ExtBackstep+")");
//---- initialization done
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int start()
{
int i,p, 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(LastLegBuffer,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;
LastLegBuffer[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;
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;
}
}
for (p=0,i=0;i<Bars && p<2;i++)
{
if (ZigzagBuffer[i] != 0)
{
LastLegBuffer[i] = ZigzagBuffer[i]; p++;
}
}
return(0);
}
//+------------------------------------------------------------------+
Comments