Volume Profile for Opening Range Breakout (ORB) Indicator for ThinkorSwim



Here is an Opening Range Breakout (ORB) indicator for ThinkorSwim with Volume Profile included.

thinkScript Code

Rich (BB code):
# Volume Profile for ORB
# V01.05.02.2018
# TOS Volume Profile with cond altered for a user input Time Range. Labels added for ORH, ORL, OR POC, Opening Range Value Percents upper and lower.
# For Intraday use only

input valueAreaPercent = 70.0;
input opacity = 15;
input RthBegin = 0930;
input OREnd = 1000;
input TimeLength = 30; #hint TimeLenght: In Minutes

def o = open;
def h = high;
def l = low;
def c = close;
def x = BarNumber();
def t = GetTime();
def RTS = RegularTradingStart(GetYYYYMMDD());
def RTE = RegularTradingEnd(GetYYYYMMDD());
def Active = SecondsFromTime(RthBegin) >= 0 and
SecondsTillTime(OREnd) > 0;
def firstBar = if Active and !Active[1]
then x
else Double.NaN;
def agg = GetAggregationPeriod();
def ORperiod_1 = if t crosses above RTS - agg + 300000
then Round(((Highest(h, 3) + Lowest(l, 3)) / 2) / TickSize(), 0) * TickSize()
else ORperiod_1[1];
plot OR_M = if x >= HighestAll(firstBar)
then HighestAll(if IsNaN(c[-1])
then ORperiod_1
else Double.NaN)
else Double.NaN;
AddChartBubble(x == firstBar, OR_M, "ORM", OR_M.TakeValueColor());
def timeSegment = (SecondsFromTime(0000) / 60) % TimeLength == 0;
def profiles = 1440 / TimeLength; # Profiles for 24 hours
def cond = if Active and !Active[1]
then 1
else timeSegment;
profile vol = VolumeProfile("startNewProfile" = cond,
"onExpansion" = 0,
"numberOfProfiles" = 20,
"pricePerRow" = TickSize(),
"value area percent" = valueAreaPercent);
def pc = if IsNaN(vol.GetPointOfControl())
then pc[1]
else vol.GetPointOfControl();
def hVA = if IsNaN(vol.GetHighestValueArea())
then hVA[1]
else vol.GetHighestValueArea();
def lVA = if IsNaN(vol.GetLowestValueArea())
then lVA[1]
else vol.GetLowestValueArea();
def hProfile = if IsNaN(vol.GetHighest())
then hProfile[1]
else vol.GetHighest();
def lProfile = if IsNaN(vol.GetLowest())
then lProfile[1]
else vol.GetLowest();
def POC_ = if Active
then Round(pc / TickSize(), 0) * TickSize()
else POC_[1];
plot POC = if x >= HighestAll(firstBar)
then HighestAll(if IsNaN(c[-1])
then POC_
else Double.NaN)
else Double.NaN;
def ProfileHigh_ = if Active
then hProfile
else ProfileHigh_[1];
plot ProfileHigh = if x >= HighestAll(firstBar)
then ProfileHigh_
else Double.NaN;
def ProfileLow_ = if Active
then lProfile
else ProfileLow_[1];
plot ProfileLow = if x >= HighestAll(firstBar)
then ProfileLow_
else Double.NaN;
def VAHigh_ = if Active
then Round(hVA / TickSize(), 0) * TickSize()
else VAHigh_[1];
plot VAHigh = if x >= HighestAll(firstBar)
then HighestAll(if IsNaN(c[-1])
then VAHigh_
else Double.NaN)
else Double.NaN;
def VALow_ = if Active
then Round(lVA / TickSize(), 0) * TickSize()
else VALow_[1];
plot VALow = if x >= HighestAll(firstBar)
then HighestAll(if IsNaN(c[-1])
then VALow_
else Double.NaN)
else Double.NaN;
vol.Show(color.current, Color.YELLOW, Color.current, opacity);
def bubble = IsNaN(c[2]) and !IsNaN(c[3]);
AddChartBubble(bubble, VAHigh, "OR %" + valueAreaPercent, VAHigh.TakeValueColor(), yes);
AddChartBubble(bubble, VALow, "OR %" + valueAreaPercent, VALow.TakeValueColor(), no);
AddChartBubble(bubble, POC, "OR POC", POC.TakeValueColor(), no);
AddChartBubble(bubble, ProfileHigh, "ORH", ProfileHigh.TakeValueColor(), yes);
AddChartBubble(bubble, ProfileLow, "ORL", ProfileLow.TakeValueColor(), no);
AddVerticalLine(Active and !Active[1], "RTH", Color.CYAN, Curve.SHORT_DASH);
AddVerticalLine(!Active and Active[1], "ORend", Color.CYAN, Curve.SHORT_DASH);
AddVerticalLine(t crosses above RTE, "RTHend", Color.CYAN, Curve.SHORT_DASH);
def prevClose = if t crosses above RTE
then vwap
else prevClose[1];
def prevCloseBar = if t crosses above RTE
then BarNumber()
else Double.NaN;
plot prevCloseLine = if x >= HighestAll(prevCloseBar)
then HighestAll(if IsNaN(c[-1])
then prevClose
else Double.NaN)
else Double.NaN;
AddChartBubble(x == HighestAll(x), prevCloseLine, "RTH C", prevCloseLine.TakeValueColor(), no);
def RTHopen = if Active and !Active[1]
then o
else RTHopen[1];
plot RTHopen_ = if x >= HighestAll(firstBar)
then HighestAll(if IsNaN(c[-1])
then RTHopen
else Double.NaN)
else Double.NaN;
AddChartBubble(x == HighestAll(x), RTHopen, "RTH O", RTHopen_.TakeValueColor(), no);
# End Code ORB using Volume Profile

Shareable Link

Last edited:


Well-known member
@BenTen How did this one get left behind?
This is much like a /CL trader I know uses with minimal emphasis on the ORB because she trades 24 hours/day. Crazy Canadian!

Vimal Mittal

Can you help me out showing image of a chart and explain all these ORB and volume indicator how to use for entry and exit?
Prison Mike

Prison Mike

@Vimal Mittal, @barbaros check out the link Ben provided. There are several ORB indicators post on the forum with plenty of information.

@BenTen I was wondering what the shorter yellow lines were? The one related to "opacity" within the input menu? Is it just an indication of lower lows, higher highs, or is it related to volume profile?



Excellent work. Has anyone noticed this? It is an old script to help keep volume relative.

#Hint: <b>Use a minimum of 10 day charts.</b>\nAggregation is limited:\nE-Mini - 5, 15, and 60 minutes\nNYSE -  5,15 and 30 minutes\n<b>Anything else will be a 5 bar average</b>\n<li>Other instruments may not work due to hours
# Notes about trading hours
# First thing to understand is Sunday does not exist and when the market opens on Sunday afternoon it's called Monday
# During the week the chart shows 1600 ... 1614 then jumps to 1630 ... 1729 then jumps again to 1800.  
# 1615,1730 and 1745 are missing.  1615 is always missed at the end of the day even though 1600 and 1630 are there.
# The name of the day changes from Friday to Monday at 1800 on "Sunday" , but
# During the week the name changes at 16:30.
# As you can see this area gets jumbled .
# So
# Monday starts at 1800 runs through 1600 and looses 4 bars due to a later start plus the three that are always lost for a total of 89 bars  
# 96-7 = 89  (Missing -1630,1645,1700,1715,1730,1745, 1615, )
# Remember 1615 is always missed at the end of the day even though 1600 and 1630 are there.
# Tuesday - Friday starts at 1630 runs through 1600 and looses 3 bars for a total of 93 bars    96-3 = 93  (Missing - 1615, 1730,1745)
# When counting back through Monday the count is the same as any other day until it gets to 1715,1700,1645,1615.
# Here it needs to stop because to continue back further runs into the NYSE hours
# To compensate I have defined StandardHours and an individual filter for each day to prevent the average from gathering volume data from the wrong bar
# I've also limited the Aggregation of the charts to 5 15 and 60 on the e-mini and 5,15 and 30 minutes on the NYSE
# Note:
# NYSE Trades 6-1/2 hours a day. It opens at 09:30 and closes at 16:00
# /DX Trades 2100 to 1700 and closes 1700 Friday Opens 1800 Sunday. Monday = 23 Hrs all other days = 21 Hours
# EUR/USA Trades 24 hours a day and closes 17:00 Friday Opens 18:00 Sunday. (ToS provide no Volume)
Last edited:

Similar threads