ZigZag_AutoChannel_002
Download scriptOverview
This script is designed to identify and visualize significant structural patterns in financial price movements. Its primary goal is to filter out minor market "noise" to reveal the underlying trend by highlighting key high and low points, ultimately forming a visual channel on your trading chart.
Core Logic and Functionality
The logic operates through a multi-stage process to ensure that only meaningful price swings are captured:
1. Data Filtering and Point Identification The script constantly scans historical price data to identify local peaks (highs) and valleys (lows). To prevent every minor fluctuation from being marked, it uses three specific filters:
- Depth: It looks at a set number of previous candles to determine if a high or low is significant enough to be considered a "turning point."
- Deviation: It ensures that the price has moved a minimum distance. This prevents the script from reacting to insignificant vibrations in the market.
- Backstep: This acts as a refinement tool, ensuring that identified points are distinct from one another and not clustered too closely together.
2. Structural Refinement (The "ZigZag" Logic) Once potential highs and lows are found, the script performs a "cleanup" phase. It compares these points against each other to ensure logical flow:
- If a new high is detected that is higher than the previous one, it updates the trend point.
- If it finds two consecutive highs or lows, it discards the lower/higher value to ensure the path remains a clean, alternating sequence of peaks and valleys (similar to a ZigZag pattern).
3. Trendline Generation After establishing these key structural points, the script calculates the trajectory between them. It automatically draws two main trend lines:
- It identifies the most recent significant points in the data.
- It connects these points to create dynamic trend lines that represent the current "path" of the market.
- These lines are updated in real-time as new price data arrives, moving with the market to reflect the most current structural shift.
Visual Output
For the user, this logic translates into a clean chart representation where:
- Structural Highs and Lows are mathematically identified.
- Trend Lines are automatically drawn and moved, providing a clear visual of the current market direction (Upward vs. Downward).
- Upper and Lower Bands are generated based on these trend lines, helping traders see the boundaries of the current price channel.
//Version: 2
//Time: December 02, 2006
//+------------------------------------------------------------------+
//| ZigZag Channels |
//| ZigZag_Channels.mq4 |
//| Developed by Coders Guru |
//| http://www.xpworx.com |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Red
//---- indicator parameters
extern int ExtDepth = 12;
extern int ExtDeviation = 5;
extern int ExtBackstep = 3;
extern color color_trend_1 = Yellow;
extern color color_trend_2 = Yellow;
extern int back = 1;
//---- indicator buffers
double ExtMapBuffer[];
double ExtMapBuffer2[];
double upperband[];
double lowerband[];
int deinit()
{
ObjectDelete("trend_1");
ObjectDelete("trend_2");
return (0);
}
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
IndicatorBuffers(4);
//---- drawing settings
SetIndexStyle(0,DRAW_SECTION);
//---- indicator buffers mapping
SetIndexBuffer(0,ExtMapBuffer);
SetIndexBuffer(1,ExtMapBuffer2);
SetIndexBuffer(2,upperband);
SetIndexBuffer(3,lowerband);
SetIndexLabel(0,NULL) ;
SetIndexLabel(1,NULL) ;
SetIndexLabel(2,"Upper band") ;
SetIndexLabel(3,"Lower band") ;
SetIndexEmptyValue(0,0.0);
ArraySetAsSeries(ExtMapBuffer,true);
ArraySetAsSeries(ExtMapBuffer2,true);
ArraySetAsSeries(upperband,true);
ArraySetAsSeries(lowerband,true);
//ObjectDelete("trend_1");
//ObjectDelete("trend_2");
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int start()
{
int shift, back,lasthighpos,lastlowpos;
double val,res;
double curlow,curhigh,lasthigh,lastlow;
for(shift=Bars-ExtDepth; shift>=0; shift--)
{
val=Low[Lowest(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=ExtMapBuffer[shift+back];
if((res!=0)&&(res>val)) ExtMapBuffer[shift+back]=0.0;
}
}
}
ExtMapBuffer[shift]=val;
//--- high
val=High[Highest(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=ExtMapBuffer2[shift+back];
if((res!=0)&&(res<val)) ExtMapBuffer2[shift+back]=0.0;
}
}
}
ExtMapBuffer2[shift]=val;
}
// final cutting
lasthigh=-1; lasthighpos=-1;
lastlow=-1; lastlowpos=-1;
for(shift=Bars-ExtDepth; shift>=0; shift--)
{
curlow=ExtMapBuffer[shift];
curhigh=ExtMapBuffer2[shift];
if((curlow==0)&&(curhigh==0)) continue;
//---
if(curhigh!=0)
{
if(lasthigh>0)
{
if(lasthigh<curhigh) ExtMapBuffer2[lasthighpos]=0;
else ExtMapBuffer2[shift]=0;
}
//---
if(lasthigh<curhigh || lasthigh<0)
{
lasthigh=curhigh;
lasthighpos=shift;
}
lastlow=-1;
}
//----
if(curlow!=0)
{
if(lastlow>0)
{
if(lastlow>curlow) ExtMapBuffer[lastlowpos]=0;
else ExtMapBuffer[shift]=0;
}
//---
if((curlow<lastlow)||(lastlow<0))
{
lastlow=curlow;
lastlowpos=shift;
}
lasthigh=-1;
}
}
for(shift=Bars-1; shift>=0; shift--)
{
if(shift>=Bars-ExtDepth) ExtMapBuffer[shift]=0.0;
else
{
res=ExtMapBuffer2[shift];
if(res!=0.0) ExtMapBuffer[shift]=res;
}
}
DrawTrends();
for(shift=Bars-1; shift>=0; shift--)
{
upperband[shift]= ObjectGetValueByShift("trend_1",shift);
lowerband[shift]= ObjectGetValueByShift("trend_2",shift);
}
}
void DrawTrends()
{
double temp = 0;
int count = 0;
double save_0 , save_1 , save_2 , save_3;
int t_0 , t_1 , t_2 , t_3;
//get last up
for(int i = 0 ; i < Bars ; i++)
{
temp = ExtMapBuffer[i];
if (temp != 0) count++;
Print("count:", count);
if(count == back + 1 && temp != 0) {save_0 = temp; t_0 = i;}
if(count == back + 2 && temp != 0) {save_1 = temp; t_1 = i;}
if(count == back + 3 && temp != 0) {save_2 = temp; t_2 = i;}
if(count == back + 4 && temp != 0) {save_3 = temp; t_3 = i;}
if(count == back + 5) break;
}
count = 0;
//draw trends
Print(save_0,":",save_1,":",save_2,":",save_3);
if((ObjectFind("trend_2")==-1) || (ObjectFind("trend_2")==-1))
{
ObjectCreate("trend_2",OBJ_TREND,0,iTime(NULL,0,t_3),save_3,iTime(NULL,0,t_1),save_1);
ObjectCreate("trend_1",OBJ_TREND,0,iTime(NULL,0,t_2),save_2,iTime(NULL,0,t_0),save_0);
ObjectSet("trend_1",OBJPROP_STYLE,STYLE_SOLID);
ObjectSet("trend_2",OBJPROP_STYLE,STYLE_SOLID);
ObjectSet("trend_1",OBJPROP_WIDTH,2);
ObjectSet("trend_2",OBJPROP_WIDTH,2);
ObjectSet("trend_1",OBJPROP_COLOR,color_trend_1);
ObjectSet("trend_2",OBJPROP_COLOR,color_trend_2);
}
else
{
if (save_2!=0)
{
ObjectMove("trend_1", 0,iTime(NULL,0,t_2),save_2);
ObjectMove("trend_1", 1,iTime(NULL,0,t_0),save_0);
ObjectMove("trend_2", 0,iTime(NULL,0,t_3),save_3);
ObjectMove("trend_2", 1,iTime(NULL,0,t_1),save_1);
}
}
}
Comments