ZigZagHistory
Download scriptThis 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.
//+------------------------------------------------------------------+
//| 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