ZigZag.new
Download scriptThis script is designed to create a "ZigZag" indicator on a trading chart. The primary purpose of this tool is to filter out minor price fluctuations (market noise) and highlight the significant structural movements—specifically the major peaks and troughs—of a financial asset's price history.
Core Logic and Functionality
The logic operates by identifying structural turning points rather than recording every single price movement. It achieves this through a multi-layered filtering process:
1. Data Filtering and Sensitivity The script uses three primary parameters to determine how "aggressive" the lines should be:
- Depth: This dictates how far back the script looks to find a significant high or low. A higher depth means the indicator will only mark very large price moves.
- Deviation: This acts as a sensitivity threshold. The price must move by a specific minimum amount relative to the previous point for a new "leg" of the ZigZag to be formed.
- Backstep: This ensures that the peaks and troughs are not too close to one another, preventing the creation of many small, jagged lines in a tight trading range.
2. The Three-Stage Calculation Process To ensure accuracy, the script processes the data in three distinct phases:
-
Phase 1: Preliminary Identification The script scans through the price history to identify potential highs and lows. It checks if the current price point is significantly different from the previous one based on your settings. If a point meets these criteria, it is temporarily marked as a candidate for a peak or a trough.
-
Phase 2: Conflict Resolution and Pruning Because multiple points might qualify as "significant" in a short period, the script performs a second pass to resolve conflicts. It compares the identified peaks and troughs against each other. For example, if two high points are identified very close together, it keeps only the highest one and discards the other. This ensures that the final result is a clean, alternating "up-and-down" movement rather than overlapping lines.
-
Phase 3: Final Construction and Error Correction The script performs a final pass to merge the peak and trough data into a single continuous line (the ZigZag). It also includes a "cleaning" routine at the end to remove any "false cities"—mathematical anomalies where the logic might have produced three consecutive peaks or troughs in a row, which is impossible in a standard trend.
User Experience
For a visitor viewing this on a chart, the result is a simplified, geometric representation of price action. Instead of seeing every tiny tick of the market, you see a clear line connecting the major highs and lows. This helps in identifying long-term trends, support and resistance levels, and significant trend reversals by stripping away the "noise" of day-to-day volatility.
//+------------------------------------------------------------------+
//| 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 Aquamarine
#property indicator_width1 0
#property indicator_style1 1
//----
extern int ExtDepth=6;
extern int ExtDeviation=3;
extern int ExtBackstep=2;
//----
//----
double ZigZagBuffer[];
//+------------------------------------------------------------------+
//| ZigZag initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
SetIndexBuffer(0,ZigZagBuffer);
SetIndexStyle(0,DRAW_SECTION);
SetIndexEmptyValue(0,0.0);
IndicatorShortName("ZigZag("+ExtDepth+","+ExtDeviation+","+ExtBackstep+")");
//----
return(0);
}
//+------------------------------------------------------------------+
//| ZigZag iteration function |
//+------------------------------------------------------------------+
int start()
{
//----+ ïðîâåðêà êîëè÷åñòâà áàðîâ íà äîñòàòî÷íîñòü äëÿ êîððåêòíîãî ðàñ÷¸òà èíäèêàòîðà
if (Bars-1<ExtDepth)return(0);
//----+ Ââåäåíèå öåëûõ ïåðåìåííûõ ïàìÿòè äëÿ ïåðåñ÷¸òà èíäèêàòîðà òîëüêî íà íåïîäñ÷èòàííûõ áàðàõ
static int time2,time3,time4;
//----+ Ââåäåíèå ïåðåìåííûõ ñ ïëàâàþùåé òî÷êîé äëÿ ïåðåñ÷¸òà èíäèêàòîðà òîëüêî íà íåïîäñ÷èòàííûõ áàðàõ
static double ZigZag2,ZigZag3,ZigZag4;
//----+ Ââåäåíèå öåëûõ ïåðåìåííûõ äëÿ ïåðåñ÷¸òà èíäèêàòîðà òîëüêî íà íåïîäñ÷èòàííûõ áàðàõ è ïîëó÷åíèå óæå ïîäñ÷èòàííûõ áàðîâ
int MaxBar,limit,supr2_bar,supr3_bar,supr4_bar,counted_bars=IndicatorCounted();
//---- ïðîâåðêà íà âîçìîæíûå îøèáêè
if (counted_bars<0)return(-1);
//---- ïîñëåäíèé ïîäñ÷èòàííûé áàð äîëæåí áûòü ïåðåñ÷èòàí
if (counted_bars>0) counted_bars--;
//----+ Ââåäåíèå ïåðåìåííûõ
int shift, num, back,lasthighpos,lastlowpos;
double val,res,TempBuffer[1];
double curlow,curhigh,lasthigh,lastlow;
//---- îïðåäåëåíèå íîìåðà ñàìîãî ñòàðîãî áàðà, íà÷èíàÿ ñ êîòîðîãî áóäåò ïðîèçåä¸í ïîëûé ïåðåñ÷¸ò âñåõ áàðîâ
MaxBar=Bars-ExtDepth;
//---- îïðåäåëåíèå íîìåðà ñòàðòîâîãî áàðà â öèêëå, íà÷èíàÿ ñ êîòîðîãî áóäåò ïðîèçåäèòüñÿ ïåðåñ÷¸ò íîâûõ áàðîâ
if (counted_bars==0)limit=MaxBar;
else
{
//----
supr2_bar=iBarShift(NULL,0,time2,TRUE);
supr3_bar=iBarShift(NULL,0,time3,TRUE);
supr4_bar=iBarShift(NULL,0,time4,TRUE);
//----
limit=supr3_bar;
if ((supr2_bar<0)||(supr3_bar<0)||(supr4_bar<0))
{
limit=MaxBar;
Print("Ñòàðòîâûé áàð íå íàéäåí, áóäåí ïðîèçâåä¸í ïåðåñ÷¸ò èíäèêàòîðà íà âñåõ áàðàõ" );
}
}
//---- èíèöèàëèçàöèÿ íóëÿ
if (limit>=MaxBar)
{
for (shift=Bars-1; shift>=MaxBar;shift--)ZigZagBuffer [shift]=0.0;
limit=MaxBar;
}
//----
//---- èçìåíåíèå ðàçìåðà âðåìåííîãî áóôåðà
if(ArrayResize(TempBuffer,limit+ExtBackstep+1)!=limit+ExtBackstep+1)return(-1);
//----+-------------------------------------------------+
//----+ íà÷àëî ïåðâîãî áîëüøîãî öèêëà
for(shift=limit; shift>=0; shift--)
{
//---
num=Lowest(NULL,0,MODE_LOW,ExtDepth,shift);
val=Low[num];
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=ZigZagBuffer[shift+back];
if((res!=0)&&(res>val)) ZigZagBuffer[shift+back]=0.0;
}
}
}
ZigZagBuffer[shift]=val;
//---
num=Highest(NULL,0,MODE_HIGH,ExtDepth,shift);
val=High[num];
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=TempBuffer[shift+back];
if((res!=0)&&(res<val)) TempBuffer[shift+back]=0.0;
}
}
}
TempBuffer[shift]=val;
}
//----+ êîíåö ïåðâîãî áîëüøîãî öèêëà
// final cutting
lasthigh=-1; lasthighpos=-1;
lastlow= -1; lastlowpos= -1;
//----+-------------------------------------------------+
//----+ íà÷àëî âòîðîãî áîëüøîãî öèêëà
for(shift=limit; shift>=0; shift--)
{
curlow=ZigZagBuffer[shift];
curhigh=TempBuffer[shift];
if((curlow==0)&&(curhigh==0)) continue;
//---
if(curhigh!=0)
{
if(lasthigh>0)
{
if(lasthigh<curhigh) TempBuffer[lasthighpos]=0;
else TempBuffer[shift]=0;
}
//---
if(lasthigh<curhigh || lasthigh<0)
{
lasthigh=curhigh;
lasthighpos=shift;
}
lastlow=-1;
}
//----
if(curlow!=0)
{
if(lastlow>0)
{
if(lastlow>curlow) ZigZagBuffer[lastlowpos]=0;
else ZigZagBuffer[shift]=0;
}
//---
if((curlow<lastlow)||(lastlow<0))
{
lastlow=curlow;
lastlowpos=shift;
}
lasthigh=-1;
}
}
//----+ êîíåö âòîðîãî áîëüøîãî öèêëà
//----+-------------------------------------------------+
//----+ íà÷àëî òðåòüåãî öèêëà
for(shift=limit; shift>=0; shift--)
{
res=TempBuffer[shift];
if(res!=0.0) ZigZagBuffer[shift]=res;
}
//----+ êîíåö òðåòüåãî öèêëà
//+--- Âîññòàíîâëåíèå çíà÷åíèé èíäèêàòîðíîãî áóôôåðà, êîòîðûå ìîãëè áûòü óòåðÿíû
if (limit<MaxBar)
{
ZigZagBuffer[supr2_bar]=ZigZag2;
ZigZagBuffer[supr3_bar]=ZigZag3;
ZigZagBuffer[supr4_bar]=ZigZag4;
for(int qqq=supr4_bar-1; qqq>supr3_bar; qqq--)ZigZagBuffer[qqq]=0;
for(int ggg=supr3_bar-1; ggg>supr2_bar; ggg--)ZigZagBuffer[ggg]=0;
}
//+---+============================================+
//+--- èñïðàâëåíèå âîçíèêàþùèõ ãîðáîâ
double vel1, vel2, vel3, vel4;
int bar1, bar2, bar3, bar4;
int count;
if (limit==MaxBar)supr4_bar=MaxBar;
for(int bar=supr4_bar; bar>=0; bar--)
{
if (ZigZagBuffer[bar]!=0)
{
count++;
vel4=vel3;bar4=bar3;
vel3=vel2;bar3=bar2;
vel2=vel1;bar2=bar1;
vel1=ZigZagBuffer[bar];bar1=bar;
if (count<3)continue;
if ((vel3<vel2)&&(vel2<vel1))ZigZagBuffer[bar2]=0;
if ((vel3>vel2)&&(vel2>vel1))ZigZagBuffer[bar2]=0;
if ((vel2==vel1)&&(vel1!=0 ))ZigZagBuffer[bar1]=0;
}
}
//+--- çàïîìèíàíèå âðåìåíè òð¸õ ïîñëåäíèõ ïåðåãèáîâ Çèãçàãà è çíà÷åíèé èíäèêàòîðà â ýòèõ òî÷êàõ
time2=Time[bar2];
time3=Time[bar3];
time4=Time[bar4];
ZigZag2=vel2;
ZigZag3=vel3;
ZigZag4=vel4;
//+---
//---- çàâåðøåíèå âû÷èñëåíèé çíà÷åíèé èíäèêàòîðà
return(0);
}
//---+ +---------------------------------------------------------------------+
Comments