This tool is designed to provide a smoother and more responsive way to track market trends without the common "lag" found in standard moving averages. In typical technical analysis, most indicators react to past price data with a delay; this script uses a specialized mathematical approach to minimize that delay while still filtering out significant market noise.
Core Logic and Mechanics
The primary function of this indicator is to calculate a modified moving average that accounts for the "momentum" of price movements. Instead of giving every historical price point equal importance, it applies a weighted calculation based on two main components:
- Weighted Smoothing: The logic uses a trigonometric (cosine) function combined with a weight distribution. This allows the indicator to prioritize certain data points over others, creating a curve that follows the price more naturally.
- Cycle Compensation: By incorporating a "cycle" factor, the script attempts to harmonize the data points so that the resulting line isn't just a reactive average, but a proactive representation of where the price is heading.
Trend Identification and Visualization
The script does more than just draw a single line; it actively interprets the direction of the market to provide clear visual cues:
- Dynamic Trend Detection: The system monitors the change between current and previous calculations. If the movement exceeds a specific threshold (the "Filter"), the script identifies a shift in momentum.
- Color-Coded Directional Paths: Based on these shifts, the indicator separates into two distinct visual paths:
- An Upward Path is displayed when the trend is positive.
- A Downward Path is displayed when the trend is negative.
- Trend Smoothing (Filtering): You can enable a filter to prevent "jitter" or minor fluctuations from causing constant color changes. This ensures that the trend path only flips when a significant and sustained move occurs, rather than reacting to every tiny price tick.
Summary for Users
For a trader, this means you receive a cleaner visual representation of the market's direction. It aims to provide a "lead" on the trend by reducing the lag time typical of standard moving averages, allowing you to see whether the current momentum is leaning upward or downward with greater clarity and less visual clutter.
//+------------------------------------------------------------------+
//| NonLagMA.mq4 |
//| Copyright © 2006, TrendLaboratory |
//| |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, TrendLaboratory"
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 Yellow
#property indicator_width1 2
#property indicator_color2 Green
#property indicator_width2 2
#property indicator_color3 Red
#property indicator_width3 2
//---- input parameters
extern int Price = 0;
extern int Length = 21;
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[];
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,"Down");
//----
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 |
//+--------------------------------------------------------------+
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;
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