ZigZagHistoryLL
Download scriptThis script is designed to analyze price movements in a financial market and visualize the core structural "skeleton" of those movements. It filters out minor market noise to highlight the significant trend changes, specifically identifying major highs and lows.
Core Logic Overview
The primary goal of this tool is to identify "swings"—the points where the price reverses direction significantly. Rather than showing every tiny fluctuation, the logic uses a set of three specific rules to determine which price points are important enough to be drawn on your chart.
1. Sensitivity Filtering
The script uses three main parameters to define what it considers a "significant" move:
- Depth: This determines how far back the script looks to find a peak or a valley. A higher depth means the script will only recognize larger, more substantial price swings.
- Deviation: This acts as a minimum "jump" requirement. The price must move by a specific amount from its previous point before the script recognizes it as a new trend direction.
- Backstep: This ensures that if multiple highs or lows occur very close to one another, the script only keeps the most extreme one, preventing the chart from becoming cluttered with overlapping lines.
2. The "Map" Construction
The logic first scans the price history to build a hidden map of potential high and low points. It constantly monitors the current price against these mapped points:
- It identifies the highest and lowest prices within a specific window.
- If a new price point is found that exceeds the previous one (or falls below it, depending on the direction), it updates the "map."
- It also calculates a "Mid" line, which represents the average between these highs and lows, providing a visual sense of the center of the current price action.
3. Structural Refinement (The ZigZag)
Once the map of potential peaks and valleys is built, the script performs a secondary "cleaning" process to draw the actual ZigZag line. This is where the logic becomes sophisticated:
- Trend Recognition: The script identifies whether the price is currently in an upward or downward trend.
- Peak vs. Valley Selection: Instead of simply connecting every point, it compares new points against the "last" confirmed peak or valley. If it finds a higher high during an uptrend, it "erases" the previous high and moves the marker forward. Similarly, if it finds a lower low during a downtrend, it updates the bottom point.
- Final Connection: This process ensures that the final line drawn on your chart represents the absolute peaks and valleys of the market movement, effectively smoothing out the "choppiness" of the data.
Summary for the User
Essentially, this script acts as a filter. It looks at all the messy price movements, ignores the small fluctuations that don't meet your specific criteria (Depth, Deviation, and Backstep), and draws a clean, connected path between the most important turning points in the market history.
//+------------------------------------------------------------------+
//| ZigzagHistory.mq4 |
//| Copyright © 2005-2007, MetaQuotes Software Corp. |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property indicator_chart_window
#property indicator_buffers 7
#property indicator_color1 Red
#property indicator_color4 Green
#property indicator_color5 Green
#property indicator_color6 DimGray
#property indicator_color7 Gold
//---- indicator parameters
extern int ExtDepth=10;
extern int ExtDeviation=5;
extern int ExtBackstep=3;
//---- indicator buffers
double ZigzagBuffer[];
double LastLegBuffer[];
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(7);
//---- 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);
SetIndexBuffer(6,LastLegBuffer);SetIndexStyle(6,DRAW_SECTION);
SetIndexEmptyValue(0,0.0);
SetIndexEmptyValue(6,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(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;
LastLegBuffer[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;
}
}
for (p=0,i=0;i<Bars && p<2;i++)
{
if (ZigzagBuffer[i] != 0)
{
LastLegBuffer[i] = ZigzagBuffer[i]; p++;
}
}
return(0);
}
//+------------------------------------------------------------------+
Comments