This script functions as a sophisticated technical analysis tool designed to track market trends with high precision. Its primary objective is to calculate a "Non-Lag Moving Average," which is engineered to identify the direction of price movements while minimizing the inherent delay (lag) that typically affects standard moving averages.
Core Logic and Methodology
1. Advanced Weighting System Unlike simple moving averages that treat all past data points equally, this tool applies a unique mathematical weighting system. It uses a combination of trigonometric functions (cosines) and specific coefficients to assign more importance to certain price points. By adjusting these weights dynamically across a defined cycle, the script can react more fluidly to current market shifts while still filtering out "noise."
2. Smooth Curve Generation The logic processes historical price data through a multi-step calculation to produce a smoothed line. It looks at a specific window of time (determined by the user's settings) and calculates a weighted sum of prices. This results in a curve that represents the "true" underlying momentum of the asset, helping traders see where the market is headed rather than just where it has been.
3. Trend Detection and Color Coding The script includes an intelligent trend-tracking mechanism. It monitors the slope of the moving average to determine if the market is in an upward or downward phase:
- Upward Trend: If the average is rising significantly enough to cross a specific threshold, the tool identifies this as an "Up" trend.
- Downward Trend: If the average is falling significantly, it identifies a "Down" trend.
To make this visually intuitive, the script can separate these movements into distinct lines (often represented by different colors like Blue for Up and Red for Down). This allows a user to see exactly when a trend reversal occurs.
4. Customization and Filtering The logic provides several "levers" that users can adjust to suit different trading styles:
- Smoothing & Deviation: Users can slightly tweak the deviation of the average to make it more or less sensitive to price spikes.
- Noise Filtering: There is a built-in filter designed to ignore very minor price fluctuations, ensuring that the moving average only reacts to meaningful market movements.
- Visual Offset: The script allows for "displacing" or shifting the lines visually, which can help in aligning the data with specific chart layouts.
Summary for the User
Essentially, this script acts as a "smart" trend follower. It takes raw price data, applies a complex mathematical filter to remove delays and noise, and then projects a clear visual path showing whether the market is currently trending up or down. It is designed to give traders a cleaner, more responsive view of market momentum than standard built-in tools.
//+------------------------------------------------------------------+
//| NonLagMA_v4.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_separate_window
#property indicator_buffers 3
#property indicator_color1 Yellow
#property indicator_width1 2
#property indicator_color2 Blue
#property indicator_width2 2
#property indicator_color3 Red
#property indicator_width3 2
//---- input parameters
extern int Price = 0;
extern int Length = 9;
extern int Displace = 0;
extern int Filter = 0;
extern int Color = 1;
extern int ColorBarBack = 0;
extern double Deviation = 0;
double Cycle = 4;
//---- indicator buffers
double MABuffer[];
double UpBuffer[];
double DnBuffer[];
double price[];
double trend[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
int ft=0;
string short_name;
//---- indicator line
IndicatorBuffers(5);
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,MABuffer);
SetIndexStyle(1,DRAW_LINE);
SetIndexBuffer(1,UpBuffer);
SetIndexStyle(2,DRAW_LINE);
SetIndexBuffer(2,DnBuffer);
SetIndexBuffer(3,price);
SetIndexBuffer(4,trend);
IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));
//---- name for DataWindow and indicator subwindow label
short_name="NonLagMA("+Length+")";
IndicatorShortName(short_name);
SetIndexLabel(0,"NLMA");
SetIndexLabel(1,"Up");
SetIndexLabel(2,"Dn");
//----
SetIndexShift(0,Displace);
SetIndexShift(1,Displace);
SetIndexShift(2,Displace);
SetIndexDrawBegin(0,Length*Cycle+Length);
SetIndexDrawBegin(1,Length*Cycle+Length);
SetIndexDrawBegin(2,Length*Cycle+Length);
//----
return(0);
}
//+------------------------------------------------------------------+
//| NonLagMA_v4 |
//+------------------------------------------------------------------+
int start()
{
int i,shift, counted_bars=IndicatorCounted(),limit;
double alfa, beta, t, Sum, Weight, step,g;
double pi = 3.1415926535;
double Coeff = 3*pi;
int Phase = Length-1;
double Len = Length*Cycle + Phase;
if ( counted_bars > 0 ) limit=Bars-counted_bars;
if ( counted_bars < 0 ) return(0);
if ( counted_bars ==0 ) limit=Bars-Len-1;
if ( counted_bars < 1 )
for(i=1;i<Length*Cycle+Length;i++)
{
MABuffer[Bars-i]=0;
UpBuffer[Bars-i]=0;
DnBuffer[Bars-i]=0;
}
for(shift=limit;shift>=0;shift--)
{
Weight=0; Sum=0; t=0;
for (i=0;i<=Len-1;i++)
{
g = 1.0/(Coeff*t+1);
if (t <= 0.5 ) g = 1;
beta = MathCos(pi*t);
alfa = g * beta;
//if (shift>=1) price[i] = iMA(NULL,0,Per,Displace,Mode,Price,shift+i);
//else
price[i] = iMA(NULL,0,1,0,MODE_SMA,Price,shift+i);
Sum += alfa*price[i];
Weight += alfa;
if ( t < 1 ) t += 1.0/(Phase-1);
else if ( t < Len-1 ) t += (2*Cycle-1)/(Cycle*Length-1);
}
if (Weight > 0) MABuffer[shift] = (1.0+Deviation/100)*Sum/Weight;
if (Filter>0)
{
if( MathAbs(MABuffer[shift]-MABuffer[shift+1]) < Filter*Point ) MABuffer[shift]=MABuffer[shift+1];
}
if (Color>0)
{
trend[shift]=trend[shift+1];
if (MABuffer[shift]-MABuffer[shift+1] > Filter*Point) trend[shift]= 1;
if (MABuffer[shift+1]-MABuffer[shift] > Filter*Point) trend[shift]=-1;
if (trend[shift]>0)
{
UpBuffer[shift] = MABuffer[shift];
if (trend[shift+ColorBarBack]<0) UpBuffer[shift+ColorBarBack]=MABuffer[shift+ColorBarBack];
DnBuffer[shift] = EMPTY_VALUE;
}
if (trend[shift]<0)
{
DnBuffer[shift] = MABuffer[shift];
if (trend[shift+ColorBarBack]>0) DnBuffer[shift+ColorBarBack]=MABuffer[shift+ColorBarBack];
UpBuffer[shift] = EMPTY_VALUE;
}
}
}
return(0);
}
Comments