NonLagZigZag_v2_v2

Download script
Author: Copyright � 2006, TrendLaboratory
NonLagZigZag_v2_v2

This tool is designed to identify and visualize significant price movements on a trading chart while filtering out minor market "noise." Unlike standard moving averages that can sometimes lag behind the current price, this script utilizes a specialized mathematical smoothing technique to provide a clearer picture of the underlying trend.

Core Logic Overview

The indicator functions by processing historical price data through several layers of calculation to determine whether a trend is genuinely shifting or simply fluctuating slightly.

1. Advanced Smoothing (Non-Lag Moving Average) Instead of using a simple average, the script applies a complex weighting system. It calculates a "Non-Lag" moving average, which assigns specific mathematical weights to different price points. This allows the tool to react more fluidly to price changes while maintaining a smoother line than traditional methods.

2. Dynamic Volatility Filtering To prevent the indicator from reacting to every tiny tick in the market, it uses a "Dynamic Filter." It constantly measures the standard deviation (the degree of volatility) of the price movements.

  • If a price change is smaller than this calculated filter, the script ignores it, treating it as insignificant noise.
  • Only when a price move exceeds this specific threshold does the tool acknowledge a potential change in direction.

3. Trend Detection & Identification Once the smoothed price moves beyond the volatility filter, the script identifies the direction of the trend (Up or Down). It keeps track of these shifts to determine the current momentum of the market.

4. ZigZag Pattern Construction The final output is the "ZigZag" line seen on the chart. The logic works as follows:

  • Peak and Trough Tracking: When a new trend is detected, the script looks back at the price history to find the highest point (in an uptrend) or the lowest point (in a downtrend).
  • Point Mapping: It marks these specific extremes on the chart.
  • Visual Cleaning: The script is designed to "clean" the path between these points, ensuring that only the most significant highs and lows are connected by the gold line, creating a clear visual map of the market's structure.

Summary for the User

In plain terms, this tool looks at the price history, smooths out the "jittery" movements using a non-lagging formula, measures how much the market is currently swinging, and only draws a new point on your chart when the price moves significantly enough to be considered a real trend change. It helps traders see the "big picture" by highlighting the major peaks and valleys while ignoring the minor fluctuations.

Indicators Used
Moving average indicator
Miscellaneous
Implements a curve of type %1
8 Views
1 Downloads
0 Favorites
NonLagZigZag_v2_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