Skip to main content

Opening Range Breakout (ORB) Trading Strategy

Opening Range Breakout (ORB) is probably the most popular intraday trading system. It takes into account the volatility of the first few minutes of trading hours, and any breakout above or below the price range of this period is considered a possible trade. The credit behind this system goes to Sir Tony Crabel who published a book in 1990 to explain this strategy in detail.

How to trade Opening Range Breakout?

First of all, you have to decide a specific period in the intraday chart which would be called as Opening range period. This period may vary depending on the security you are trading. The high made during this period is called the Opening Range High, and the low is called the Opening Range Low. The system gives a Buy signal when the price crosses above the Opening range while it gives a Sell signal when the price crosses below the Opening range. Aggressive traders may take the trade as soon as the breakout happens, while conservative traders may wait for a specific period or price move before entering. The time range between which the trade can be taken is called Trade Start time and Trade End time. There can be predefined targets and stop-loss depending on your risk management, but all positions should be necessarily squared off at the end of the day.

Below are the parameters for the AFL we are going to discuss below:

  • Opening Range Period: 5 Minutes
  • Trade Start Time: 55 minutes after Market Open
  • Trade End Time: 70 minutes after Market Open

Please note that this AFL is available in its raw form in most of the online forums and communities. We have just optimized it for Nifty Futures and made it backtestable.

AFL Overview

ParameterValue
Preferred TimeframeIntraday 5 minute
Indicators UsedNone
Buy Condition
  • The current candle high is greater than the Opening Range High.
  • Between 55 to 70 minutes of Market Open time.
Short Condition
  • The current candle low is less than the Opening range Low.
  • Between 55 to 70 minutes of Market Open time.
Sell Condition
  • Stop Loss hit
  • Target Met
  • End of Day
Cover Condition
  • Stop Loss hit
  • Target Met
  • End of Day
Stop Loss0.5%
Targets3%
Position Size150 (fixed)
Initial Equity200000
Brokerage50 per order
Margin10%

AFL Code

				
					//------------------------------------------------------
//  Formula Name:    Intraday Opening Range Breakout system
//  Website:         https://zerobrokerageclub.com/
//------------------------------------------------------


function ParamOptimize( pname, defaultval, minv, maxv, step ) 
{ 
return Optimize( pname, 
Param( pname, defaultval, minv, maxv, step ), 
minv, maxv, step ); 
} 
 
_SECTION_BEGIN("Intraday Opening Range Breakout system");  

SetOption( "InitialEquity", 200000);
SetOption("FuturesMode" ,True);
SetOption("MinShares",1);
SetOption("CommissionMode",2);
SetOption("CommissionAmount",50);
SetOption("AccountMargin",10);
SetOption("RefreshWhenCompleted",True);
SetPositionSize(150,spsShares);
SetOption( "AllowPositionShrinking", True );
 
//--Intraday time frame  
TimeFrameSet(in5Minute); 
TimeFrameInMinutes = 5; 
 
//--Define all params  
EntryBufferPct = ParamOptimize("Entry Buffer %", 0, 0, 2, 0.1); 
SLPct = ParamOptimize("SL %", 0.5, 0.5, 2, 0.5); 
TargetPct = ParamOptimize("Target %", 3, 0, 3, 0.5); 
MaxTarget = 100; 
TargetPct = IIf(TargetPct == 0, MaxTarget, TargetPct);  
EntryTimeStart = ParamOptimize("Entry Time Start (Minutes)", 55, 5, 120, 5); 
EntryBarStart = floor(EntryTimeStart/TimeFrameInMinutes) - 1; 
EntryTimeEnd = ParamOptimize("Entry Time End (Minutes)", 70, 10, 300, 10); 
EntryBarEnd = floor(EntryTimeEnd/TimeFrameInMinutes) - 1; 
EntryBarEnd = IIf(EntryBarEnd < EntryBarStart, EntryBarStart, EntryBarEnd);   
 
//--Plot Price Candle Chart 
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( Close, "Price", colorWhite, styleCandle );
 
//--New Day & Time. End Day & Time . End Day & Time is null till end of day 1   
NewDay = (Day()!= Ref(Day(), -1)) OR BarIndex() == 0;  
printf("\n NewDay  : " + NewDay );  
EndDay = (Day()!= Ref(Day(), 1));  
printf("\n EndDay  : " + EndDay ); 
FirstBarTime = ValueWhen(NewDay,TimeNum(),1);  
EndTime = ValueWhen(EndDay,TimeNum(),1); 
SquareOffTime = EndTime; 
 
//--Calculate ORB, and SL 
HighestOfDay = HighestSince(NewDay,H,1);  
LowestOfDay = LowestSince(NewDay,L,1);  
ORBH = ValueWhen(NewDay,HighestOfDay ,1) * (1 + (EntryBufferPct/100));  
ORBL = ValueWhen(NewDay,LowestOfDay ,1) * (1 - (EntryBufferPct/100));  

 
//--Find Buy, Sell, Short & Cover Signals 
BarsSinceNewDay = BarsSince(NewDay);  
BuySignal = (H >= ORBH) AND (BarsSinceNewDay  > EntryBarStart);  
printf("\nBuySignal : " + BuySignal );  
ShortSignal = (L <= ORBL) AND (BarsSinceNewDay  > EntryBarStart) ;  
printf("\nShortSignal  : " + ShortSignal );  
BarsSinceLastBuySignal = (BarsSince(Ref(BuySignal,-1)) + 1); 
BarsSinceLastShortSignal = (BarsSince(Ref(ShortSignal,-1)) + 1); 
BarsSinceLastEntrySignal = Min(BarsSinceLastBuySignal, BarsSinceLastShortSignal); 
BothEntrySignalsNull = IsNull(BarsSinceLastBuySignal) AND IsNull(BarsSinceLastShortSignal); //true for start of Day 1 
printf("\n\nBarsSinceNewDay : " + BarsSinceNewDay );  
printf("\nBarsSinceLastBuySignal : " + BarsSinceLastBuySignal );  
printf("\nBarsSinceLastShortSignal : " + BarsSinceLastShortSignal );  
printf("\n BarsSinceLastEntrySignal : " + BarsSinceLastEntrySignal);  
Buy = (H >= ORBH) AND (BarsSinceNewDay  > EntryBarStart) AND (BarsSinceNewDay <= EntryBarEnd) AND ((BarsSinceNewDay < BarsSinceLastEntrySignal) OR BothEntrySignalsNull );  
Short = (L <= ORBL) AND (BarsSinceNewDay  > EntryBarStart) AND (BarsSinceNewDay <= EntryBarEnd) AND ((BarsSinceNewDay < BarsSinceLastEntrySignal) OR BothEntrySignalsNull );  
BuyPrice = IIf(Buy, Max(ORBH,O), Null);  
ShortPrice = IIf(Short, Min(ORBL,Open), Null);  

ORBHSL = ValueWhen(BuyPrice,BuyPrice) * (1-(SLPct/100));   
ORBLSL = ValueWhen(ShortPrice,ShortPrice) * (1+(SLPct/100)); 
ORBHTarget = ValueWhen(BuyPrice,BuyPrice) * (1+(TargetPct/100)); 
ORBLTarget = ValueWhen(ShortPrice,ShortPrice) * (1-(TargetPct/100)); 

Sell = (L <= ORBHSL) OR (H >= ORBHTarget) OR (TimeNum() > SquareOffTime-1) AND (BarsSinceNewDay > BarsSinceLastBuySignal);  
Cover = (H >= ORBLSL) OR (L <= ORBLTarget) OR (TimeNum() > SquareOffTime-1) AND (BarsSinceNewDay > BarsSinceLastShortSignal);  

SellPrice = IIf(Sell, IIf(H >= ORBHTarget, ORBHTarget, Max(ORBHSL, L)), Null);  
CoverPrice = IIf(Cover, IIf(L <= ORBLTarget, ORBLTarget, Min(ORBLSL, H)), Null);  

printf("\nBuy : " + Buy );  
printf("\nSell : " + Sell );  
printf("\nShort : " + Short );  
printf("\nCover : " + Cover );  

printf("\nORBH : " + ORBH );  
printf("\nORBL : " + ORBL );  
printf("\nBuyPrice : " + BuyPrice );  
printf("\nShortPrice : " + ShortPrice );  

printf("\nORBHSL : " + ORBHSL );  
printf("\nORBLSL : " + ORBLSL );  
printf("\nORBHTarget : " + ORBHTarget );  
printf("\nORBLTarget : " + ORBLTarget );  
 
//--Handle if ORB broken both sides on same bar 
//--And remove duplicate Sell & Cover signals, since ExRem did not work as needed when Buy & Sell on same bar 
orbBothSides = IIf(Buy AND Short, 1, 0);  
Buy = IIf(orbBothSides AND C <= O, 0, Buy);  
Short = IIf(orbBothSides AND C > O, 0, Short);  
Sell = IIf(orbBothSides AND C > O AND (L <= ORBHSL), 1, Sell);  
Sell = IIf((BarsSince(Buy) < (BarsSince(Ref(Sell,-1))+1)) OR (BarsSince(Buy) AND IsNull(BarsSince(Ref(Sell,-1)))),Sell,0); 
Cover = IIf(orbBothSides AND C <= O AND (H >= ORBLSL), 1, Cover);  
Cover = IIf((BarsSince(Short) < (BarsSince(Ref(Cover,-1))+1)) OR (BarsSince(Short) AND IsNull(BarsSince(Ref(Cover,-1)))),Cover,0); 


//Plot(IIf(BarsSinceNewDay > BarsSinceLastBuySignal,ORBHSL,NULL),"BuyStopLoss",colorRed,styleDashed); 
//Plot(IIf(BarsSinceNewDay > BarsSinceLastShortSignal,ORBLSL,NULL),"SellStopLoss",colorRed,styleDashed);  
Plot(ORBH,"",colorBlue,styleDots);
Plot(ORBL,"",colorBlue,styleDots);


/* 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);

 
//--Restore time frame  
TimeFrameRestore();  
_SECTION_END();
				
			

AFL Screenshot

The blue dotted line shows the Opening Range.

Opening Range

Backtest Report

ParameterValue
Fixed Position Size
Initial Capital200000
Final Capital662679.55
Backtest Period01-Jan-2015 to 22-03-2016
Timeframe5 Minutes
Net Profit %231.34%
Annual Return %165.97%
Number of Trades259
Winning Trade %54.44%
Average holding Period55.46 periods
Max consecutive losses13
Max system % drawdown-20.02%
Max Trade % drawdown-12.83%

Download the detailed backtest report here.

Equity Curve

This strategy has a very smooth and linear equity curve with minimum drawdowns. Check it out.

Equity Curve

Additional Amibroker settings for backtesting

Goto Symbol–>Information, and specify the lot size and margin requirement. The below screenshot shows lot size of 75 and margin requirement of 10% for NSE Nifty:

Symbol Info_Nifty