NonLagZigZag_v2

Download script
Author: Copyright � 2006, TrendLaboratory
NonLagZigZag_v2

This tool is designed to provide traders with a visual representation of market structure by identifying key price turning points (peaks and troughs) while minimizing the "noise" or false signals often found in standard charts. It achieves this by combining advanced smoothing techniques with a dynamic volatility filter.

Core Logic Overview

The script operates through three primary layers of processing:

1. Advanced Smoothing (Non-Lag Moving Average) At its foundation, the indicator uses a sophisticated moving average. Unlike standard averages that can cause delays in data (lag), this specific calculation applies weighted coefficients to price data. By calculating these weights based on mathematical curves, it attempts to track the "true" direction of the market more closely, providing a smoother line that reacts to significant movements without being distracted by minor price fluctuations.

2. Dynamic Volatility Filtering To ensure the indicator only reacts to meaningful price changes, it employs a dynamic filter. It calculates the standard deviation—a measure of how much the price is currently swinging. By multiplying this deviation by a user-defined percentage, the script creates a "threshold." If the change in price is smaller than this threshold, the indicator treats it as insignificant noise and maintains its current direction. This prevents the chart from becoming cluttered with every tiny wiggle in the market.

3. Trend and Extremum Identification (The ZigZag) Once the smooth trend and volatility filters are established, the script identifies the "turning points."

  • Trend Detection: It determines whether the market is currently in an upward or downward state based on the direction of the smoothed average.
  • Peak & Trough Capture: When the trend reverses (e.g., switching from up to down), the logic searches back through recent price history to find the absolute highest high or lowest low reached during that specific movement.
  • Visual Mapping: It then plots these extreme points on your chart as a connected line. This creates a clear "zig-zag" path that highlights the structural skeleton of the market, making it easier to see major trend changes and support/resistance levels at a glance.

Summary for the User

In plain terms, this script looks at the price, smooths out the unnecessary "jitter," ignores small movements that don't matter, and then draws a line connecting only the most important highs and lows. It helps you see the "big picture" of market movement by stripping away the distractions.

Indicators Used
Moving average indicator
Miscellaneous
Implements a curve of type %1
10 Views
0 Downloads
0 Favorites
NonLagZigZag_v2
//+------------------------------------------------------------------+
//|                                              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         =   100;  //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