NonLagZigZag_v2_005

Download script
Author: Copyright � 2006, TrendLaboratory
NonLagZigZag_v2_005

This script is designed to identify and visualize significant market structural shifts—specifically highs and lows—on a trading chart. It functions by combining sophisticated smoothing techniques with volatility filtering to distinguish between minor price "noise" and actual trend reversals.

Here is a breakdown of the logic used to achieve this:

1. Advanced Signal Smoothing

Instead of using a standard moving average, which can be slow or lag behind current prices, the script employs a specialized mathematical formula (a Non-Lag Moving Average). It uses a weighted calculation that balances how much influence past prices have on the current result. This allows the tool to follow price movements more closely while still maintaining a smooth curve that filters out erratic, minor fluctuations.

2. Volatility Filtering

To prevent the indicator from reacting to every tiny tick in price, the script calculates the "Standard Deviation." In plain terms, it measures how much the market is swinging at any given moment. It then creates a dynamic threshold (a filter).

  • If a price move is smaller than this threshold, the script ignores it as insignificant noise.
  • If a move exceeds this threshold, the script recognizes it as a potential change in trend direction.

3. Trend Detection

The logic continuously compares the current smoothed price against its previous position. By comparing these values against the volatility filter mentioned above, the script determines whether the market is in an "Up" phase or a "Down" phase. It won't confirm a new trend until the movement is strong enough to break through the established volatility threshold.

4. High and Low Identification (The ZigZag Effect)

Once a trend change is confirmed, the script searches back through the price history to find the most extreme point of the previous move:

  • In an Uptrend: When the market shifts from down to up, the script identifies the lowest point reached during that preceding downward move and marks it.
  • In a Downtrend: When the market shifts from up to down, the script identifies the highest peak reached during that preceding upward move and marks it.

5. Visual Output

The final result is a "ZigZag" line on your chart. This line connects these identified extreme highs and lows, effectively stripping away the clutter of daily price fluctuations to show you the core "skeleton" of the market's structural movement. It helps traders see where the major pivots are occurring without being distracted by minor price movements.

Indicators Used
Moving average indicator
Miscellaneous
Implements a curve of type %1
11 Views
0 Downloads
0 Favorites
NonLagZigZag_v2_005
//+------------------------------------------------------------------+
//|                                              NonLagZigZag_v2.mq4 |
//|                                Copyright © 2006, TrendLaboratory |
//|            http://finance.groups.yahoo.com/group/TrendLaboratory |
//|                                   E-mail: igorad2003@yahoo.co.uk |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, TrendLaboratory"
#property link      "http://finance.groups.yahoo.com/group/TrendLaboratory"


#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Gold
#property indicator_width1 2

//---- input parameters
extern int     Price          =    0;  //Apply to Price(0-Close;1-Open;2-High;3-Low;4-Median price;5-Typical price;6-Weighted Close) 
extern int     Length         =   14;  //Period of NonLagMA
extern double  PctFilter      =    2;  //Dynamic filter in decimals

double ZZBuffer[];
double MABuffer[];
double trend[];
double Del[];
double AvgDel[];

int    ilow, ihigh, nlow, nhigh, prevnhigh,prevnlow, BarsBack;  
double alfa[];
datetime lotime,hitime;
int    i, Phase, Len, Cycle=4, Back=0;
double Coeff, beta, t, Sum, Weight, g;
double pi = 3.1415926535;    
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
  int init()
  {
   IndicatorBuffers(5);
   SetIndexStyle(0,DRAW_SECTION);
   SetIndexBuffer(0,ZZBuffer);
   SetIndexBuffer(1,MABuffer);
   SetIndexBuffer(2,trend);
   SetIndexBuffer(3,Del);
   SetIndexBuffer(4,AvgDel); 
   string short_name;
//---- indicator line
   
   IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));
//---- name for DataWindow and indicator subwindow label
   short_name="NonLagZigZag("+Length+")";
   IndicatorShortName(short_name);
   SetIndexLabel(0,"NonLagZigZag");
//----
   SetIndexEmptyValue(0,0.0);   
   SetIndexDrawBegin(0,Length*Cycle+Length);
//----
   
   Coeff =  3*pi;
   Phase = Length-1;
   Len = Length*Cycle + Phase;  
   ArrayResize(alfa,Len);
   Weight=0;    
      
      for (i=0;i<Len-1;i++)
      {
      if (i<=Phase-1) t = 1.0*i/(Phase-1);
      else t = 1.0 + (i-Phase+1)*(2.0*Cycle-1.0)/(Cycle*Length-1.0); 
      beta = MathCos(pi*t);
      g = 1.0/(Coeff*t+1);   
      if (t <= 0.5 ) g = 1;
      alfa[i] = g * beta;
      Weight += alfa[i];
      }
 
   return(0);
  }

//+------------------------------------------------------------------+
//| NonLagZigZag_v2                                                  |
//+------------------------------------------------------------------+
int start()
{
   int    i,shift, counted_bars=IndicatorCounted(),limit;
   double price,smin,smax;      
   if ( counted_bars > 0 )  limit=Bars-counted_bars;
   if ( counted_bars < 0 )  return(0);
   if ( counted_bars ==0 )  limit=Bars-1; 
   if ( counted_bars < 1 ) 
   {
   for(i=0;i<Bars-1;i++) 
   ZZBuffer[i]=0;
   for(i=1;i<Len;i++) 
   MABuffer[Bars-i]=iMA(NULL,0,1,0,MODE_SMA,Price,Bars-i);    
   }
   
   for(shift=limit;shift>=0;shift--) 
   {	
      Sum = 0;
      for (i=0;i<=Len-1;i++)
	   { 
      price = iMA(NULL,0,1,0,3,Price,i+shift);      
      Sum += alfa[i]*price;
      }
   
	if (Weight > 0) MABuffer[shift] = Sum/Weight;
   
   Del[shift] = MathAbs(MABuffer[shift] - MABuffer[shift+1]);
   
   double sumdel=0;
   for (i=0;i<=Length-1;i++) sumdel += Del[shift+i];
   
   AvgDel[shift] = sumdel/Length;
   
   double sumpow = 0;
   for (i=0;i<=Length-1;i++) sumpow += MathPow(Del[shift+i]-AvgDel[shift+i],2);
   double StdDev = MathSqrt(sumpow/Length); 
   
   double Filter = PctFilter * StdDev;       
   if (Filter < Point) Filter = Point;
   
   if( MathAbs(MABuffer[shift]-MABuffer[shift+1]) < Filter ) MABuffer[shift]=MABuffer[shift+1];
   
   trend[shift]=trend[shift+1];
   if (MABuffer[shift]-MABuffer[shift+1] > Filter) trend[shift]= 1;   
   if (MABuffer[shift+1]-MABuffer[shift] > Filter) trend[shift]=-1;
   
      if(trend[shift]>0)
      {
         if( trend[shift]!=trend[shift+1]) 
         {
         ilow = LowestBar(iBarShift(NULL,0,hitime,FALSE)-shift,shift);
         lotime = Time[ilow];
         ZZBuffer[ilow] = Low[ilow];
         }
         else
         if (shift==0) 
         {
         int hilen = iBarShift(NULL,0,lotime,FALSE);
         nhigh = HighestBar(hilen,0);
         ZZBuffer[nhigh]=High[nhigh];
         if (nhigh== 0) for (i=hilen-1;i>=1;i--) ZZBuffer[i]=0; 
         if (nhigh > 0) for (i=nhigh-1;i>=0;i--) ZZBuffer[i]=0; 
         }
      }
      
      if (trend[shift]<0)
      { 
         if( trend[shift]!=trend[shift+1]) 
         {
         ihigh = HighestBar(iBarShift(NULL,0,lotime,FALSE)-shift,shift);
         hitime=Time[ihigh];
         ZZBuffer[ihigh] = High[ihigh];
         }
         else
         if (shift==0) 
         {
         int lolen = iBarShift(NULL,0,hitime,FALSE);
         nlow = LowestBar(lolen,0);
         ZZBuffer[nlow] = Low[nlow]; 
         if (nlow==0) for (i=lolen-1;i>=1;i--) ZZBuffer[i]=0; 
         if (nlow >0) for (i=nlow-1;i>=0;i--) ZZBuffer[i]=0; 
         }
      }
   }
   return(0);	
}

int LowestBar(int len,int k)
{
   double min = 10000000;   
   int lobar;
   
   for (int i=k+len-1;i>=k;i--)
   if(Low[i] < min) {min = Low[i]; lobar = i;}
   if(len<=0) lobar=k;
   return(lobar);
} 

int HighestBar(int len,int k)
{
   double max = -10000000;   
   int hibar;
   
   for (int i=k+len-1;i>=k;i--)
   if(High[i] > max) {max = High[i]; hibar = i;}
   
   if(len<=0) hibar=k;
   return(hibar);
}                                     

Comments