Skip to main content

In AFL section, we’ve mainly discussed strategies that follow trends in the market. However, we tried something different and experimented with a Mean Reversion Trading System, and we were really impressed by how accurate it was and the returns it generated. In this post, we’ll explore this unique system and take a close look at how it performed in historical testing with NSE Nifty. To start, let’s get a clear grasp of what the Mean Reversion system is all about.

Mean Reversion systems operate on the premise that stock prices fluctuate within a predefined range bounded by upper and lower price bands. Prices tend to gravitate toward a median level over time. To trade such a system, a Buy order is placed at the lower end of the range, while a Sell order is placed at the upper end. It’s crucial to exercise caution during any breakout from this range, particularly when accompanied by high trading volumes. Implementing a strict stop-loss strategy is essential when trading Mean Reversion systems. Various indicators can be useful for developing Mean Reversion Trading systems, such as Bollinger Bands, Donchian channels, RSI, and CCI, among others.

For AFL coding tutorials and creating your own trading systems, please visit this link.

 

ParameterValue
Preferred TimeframeIntraday 5 minute
Indicators UsedBollinger Band, ADX
Buy Condition
  • The current closing price is higher than the Bollinger Band’s lower limit, and the previous closing price is lower than the Bollinger Band’s lower limit.
  • ADX is less than 35, indicating a ranging market.
Short Condition
  • The current closing price is lower than the Bollinger Band’s upper limit, and the previous closing price is higher than the Bollinger Band’s upper limit.
  • ADX is less than 35, indicating a ranging market.
Sell Condition
  • Stop Loss is triggered.
  • Target is achieved.
  • Closing price is lower than the Bollinger Band’s lower limit.
  • Short Condition criteria are met.
Cover Condition
  • Stop Loss is triggered.
  • Target is achieved.
  • Closing price is higher than the Bollinger Band’s upper limit.
  • Buy Condition criteria are met.
Stop Loss0.5%
Targets1%
Position Size150 (fixed)
Initial Equity200,000
Brokerage100 per order
Margin10%

AFL Code

				
					//------------------------------------------------------
//  Formula Name:    Mean Reversion Trading System
//  Website:         zerobrokerageclub.com
//------------------------------------------------------

_SECTION_BEGIN("Mean Reversion Trading System");
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 ) ) ));

SetTradeDelays( 1, 1, 1, 1 );
SetOption( "InitialEquity", 200000);
SetOption("FuturesMode" ,True);
SetOption("MinShares",1);
SetOption("CommissionMode",2);
SetOption("CommissionAmount",100);
SetOption("AccountMargin",10);
SetOption("RefreshWhenCompleted",True);
SetPositionSize(150,spsShares);
SetOption( "AllowPositionShrinking", True );

BuyPrice=Open;
SellPrice=Open;
ShortPrice=Open;
CoverPrice=Open;

Periods =optimize("Periods",110,10,200,20);
Width =optimize("width",2,1,10,1);
MAPeriods = 200;
BBColor = colorOrange;
Style = 0;
bTop=BBandTop( Close, Periods, Width );
bBottom=BBandBot( Close, Periods, Width );
ADXPeriods=optimize("ADXPeriods",10,2,20,1);


BuyCondition=IIf(Ref(C,-1)<bBottom AND close>bBottom AND ADX(ADXPeriods)<35,1,0);
ShortCondition=IIf(Ref(C,-1)>bTop AND close<bTop AND ADX(ADXPeriods)<35,1,0);


Buy = IIf(Ref(C,-1)<bBottom AND close>bBottom AND ADX(ADXPeriods)<35,1,0);
Short = IIf(Ref(C,-1)>bTop AND close<bTop AND ADX(ADXPeriods)<35,1,0);


BarsSinceBuy=BarsSince(BuyCondition);
BarsSinceShort=BarsSince(ShortCondition);

LastBuyPrice=ValueWhen(Buy AND BarsSinceBuy<BarsSinceShort,BuyPrice);
LastShortPrice=ValueWhen(Short AND BarsSinceShort<BarsSinceBuy,ShortPrice);

StopLoss=optimize("SL",0.5,0.2,1,0.2);
Target=optimize("Target",1,0.5,5,0.5);

BuySL=BarsSinceBuy<BarsSinceShort AND Close<=LastBuyPrice-LastBuyPrice*(Stoploss/100);
ShortSL=BarsSinceShort<BarsSinceBuy AND Close>=LastShortPrice+LastBuyPrice*(Stoploss/100);
BuyTarget=BarsSinceBuy<BarsSinceShort AND Close>=LastBuyPrice+LastBuyPrice*(Target/100);
ShortSL=BarsSinceShort<BarsSinceBuy AND Close<=LastShortPrice-LastBuyPrice*(Target/100);

Sell=Short OR Close<bBottom OR BuySL OR BuyTarget;
Cover=Buy OR Close>bTop OR ShortSL OR BuyTarget;



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



ApplyStop(Type=0,Mode=1,Amount=StopLoss);
ApplyStop(Type=1,Mode=1,Amount=Target);

printf("\nBuy : " + Buy );
printf("\nShort : " + Short );
printf("\nCover : " + Cover );
printf("\nSell : " + Sell );
printf("\nBuyPrice : " + BuyPrice );
printf("\nShortPrice : " + ShortPrice );
printf("\nLastBuyPrice : "+ LastBuyPrice);
printf("\nLastShortPrice : "+ LastShortPrice);
printf("\nBuyCondition : "+ BuyCondition);
printf("\nShortCondition : "+ ShortCondition);
printf("\nBuySL : "+BuySL); 
printf("\nShortSL : "+ShortSL);
 
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 
Plot( bTop, "BBTop" + _PARAM_VALUES(), BBColor , Style ); 
Plot( bBottom, "BBBot" + _PARAM_VALUES(), BBColor , Style ); 


/* 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(Cover, shapeSquare, shapeNone),colorGreen, 0, L, Offset=-40);
PlotShapes(IIf(Cover, shapeSquare, shapeNone),colorLime, 0,L, Offset=-50);
PlotShapes(IIf(Cover, 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);
PlotShapes(IIf(Short, shapeSquare, shapeNone),colorRed, 0, H, Offset=40);
PlotShapes(IIf(Short, shapeSquare, shapeNone),colorOrange, 0,H, Offset=50);
PlotShapes(IIf(Short, shapeDownArrow, shapeNone),colorWhite, 0,H, Offset=-45);

_SECTION_END();	
				
			

AFL Screenshot

Mean-Reversion
Backtest Report

ParameterValue
Fixed Position Size
Initial Capital200,000
Final Capital378,919.40
Scrip NameNSE Nifty
Backtest Period14-Jan-2015 to 29-04-2016
Timeframe5 Minutes
Net Profit %89.46%
Annual Return %61.91%
Number of Trades114
Winning Trade %32.46%
Average Holding Period25.17 periods
Max Consecutive Losses9
Max System % Drawdown-10.78%
Max Trade % Drawdown-7.95%

You can find the detailed backtest report here

Equity Curve

Equity Curve Mean Reversion

Additional Amibroker settings for backtesting

Navigate to Symbol → Information, and define the lot size and margin prerequisites. The image below illustrates a lot size of 75 and a 10% margin requirement for NSE Nifty:

Symbol Info Nifty