This technical indicator is designed to provide a smoother, more refined trend line on a trading chart by analyzing price action and filtering out "noise." It goes beyond a simple moving average by employing advanced mathematical logic to ensure that the resulting line reflects significant market movements rather than minor, erratic fluctuations.
Core Logic Overview
The tool operates through a three-stage calculation process:
1. Noise Assessment and Efficiency Ratio The script first looks at a specific window of recent price bars to calculate "Noise." It measures the cumulative sum of price changes within that window. By comparing the total net price movement against this noise, it determines an Efficiency Ratio (ER). This allows the indicator to distinguish between steady, intentional trends and erratic, sideways market movements.
2. The Moving Average Calculation (mAMA) Using the Efficiency Ratio, the script calculates a primary smoothed average. This calculation adjusts how much weight is given to new price data based on whether the market is moving efficiently. If the movement is clear and stable, the indicator reacts; if the movement is choppy and lacks direction, the indicator remains more conservative.
3. The Intelligent Filter (fAMA) This is the final layer of logic that produces the actual line you see on your chart. The script compares the primary smoothed average against a specific "filter" threshold. It looks at two main factors to decide whether to update the line:
- Volatility Check: It measures the standard deviation (how much the average is fluctuating).
- Price Breakout Check: It examines the highs and lows of recent candles to see if the price has actually broken out of its previous range.
How it Behaves in Practice
The primary goal of this logic is stability.
- During a strong trend: If the market moves decisively upward or downward with enough momentum to surpass the filter's sensitivity levels, the line will follow the price closely.
- During consolidation/choppiness: If the price is moving sideways or fluctuating without significant strength, the logic "freezes" the line. Instead of zig-zagging up and down following every tiny price tick, the indicator holds its previous position until a confirmed trend shift occurs.
By combining an Efficiency Ratio with a volatility-based filter, this script aims to provide traders with a clearer visual representation of the prevailing market direction while ignoring the "jitter" of minor price fluctuations.
//+------------------------------------------------------------------+
//| fAMA.mq4 |
//| Copyright © 2005, Profi_R |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, Profi_R"
#property link "rvm_fam@fromru.com"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Black
//---- input parameters
extern int Range=10;
extern int FastMA=2;
extern int SlowMA=30;
extern int filter=50;
extern int n=4;
extern int h=10;
//---- buffers
double fAMA[];
double mAMA[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
string short_name; //????????? ?????????? short_name ???? "?????????"
//---- indicators
IndicatorBuffers(2);
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,fAMA);
SetIndexBuffer(1,mAMA);
//---- name for DataWindow and indicator subwindow label
//?????????? short_name ??????????? ????????? ???????? ?????? ?????????
short_name="fAMA("+Range+","+FastMA+","+SlowMA+","+filter+","+n+","+h+")";
//??? ??????????? ?? ??????? ???????? ?????????? ??????? ????????????
IndicatorShortName(short_name);
SetIndexLabel(0,short_name);//????????? ????? ??? ??????
//----
SetIndexDrawBegin(0,Range); //????????? ????????? ????? ?????????? ??? 0 ??????
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int counted_bars=IndicatorCounted();
//---- TODO: add your code here
int cb,i;
double k1,k2,Noise,ER,SSC,AMA,sdAMA,dAMA;
if(Bars<=Range) return(0);
else
{
k1=2.0/(SlowMA+1);
k2=2.0/(FastMA+1)-k1;
AMA=Close[Bars-Range];
mAMA[Bars-Range]=Close[Bars-Range+1];
for(cb=Bars-counted_bars-Range-1;cb>=0;cb--)
{
Noise=0;
for(i=cb;i<=cb+Range-1;i++)
{
Noise=Noise+MathAbs(Close[i]-Close[i+1]);
}
if(Noise!=0)
{
ER=MathAbs(Close[cb]-Close[cb+Range])/Noise;
}
else
{
ER=0;
}
SSC=(ER*k2+k1);
AMA=AMA+NormalizeDouble(SSC*SSC*(Close[cb]-AMA),4);
mAMA[cb]=AMA;
if(filter<1)
{
fAMA[cb]=mAMA[cb];
}
else
{
for(i=cb;i<=cb+SlowMA-1;i++)
{
sdAMA=sdAMA+MathAbs(mAMA[i]-mAMA[i+1]);
}
dAMA=mAMA[cb]-mAMA[cb+1];
if(dAMA>=0)
{
if(dAMA<NormalizeDouble(filter*sdAMA/(100*SlowMA),4)&&
High[cb]<=High[Highest(NULL,0,MODE_HIGH,n,cb)]+h*Point)
{
fAMA[cb]=fAMA[cb+1];
}
else
{
fAMA[cb]=mAMA[cb];
}
}
else
{
if(MathAbs(dAMA)<NormalizeDouble(filter*sdAMA/(100*SlowMA),4)&&
Low[Lowest(NULL,0,MODE_LOW,n,cb)]-h*Point<Low[cb])
{
fAMA[cb]=fAMA[cb+1];
}
else
{
fAMA[cb]=mAMA[cb];
}
}
sdAMA=0.0;
}
}
}
//----
return(0);
}
//+------------------------------------------------------------------+
Comments