ZigZag_AutoChannel_002

Download script
ZigZag_AutoChannel_002

Overview

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.
Miscellaneous
Implements a curve of type %1
6 Views
0 Downloads
0 Favorites
ZigZag_AutoChannel_002
//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