Rajandran R Creator of OpenAlgo - OpenSource Algo Trading framework for Indian Traders. Telecom Engineer turned Full-time Derivative Trader. Mostly Trading Nifty, Banknifty, High Liquid Stock Derivatives. Trading the Markets Since 2006 onwards. Using Market Profile and Orderflow for more than a decade. Designed and published 100+ open source trading systems on various trading tools. Strongly believe that market understanding and robust trading frameworks are the key to the trading success. Building Algo Platforms, Writing about Markets, Trading System Design, Market Sentiment, Trading Softwares & Trading Nuances since 2007 onwards. Author of Marketcalls.in

Range Filter – Trading Strategy – Amibroker – Better Trend Following Indicator

4 min read

Range Filter is a non-ATR-based trend following strategy inspired by Tradingview Pinescript coder – DonovanWall. According to him, Range Filter is an experimental study designed to filter out minor price action for a clearer view of trends. Here is the Amibroker Trend Following Strategy code based on the Range Filter.

How Range Filter is Calculated?

1), a smooth average price range is calculated for the basis of the filter and multiplied by a specified amount.
2)the filter is calculated by gating price movements that do not exceed the specified range.
3)the target ranges are plotted to display the prices that will trigger filter movement.

Strategy Timeframe : 15mins

Trading Symbol: Nifty Futures

Trading Commissions Used : 0.02% per leg

Historical Data Backtesting Period: 2011 – 2022

Position Sizing : 1 Lot (Fixed Lot)

Equity Curve

Drawdown Curve

Backtesting Report

Absolute Profit Table (in Thousands)

Range Filter – Amibroker AFL Code

//Coded by Rajandran R - www.marketcalls.in / www.algomojo.com
//Code Inspired from Tradingview Pinescript
//Original Coded by : DonovanWall
//Tradingview Source Code : https://in.tradingview.com/script/lut7sBgG-Range-Filter-DW/
//Coded Date : 23rd - Aug 2022

_SECTION_BEGIN("Range Filter - Trading Strategy");

SetPositionSize(1*RoundLotSize,spsShares);


src = ParamField("Source",3);

// Sampling Period

per = param("Sampling Period",15,5,200,5);

// Range Multiplier

mult = param("Range Multiplier",2.5,1,5,0.5);


upward = 0;
dnward = 0;

// Smooth Average Range

function smoothrange(x, t, m)
{

	wper = t * 2 - 1;
    avrng = ema(abs(x - Ref(x,-1)), t);
    smoothrng = ema(avrng, wper) * m;
    return smoothrng;

}

smrng = smoothrange(src, per, mult);

// Range Filter

function rngfilter(x, r)
{

	rngfilt = x;
	//rngfilt := x > nz(rngfilt[1]) ? x - r < nz(rngfilt[1]) ? nz(rngfilt[1]) : x - r : x + r > nz(rngfilt[1]) ? nz(rngfilt[1]) : x + r
    for(i=1;i<BarCount;i++)
    {
    
    if(x[i] > rngfilt[i-1])
    {
		if((x[i] - r[i]) < rngfilt[i-1])
		{
		rngfilt[i] = rngfilt[i-1];
		}
		else
		{
			rngfilt[i] = x[i]-r[i];
		
		}
    }
    else
    {
	  
		if((x[i] + r[i])  > rngfilt[i-1])
		{
		
		
		rngfilt[i] = rngfilt[i-1];
		
		
		}
		else
		{
		rngfilt[i] =  x[i] + r[i];
		}
		}
    }//end of for loop
 return rngfilt;
}

filt = rngfilter(src, smrng);
upward = 0;
downward = 0;
// Filter Direction

for(i=1;i<BarCount;i++)
{

if(filt[i] > filt[i-1])
{
upward[i] = upward[i-1] + 1;
}
else{

 if(filt[i] < filt[i-1])
 {
	upward[i] = 0;
 
 }
 
 else
 {
 upward[i] = upward[i-1];
 }
 
 }
  


}//end of for loop


for(i=1;i<BarCount;i++)
{

if(filt[i] < filt[i-1])
{
downward[i] = downward[i-1] + 1;
}
else{

 if(filt[i] < filt[i-1])
 {
	dnward[i] = 0;
 
 }
 
 else
 {
 dnward[i] = dnward[i-1];
 }
  


}//end of for loop



}//end of range filter function

// Target Bands

hband = filt + smrng;
lband = filt - smrng;

Plot(hband,"H-Band",colorBlue,styleLine);
Plot(lband,"L-Band",colorRed,styleLine);

longCond = (src > filt and src > Ref(src,-1) and upward > 0) or (src > filt and src < Ref(src,-1) and upward > 0);
shortCond = (src < filt and src <  Ref(src,-1) and downward > 0) or (src < filt and src > Ref(src,-1) and downward > 0);



Buy = ExRem(longCond,shortCond);
Sell = ExRem(shortCond,longCond);
Short = Sell;
Cover = Buy;

Buy = Ref(Buy,-1);
Sell = Ref(Sell,-1);
Short = Ref(Short,-1);
Cover = Ref(Cover,-1);

BuyPrice = ValueWhen(Buy,Open);
SellPrice = ValueWhen(Sell,Open);
ShortPrice = ValueWhen(Short,Open);
CoverPrice = ValueWhen(Cover,Open);



buycontinue = Flip(Buy,Sell);
shortcontinue = Flip(Short,Cover);

barcolor =  IIf(buycontinue,colorGreen,colorRed);


for( i = 0; i < BarCount; i++ ) 
 { 
if( Buy[i] ) PlotText("Buy",i,L[i],colorWhite,colorLime,-70);
if( Short[i] ) PlotText("Short",i,H[i],colorWhite,colorRed,70);
//if( Sell[i] ) PlotText( "Selln@" + C[ i ], i, H[ i ]+dist[i], colorRed, colorYellow ); 
 } 


/* Plot Buy and Sell Signal Arrows */
PlotShapes(IIf(Buy, shapeSquare, shapeNone),colorGreen, 0, L, Offset=-40);
PlotShapes(IIf(Buy, shapeSquare, shapeNone),colorLime, 0,L, Offset=-50);                      
PlotShapes(IIf(Buy, shapeUpArrow, shapeNone),colorWhite, 0,L, Offset=-45); 
PlotShapes(IIf(Sell, shapeSquare, shapeNone),colorRed, 0, H, Offset=40);
PlotShapes(IIf(Sell, shapeSquare, shapeNone),colorOrange, 0,H, Offset=50);                      
PlotShapes(IIf(Sell, shapeDownArrow, shapeNone),colorWhite, 0,H, Offset=-45);


sig=0;
bars=0;
tar1=tar2=tar3=null;

for(i=BarCount-1;i>1;i--)

{

if(Buy[i] == 1)

{

entry = open[i];

sig = 1;  //flag contains 1 when buy is valid

tar1 = entry + (entry * .0050);

tar2 = entry + (entry * .0092);

tar3 = entry + (entry * .0179);

 

bars = i;

i = 0;

}

if(Short[i] == 1)

{

sig = -1; //flag contains -1 wjhen short is valid

entry = open[i];


tar1 = entry - (entry * .0050);

tar2 = entry - (entry * .0112);

tar3 = entry - (entry * .0212);

 

 

bars = i;  // i - holds the value of bar index, computing the barindex value when the signal happened

i = 0;

}

}//for loop



Offset = 20;

Clr = IIf(sig == 1, colorLime, colorRed);


 

//plot target lines

Plot(LineArray(bars-Offset, tar1, BarCount-1, tar1,1), "", Clr, styleLine|styleDots, Null, Null, Offset);

Plot(LineArray(bars-Offset, tar2, BarCount-1, tar2,1), "", Clr, styleLine|styleDots, Null, Null, Offset);

Plot(LineArray(bars-Offset, tar3, BarCount-1, tar3,1), "", Clr, styleLine|styleDots, Null, Null, Offset);






_SECTION_END();


_SECTION_BEGIN("Signal Dashboard");

messageboard = ParamToggle("Message Board","Show|Hide",1);
upcolor = ParamColor("Up Color",colorBlue);
dncolor = ParamColor("Down Color",colorRed);



if (messageboard == 1 )

{

GfxSelectFont( "Tahoma", 13, 100 );

GfxSetBkMode( 1 );

GfxSetTextColor( colorWhite );


//Dashboard color changes dynamically according to the signals continuation
color = IIf(buycontinue, upcolor, IIf(shortcontinue, dncolor, Null));



GfxSelectSolidBrush(SelectedValue(color));


pxHeight = Status( "pxchartheight" ) ;

xx = Status( "pxchartwidth");

Left = 1100;
width = 310;

x = 5;
x2 = 360;
y = pxHeight;

sigstatus = WriteIf(buycontinue,"Buy Signal @ ","Sell Signal @");

 

GfxSelectPen( colorGreen, 1); // broader color
GfxRoundRect( x, y - 98, x2, y , 7, 7 ) ;
GfxTextOut( ( "Marketcalls - Range Filter"),13,y-90);
GfxTextOut( (" "),27,y-100);

if(SelectedValue(Buycontinue))
{
GfxTextOut( ("Last " + sigstatus + " Signal came " + BarsSince(Buy) * Interval()/60 + " mins ago"), 13, y-70) ; // The text format location
GfxTextOut( ("" + sigstatus + " : " + ValueWhen(Buy,BuyPrice)), 13, y-50);
GfxTextOut( ("Profit/Loss : " + NumToStr(Close-ValueWhen(Buy,BuyPrice),1.2)), 13, y-30);
}

if(SelectedValue(Shortcontinue))
{
GfxTextOut( ("Last " + sigstatus + " Signal came " + BarsSince(short) * Interval()/60 + " mins ago"), 13, y-70) ; // The text format location
GfxTextOut( ("" + sigstatus + " : " + ValueWhen(Short,ShortPrice)), 13, y-50);
GfxTextOut( ("Current P/L : " + NumToStr(ValueWhen(Short,ShortPrice)-Close,1.2)), 13, y-30);
}


//GfxTextOut( ("Trailing SL : " + Ref(TrendSL,-1) + " (" + WriteVal(IIf(sig == -1,entry-sl,sl-entry), 2.2) + ")"), 13, y-40);





}


_SECTION_END();

_SECTION_BEGIN("Top Dashboard");

X0 = 10;
Y0 = 20;

procedure DrawData (Text, x1, y1, x2, y2, colorFrom, colorTo)
{
	GfxSetOverlayMode(0);
	GfxSelectFont("Verdana", 8.5, 700);
	GfxSetBkMode(1);
	GfxGradientRect(x1, y1, x2, y2, colorFrom, colorTo);
	GfxDrawText(Text, x1, y1, x2, y2, 32|1|4|16);
}


DrawData (Name(), X0, Y0, X0+150, Y0+20, colorGrey40, colorblack);
DrawData (Date(), X0+155, Y0, X0+320, Y0+20, colorGrey40, colorblack);
DrawData ("Open : " + Open, X0+325, Y0, X0+450, Y0+20, colorGrey40, colorblack);
DrawData ("Close : " + Close, X0+455, Y0, X0+580, Y0+20, colorGrey40, colorblack);
DrawData ("High : " + High, X0+585, Y0, X0+710, Y0+20, colorGrey40, colorblack);
DrawData ("Low : " + Low, X0+715, Y0, X0+840, Y0+20, colorGrey40, colorblack);


_SECTION_END();




_SECTION_BEGIN("Price");
SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", barcolor, styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 
_SECTION_END();
Rajandran R Creator of OpenAlgo - OpenSource Algo Trading framework for Indian Traders. Telecom Engineer turned Full-time Derivative Trader. Mostly Trading Nifty, Banknifty, High Liquid Stock Derivatives. Trading the Markets Since 2006 onwards. Using Market Profile and Orderflow for more than a decade. Designed and published 100+ open source trading systems on various trading tools. Strongly believe that market understanding and robust trading frameworks are the key to the trading success. Building Algo Platforms, Writing about Markets, Trading System Design, Market Sentiment, Trading Softwares & Trading Nuances since 2007 onwards. Author of Marketcalls.in

Interactive Brokers – Smart Order Chart Trading Module using…

The IB Controller is an interface designed to facilitate automatic trading with AmiBroker and Interactive Brokers (IB) TWS (Trader Workstation). It serves as a...
Rajandran R
8 min read

Introducing OpenAlgo V1.0: The Ultimate Open-Source Algorithmic Trading Framework…

OpenAlgo V1.0 is an open-source algorithmic trading platform to automate your trading strategies using Amibroker, Tradingview, Metatrader, Python etc. Designed with the modern trader...
Rajandran R
2 min read

[Live Coding Webinar] Build Your First Trading Bridge for…

In this course, you will be learning to build your own trading bridge using Python. This 60-minute session is perfect for traders, Python enthusiasts,...
Rajandran R
1 min read

4 Replies to “Range Filter – Trading Strategy – Amibroker – Better…”

  1. thank you sir but shows some error .

    if( Buy[i] ) PlotText(“Buy”,i,L[i],colorWhite,colorLime,-70);
    error16 toomany arguements.

    -S.Ghaneshakumar

  2. Sir, maybe using sell and cover signals as exit points for entries might work wonders. For ex if we are on SHORT side and it touches the Down color bar it would book profit in exit and wait. If a breakout happens to downside by breaking the down color bar area let it reenter with again the next downside color bar being the target. Same logc with upside as well

Leave a Reply

Get Notifications, Alerts on Market Updates, Trading Tools, Automation & More