LowPassFilter_v1
Download scriptThis technical tool is designed to help traders identify and visualize market trends by applying a sophisticated "smoothing" process to price data. By filtering out the minor fluctuations and "noise" of the market, it aims to reveal the underlying direction of price movement more clearly.
How the Logic Works
1. Initial Smoothing (Pre-processing) Before calculating the main trend, the script first takes the raw price data (such as Close, Open, High, Low, or Median prices) and applies a preliminary smoothing layer. This step ensures that the subsequent calculations are based on a stabilized version of the price rather than volatile, tick-by-tick movements.
2. The Filter Engine The core of the script is the "Low Pass Filter," which processes the smoothed data through three different mathematical models depending on your preference:
- Basic Smoothing: A standard moving average approach for a straightforward trend line.
- Second Order: A more advanced calculation that uses geometric constants to create a smoother, less reactive curve.
- Third Order: The highest level of complexity, designed to provide the smoothest possible output by neutralizing as much market "jitter" as possible.
3. Dynamic Volatility Adjustment (Optional) The script includes a specialized feature that looks at standard deviation—a measure of how much the price is swinging. If enabled, the filter can detect when movements are too small to be considered significant and will "hold" the trend line steady until a movement large enough to be meaningful occurs. This prevents the indicator from flickering during sideways market conditions.
4. Trend Detection and Visuals Once the filtered line is calculated, the script determines the direction of the market:
- Trend Identification: It compares the current value of the filter against its previous value. If the line moves up significantly, it identifies an "Up Trend"; if it moves down, it marks a "Down Trend."
- Visual Feedback: The tool plots these trends on your chart using different colors (Yellow, Light Blue, and Tomato) to make it easy to see where the trend is shifting. It can also highlight specific bars to indicate the exact moment a trend reversal occurred.
5. Alerts and Notifications To help traders who cannot watch the screens constantly, the script includes an automated notification system. When the logic detects a definitive flip from a Down Trend to an Up Trend (or vice versa), it can trigger:
- Visual Alerts: On-screen messages identifying the specific symbol and timeframe.
- Audio Warnings: Sound files that play at the moment of the trend shift.
In summary, this script acts as a sophisticated "lens" for price action. It strips away the distractions of minor price movements to show you the primary path of the market, providing visual cues and alerts when that path changes direction.
//+------------------------------------------------------------------+
//| LowPassFilter_v1.mq4 |
//| Copyright © 2007, TrendLaboratory Ltd. |
//| http://finance.groups.yahoo.com/group/TrendLaboratory |
//| E-mail: igorad2003@yahoo.co.uk |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, TrendLaboratory Ltd."
#property link "http://finance.groups.yahoo.com/group/TrendLaboratory"
//---- indicator settings
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 Yellow
#property indicator_color2 LightBlue
#property indicator_color3 Tomato
#property indicator_width1 2
#property indicator_width2 2
#property indicator_width3 2
//---- indicator parameters
extern int Price = 0; //Price mode : 0-Close,1-Open,2-High,3-Low,4-Median,5-Typical,6-Weighted
extern int Order = 3; //Filter Order: 1-EMA,2-2nd Order,3-3rd Order
extern int FilterPeriod =14; //Filter Period
extern int PreSmooth = 1; //Pre-smoothing period
extern int PreSmoothMode = 0; //Pre-smoothing MA Mode: 0-SMA,1-EMA,2-SMMA,3-LWMA
extern double PctFilter = 0; //Dynamic filter in decimal(multiplier for StdDev)
extern int ColorMode = 0; //Color Mode: 0-off,1-on
extern int ColorBarBack = 1; //Should be 0 or 1
extern int AlertMode = 0; //Sound Alert switch (0-off,1-on)
extern int WarningMode = 0; //Sound Warning switch(0-off,1-on)
//---- indicator buffers
double Filter[];
double UpTrend[];
double DnTrend[];
double Smoother[];
double trend[];
double Del[];
double AvgDel[];
int draw_begin;
bool UpTrendAlert=false, DownTrendAlert=false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicator buffers mapping
IndicatorBuffers(7);
SetIndexBuffer(0,Filter);
SetIndexBuffer(1,UpTrend);
SetIndexBuffer(2,DnTrend);
SetIndexBuffer(3,Smoother);
SetIndexBuffer(4,trend);
SetIndexBuffer(5,Del);
SetIndexBuffer(6,AvgDel);
//---- drawing settings
SetIndexStyle(0,DRAW_LINE);
SetIndexStyle(1,DRAW_LINE);
SetIndexStyle(2,DRAW_LINE);
draw_begin = FilterPeriod + PreSmooth;
SetIndexDrawBegin(0,draw_begin);
SetIndexDrawBegin(1,draw_begin);
SetIndexDrawBegin(2,draw_begin);
IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS)+1);
//---- name for DataWindow and indicator subwindow label
IndicatorShortName("LowPassFilter("+Order+","+FilterPeriod+")");
SetIndexLabel(0,"LowPassFilter");
SetIndexLabel(1,"UpTrend");
SetIndexLabel(2,"DnTrend");
//---- initialization done
return(0);
}
//+------------------------------------------------------------------+
//| LowPassFilter_v1 |
//+------------------------------------------------------------------+
int start()
{
int limit, i, shift;
int counted_bars=IndicatorCounted();
double a, b, c, pi = 3.1415926535;
if(counted_bars<1)
for(i=1;i<=draw_begin;i++)
{
Filter[Bars-i]=0;
UpTrend[Bars-i]=0;
DnTrend[Bars-i]=0;
}
//---- last counted bar will be recounted
if(counted_bars>0) counted_bars--;
limit=Bars-counted_bars;
for(shift=limit; shift>=0; shift--)
Smoother[shift] = iMA(NULL,0,PreSmooth,0,PreSmoothMode,Price,shift);
for(shift=limit; shift>=0; shift--)
{
if(Order == 1) Filter[shift] = iMAOnArray(Smoother,0,FilterPeriod,0,1,shift);
else
if(Order == 2)
{
a = MathExp(-MathSqrt(2)*pi/FilterPeriod);
b = 2*a*MathCos(MathSqrt(2)*pi/FilterPeriod);
Filter[shift] = b*Filter[shift+1] - a*a*Filter[shift+2] + (1 - b + a*a)*Smoother[shift];
}
else
if(Order == 3)
{
a = MathExp(-pi/FilterPeriod);
b = 2*a*MathCos(MathSqrt(3)*pi/FilterPeriod);
c = MathExp(-2*pi/FilterPeriod); //a * a;
Filter[shift] = (b+c)*Filter[shift+1] - (c+b*c)*Filter[shift+2] + c*c*Filter[shift+3] + (1-b+c)*(1-c)*Smoother[shift];
}
int Length = FilterPeriod;
if (PctFilter>0)
{
Del[shift] = MathAbs(Filter[shift] - Filter[shift+1]);
double sumdel=0;
for (int j=0;j<=Length-1;j++) sumdel = sumdel+Del[shift+j];
AvgDel[shift] = sumdel/Length;
double sumpow = 0;
for (j=0;j<=Length-1;j++) sumpow+=MathPow(Del[j+shift]-AvgDel[j+shift],2);
double StdDev = MathSqrt(sumpow/Length);
double filter = PctFilter * StdDev;
if(MathAbs(Filter[shift]-Filter[shift+1]) < filter ) Filter[shift]=Filter[shift+1];
}
else
filter=0;
if (ColorMode>0)
{
trend[shift] = trend[shift+1];
if (Filter[shift] - Filter[shift+1] > filter) trend[shift] = 1;
if (Filter[shift+1] - Filter[shift] > filter) trend[shift] =-1;
if (trend[shift]>0)
{
UpTrend[shift] = Filter[shift];
if (trend[shift+ColorBarBack]<0) UpTrend[shift+ColorBarBack]=Filter[shift+ColorBarBack];
DnTrend[i] = EMPTY_VALUE;
if (WarningMode>0 && trend[shift+1]<0 && shift==0) PlaySound("alert2.wav");
}
else
if (trend[shift]<0)
{
DnTrend[shift] = Filter[shift];
if (trend[shift+ColorBarBack]>0) DnTrend[shift+ColorBarBack]=Filter[shift+ColorBarBack];
UpTrend[shift] = EMPTY_VALUE;
if (WarningMode>0 && trend[shift+1]>0 && shift==0) PlaySound("alert2.wav");
}
}
}
//----------
string Message;
if ( trend[2]<0 && trend[1]>0 && Volume[0]>1 && !UpTrendAlert)
{
Message = " "+Symbol()+" M"+Period()+": HMA Signal for BUY";
if ( AlertMode>0 ) Alert (Message);
UpTrendAlert=true; DownTrendAlert=false;
}
if ( trend[2]>0 && trend[1]<0 && Volume[0]>1 && !DownTrendAlert)
{
Message = " "+Symbol()+" M"+Period()+": HMA Signal for SELL";
if ( AlertMode>0 ) Alert (Message);
DownTrendAlert=true; UpTrendAlert=false;
}
//---- done
return(0);
}
Comments