Opening Range Indicator with Measured Moves and VWAP For ThinkOrSwim

FutureTony

Member
VIP
Hello again,

I'm back with a bit of a different take on the Opening Range. This is a relatively simple indicator that analyzes movement during a specified time period and plots various lines based on that information. I am anchoring a VWAP (with standard deviations) to this start time as well to better judge the prevailing trend. The opening range is usually a daytrading tool and as such this will not display on daily or higher timeframes. There is another similar concept based on the weekly open range but that is a topic for another time.

jTn8jym.png


In the image above, I have added the study twice. Once, from the European session open and once from the US Open. You will see the blue-ish lines representing the opening range for each of those periods with a mid-line and some extended targets based on the range. This study is intended to provide context to your trading system but is not a strategy in and of itself. If you are interested in learning more about why Opening Ranges are important and some different strategies to trade them, there is a more complex study with background information here: Opening Range Breakout.

There are options in this study to show the range as a label in the top left, to show/hide the extended targets and also to add additional 1/4 and 3/4 lines inside of the range. You can also enable bubbles to show that display the OR highs and lows but need to have an expansion area of 5 bars or so to display properly. And finally, there is an option to color your candles if they fall outside of the OR.

The options have two associated timeframes. One for the opening range you want to analyze (eg. 9:30 to 9:45) and another for the period for the lines to draw (eg. 9:30 to 16:00). In the image above, the first version has 2:30 to 3:30 as the European open range and 2:30 to 9:00 as the time to draw the lines. The second version (in the same chart) is 9:30 to 9:45 and then 9:30 to 16:00 for the line display. Hopefully this makes sense.

This study will work best on timeframes less than 1 hour and will perform will on tick charts. Range charts and renko charts will have some difficulties with the study and the VWAP will not work on those at all. This one was pretty fun to build. Please let me know if you have ideas for improvement.

Ruby:
# Opening Range w/VWAP
# Created by @tony_futures
# Inspired by @mighigandolf 's tweets

declare hide_on_daily;
input displayType = { "At timed start", default  "From RTH Start"};
input startTime = 0930;
input End_Time = 0945;
input showTodayOnly = no;
input showLabels = yes;
input showVWAP = yes;
input showVWAPDevs = yes;
def RTH;

switch (displayType) 
{ 
    case "At Timed Start": 
      RTH = secondsFromTime(startTime) >= 0; 
      
    case "From RTH Start": 
      RTH = GetTime() >= RegularTradingStart(GetYYYYMMDD());
}
input anchorTime = 0930;
input anchorEnd = 1600;
def postAnchorTime = if SecondsFromTime(anchorTime) >= 0 then 1 else 0;
def endAchorTime = if SecondsTillTime(anchorEnd) >= 0 then 1 else 0;
def endPlot = secondsFromTime(anchorEnd) >= 0;
def Today = GetLastDay() == GetDay();
def ORActive = (Today OR !showTodayOnly) and RTH and SecondsFromTime(End_Time) < 0;

def ORhigh = if RTH and !RTH[1] then high else if RTH and ORActive and high > ORhigh[1] then high else ORhigh[1];
def ORlow = if RTH and !RTH[1] then low else if RTH and ORActive and low < ORlow[1] then low else ORlow[1];
def OROpen = if RTH and !RTH[1] then open else OROpen[1];
def ORClose = if !ORActive and ORActive[1] then close[1] else ORClose[1];
def ORFullRange = AbsValue(ORHigh - ORLow);
def midPoint = ORLow + (ORFullRange/2);

AddLabel(showLabels, "Open: " + OROpen + " | Close: " + ORClose + " | Range: " + ORFullRange + " |", Color.WHITE);

# setup Colors
DefineGlobalColor("quarterColor", CreateColor(169, 169, 169));
DefineGlobalColor("midColor", CreateColor(132, 76, 130));
DefineGlobalColor("rangeColor", CreateColor(28, 96, 109));
DefineGlobalColor("openColor", CreateColor(109, 84, 44));
DefineGlobalColor("downColor", CreateColor(109, 42, 28));
DefineGlobalColor("upColor", CreateColor(76, 133, 78));
DefineGlobalColor("vwapColor", CreateColor(174, 157, 50));
#

def OREnded = (Today OR !showTodayOnly) and RTH and SecondsFromTime(End_Time) >= 0;
plot ORL = if OREnded and !endPlot then ORlow else Double.NaN;
ORL.SetDefaultColor(GlobalColor("rangeColor"));
ORL.HideBubble();
plot ORH = if OREnded and !endPlot then ORhigh else Double.NaN;
ORH.SetDefaultColor(GlobalColor("rangeColor"));
ORH.HideBubble();
input showMidPoint = yes;

plot mid = if OREnded and !endPlot then midPoint else Double.NaN;
mid.setDefaultColor(GlobalColor("midColor"));
mid.HideBubble();
input showQuarters = no;
def oneQuarter = ORLow + (ORFullRange/4);
def threeQuarter = ORHigh - (ORFullRange/4);
plot oneQLine = if showQuarters and OREnded and !endPlot then oneQuarter else Double.NaN;
oneQLine.setDefaultColor(GlobalColor("quarterColor"));
oneQLine.HideBubble();
plot threeQLine = if showQuarters and OREnded and !endPlot then threeQuarter else Double.NaN;
threeQLine.setDefaultColor(GlobalColor("quarterColor"));
threeQLine.HideBubble();

input showMeasuredTargets = yes;
def upperTarget = (ORHigh + (ORFullRange/2));
plot upper = if showMeasuredTargets and OREnded and !endPlot then upperTarget else Double.NaN;
upper.SetDefaultColor(GlobalColor("upColor"));
upper.HideBubble();
def lowerTarget = (ORLow - (ORFullRange/2));
plot lower = if showMeasuredTargets and OREnded and !endPlot then lowerTarget else Double.NaN;
lower.SetDefaultColor(GlobalColor("downColor"));
lower.HideBubble();
input showMeasuredTargets2 = no;
def upperTarget2 = (ORHigh + (ORFullRange));
plot upper2 = if showMeasuredTargets2 and OREnded and !endPlot then upperTarget2 else Double.NaN;
upper2.SetDefaultColor(GlobalColor("upColor"));
upper2.HideBubble();
def lowerTarget2 = (ORLow - (ORFullRange));
plot lower2 = if showMeasuredTargets2 and OREnded and !endPlot then lowerTarget2 else Double.NaN;
lower2.SetDefaultColor(GlobalColor("downColor"));
lower2.HideBubble();

#plot anchored VWAP for the current day
def  volumeSum = CompoundValue(1, if postAnchorTime and endAchorTime then volumeSum[1] + volume else 0, volume);
def  volumeVwapSum = CompoundValue(1, if postAnchorTime and endAchorTime then volumeVwapSum[1] + volume * vwap else 0, volume * vwap);
def volumeVwap2Sum = CompoundValue(1, if postAnchorTime and endAchorTime then volumeVwap2Sum[1] + volume * Sqr(vwap) else 0, volume * Sqr(vwap));
def price = volumeVwapSum / volumeSum;
def deviation = Sqrt(Max(volumeVwap2Sum / volumeSum - Sqr(price), 0));

input stdDev = 1.0;
def numDevDn = -stdDev;
def numDevUp = stdDev;

plot anchorVWAP = if !showVWAP then Double.NAN else if showVWAP and showTodayOnly and !Today then Double.NaN else if RTH and showVWAP then price else Double.NaN;
anchorVWAP.SetStyle(Curve.FIRM);
anchorVWAP.SetDefaultColor(GlobalColor("vwapColor"));
plot anchorVWAPUpper = if !showVWAPDevs then Double.NaN else if showVWAPDevs and showTodayOnly and !Today then Double.NaN else if RTH and showVWAPDevs then (price + (numDevUp * deviation)) else Double.NaN;
anchorVWAPUpper.SetStyle(Curve.SHORT_DASH);
anchorVWAPUpper.SetDefaultColor(Color.GRAY);
anchorVWAPUpper.HideBubble();
plot anchorVWAPLower = if !showVWAPDevs then Double.NaN else if showVWAPDevs and showTodayOnly and !Today then Double.NaN else if RTH and showVWAPDevs then (price + (numDevDn * deviation)) else Double.NaN;
anchorVWAPLower.SetStyle(Curve.SHORT_DASH);
anchorVWAPLower.SetDefaultColor(Color.GRAY);
anchorVWAPLower.HideBubble();

input colorCandles = no;
AssignPriceColor(if !colorCandles then Color.CURRENT
else if colorCandles and OREnded and high < ORL and high < anchorVWAP then 
    GlobalColor("downColor")
else if colorCandles and OREnded and low > ORH and low > anchorVWAP then 
    GlobalColor("upColor")      
else Color.CURRENT );

input showOpen = yes;
AddVerticalLine(showOpen and Today and RTH and !RTH[1], concat("Open", ""), GlobalColor("openColor"), curve.POINTS);

input showBubbles = no;
def showBubbleNow = !IsNaN(close) and IsNaN(close[-1]);
AddChartBubble(showBubbles and showBubbleNow[1], ORHigh[1], "OR High", Color.GRAY, yes);
AddChartBubble(showBubbles and showBubbleNow[1], ORLow[1], "OR Low", Color.GRAY, no);
 
Last edited:

AlphaOptions

New member
Hello again,

I'm back with a bit of a different take on the Opening Range. This is a relatively simple indicator that analyzes movement during a specified time period and plots various lines based on that information. I am anchoring a VWAP (with standard deviations) to this start time as well to better judge the prevailing trend. The opening range is usually a daytrading tool and as such this will not display on daily or higher timeframes. There is another similar concept based on the weekly open range but that is a topic for another time.

jTn8jym.png


In the image above, I have added the study twice. Once, from the European session open and once from the US Open. You will see the blue-ish lines representing the opening range for each of those periods with a mid-line and some extended targets based on the range. This study is intended to provide context to your trading system but is not a strategy in and of itself. If you are interested in learning more about why Opening Ranges are important and some different strategies to trade them, there is a more complex study with background information here: Opening Range Breakout.

There are options in this study to show the range as a label in the top left, to show/hide the extended targets and also to add additional 1/4 and 3/4 lines inside of the range. You can also enable bubbles to show that display the OR highs and lows but need to have an expansion area of 5 bars or so to display properly. And finally, there is an option to color your candles if they fall outside of the OR.

The options have two associated timeframes. One for the opening range you want to analyze (eg. 9:30 to 9:45) and another for the period for the lines to draw (eg. 9:30 to 16:00). In the image above, the first version has 2:30 to 3:30 as the European open range and 2:30 to 9:00 as the time to draw the lines. The second version (in the same chart) is 9:30 to 9:45 and then 9:30 to 16:00 for the line display. Hopefully this makes sense.

This study will work best on timeframes less than 1 hour and will perform will on tick charts. Range charts and renko charts will have some difficulties with the study and the VWAP will not work on those at all. This one was pretty fun to build. Please let me know if you have ideas for improvement.

Ruby:
# Opening Range w/VWAP
# Created by @tony_futures
# Inspired by @mighigandolf 's tweets

declare hide_on_daily;
input displayType = { "At timed start", default  "From RTH Start"};
input startTime = 0930;
input End_Time = 0945;
input showTodayOnly = no;
input showLabels = yes;
input showVWAP = yes;
input showVWAPDevs = yes;
def RTH;

switch (displayType)
{
    case "At Timed Start":
      RTH = secondsFromTime(startTime) >= 0;
     
    case "From RTH Start":
      RTH = GetTime() >= RegularTradingStart(GetYYYYMMDD());
}
input anchorTime = 0930;
input anchorEnd = 1600;
def postAnchorTime = if SecondsFromTime(anchorTime) >= 0 then 1 else 0;
def endAchorTime = if SecondsTillTime(anchorEnd) >= 0 then 1 else 0;
def endPlot = secondsFromTime(anchorEnd) >= 0;
def Today = GetLastDay() == GetDay();
def ORActive = (Today OR !showTodayOnly) and RTH and SecondsFromTime(End_Time) < 0;

def ORhigh = if RTH and !RTH[1] then high else if RTH and ORActive and high > ORhigh[1] then high else ORhigh[1];
def ORlow = if RTH and !RTH[1] then low else if RTH and ORActive and low < ORlow[1] then low else ORlow[1];
def OROpen = if RTH and !RTH[1] then open else OROpen[1];
def ORClose = if !ORActive and ORActive[1] then close[1] else ORClose[1];
def ORFullRange = AbsValue(ORHigh - ORLow);
def midPoint = ORLow + (ORFullRange/2);

AddLabel(showLabels, "Open: " + OROpen + " | Close: " + ORClose + " | Range: " + ORFullRange + " |", Color.WHITE);

# setup Colors
DefineGlobalColor("quarterColor", CreateColor(169, 169, 169));
DefineGlobalColor("midColor", CreateColor(132, 76, 130));
DefineGlobalColor("rangeColor", CreateColor(28, 96, 109));
DefineGlobalColor("openColor", CreateColor(109, 84, 44));
DefineGlobalColor("downColor", CreateColor(109, 42, 28));
DefineGlobalColor("upColor", CreateColor(76, 133, 78));
DefineGlobalColor("vwapColor", CreateColor(174, 157, 50));
#

def OREnded = (Today OR !showTodayOnly) and RTH and SecondsFromTime(End_Time) >= 0;
plot ORL = if OREnded and !endPlot then ORlow else Double.NaN;
ORL.SetDefaultColor(GlobalColor("rangeColor"));
ORL.HideBubble();
plot ORH = if OREnded and !endPlot then ORhigh else Double.NaN;
ORH.SetDefaultColor(GlobalColor("rangeColor"));
ORH.HideBubble();
input showMidPoint = yes;

plot mid = if OREnded and !endPlot then midPoint else Double.NaN;
mid.setDefaultColor(GlobalColor("midColor"));
mid.HideBubble();
input showQuarters = no;
def oneQuarter = ORLow + (ORFullRange/4);
def threeQuarter = ORHigh - (ORFullRange/4);
plot oneQLine = if showQuarters and OREnded and !endPlot then oneQuarter else Double.NaN;
oneQLine.setDefaultColor(GlobalColor("quarterColor"));
oneQLine.HideBubble();
plot threeQLine = if showQuarters and OREnded and !endPlot then threeQuarter else Double.NaN;
threeQLine.setDefaultColor(GlobalColor("quarterColor"));
threeQLine.HideBubble();

input showMeasuredTargets = yes;
def upperTarget = (ORHigh + (ORFullRange/2));
plot upper = if showMeasuredTargets and OREnded and !endPlot then upperTarget else Double.NaN;
upper.SetDefaultColor(GlobalColor("upColor"));
upper.HideBubble();
def lowerTarget = (ORLow - (ORFullRange/2));
plot lower = if showMeasuredTargets and OREnded and !endPlot then lowerTarget else Double.NaN;
lower.SetDefaultColor(GlobalColor("downColor"));
lower.HideBubble();
input showMeasuredTargets2 = no;
def upperTarget2 = (ORHigh + (ORFullRange));
plot upper2 = if showMeasuredTargets2 and OREnded and !endPlot then upperTarget2 else Double.NaN;
upper2.SetDefaultColor(GlobalColor("upColor"));
upper2.HideBubble();
def lowerTarget2 = (ORLow - (ORFullRange));
plot lower2 = if showMeasuredTargets2 and OREnded and !endPlot then lowerTarget2 else Double.NaN;
lower2.SetDefaultColor(GlobalColor("downColor"));
lower2.HideBubble();

#plot anchored VWAP for the current day
def  volumeSum = CompoundValue(1, if postAnchorTime and endAchorTime then volumeSum[1] + volume else 0, volume);
def  volumeVwapSum = CompoundValue(1, if postAnchorTime and endAchorTime then volumeVwapSum[1] + volume * vwap else 0, volume * vwap);
def volumeVwap2Sum = CompoundValue(1, if postAnchorTime and endAchorTime then volumeVwap2Sum[1] + volume * Sqr(vwap) else 0, volume * Sqr(vwap));
def price = volumeVwapSum / volumeSum;
def deviation = Sqrt(Max(volumeVwap2Sum / volumeSum - Sqr(price), 0));

input stdDev = 1.0;
def numDevDn = -stdDev;
def numDevUp = stdDev;

plot anchorVWAP = if !showVWAP and showTodayOnly and !Today then Double.NaN else if RTH and showVWAP then price else Double.NaN;
anchorVWAP.SetStyle(Curve.FIRM);
anchorVWAP.SetDefaultColor(GlobalColor("vwapColor"));
plot anchorVWAPUpper = if !showVWAPDevs and showTodayOnly and !Today then Double.NaN else if RTH and showVWAPDevs then (price + (numDevUp * deviation)) else Double.NaN;
anchorVWAPUpper.SetStyle(Curve.SHORT_DASH);
anchorVWAPUpper.SetDefaultColor(Color.GRAY);
anchorVWAPUpper.HideBubble();
plot anchorVWAPLower = if !showVWAPDevs and showTodayOnly and !Today then Double.NaN else if RTH and showVWAPDevs then (price + (numDevDn * deviation)) else Double.NaN;
anchorVWAPLower.SetStyle(Curve.SHORT_DASH);
anchorVWAPLower.SetDefaultColor(Color.GRAY);
anchorVWAPLower.HideBubble();

input colorCandles = no;
AssignPriceColor(if !colorCandles then Color.CURRENT
else if colorCandles and OREnded and high < ORL and high < anchorVWAP then
    GlobalColor("downColor")
else if colorCandles and OREnded and low > ORH and low > anchorVWAP then
    GlobalColor("upColor")    
else Color.CURRENT );

input showOpen = yes;
AddVerticalLine(showOpen and Today and RTH and !RTH[1], concat("Open", ""), GlobalColor("openColor"), curve.POINTS);

input showBubbles = no;
def showBubbleNow = !IsNaN(close) and IsNaN(close[-1]);
AddChartBubble(showBubbles and showBubbleNow[1], ORHigh[1], "OR High", Color.GRAY, yes);
AddChartBubble(showBubbles and showBubbleNow[1], ORLow[1], "OR Low", Color.GRAY, no);
Nice work Tony. I wonder if you have tried to develop a similar approach but using 1D candles for swing trading with some multiday method?
 

FutureTony

Member
VIP
Nice work Tony. I wonder if you have tried to develop a similar approach but using 1D candles for swing trading with some multiday method?
I have heard that some people watch the Globex open on Sunday through to the close of day Monday as the weekly opening range. I am going to play around with that in the future to see if there are interesting patterns that develop. If so, I will share that here.
 

balishag21

New member
Michigandolf's 30min Opening Range Tradingview
I'm looking for something similar to: https://usethinkscript.com/threads/...kout-indicator-for-thinkorswim.154/#post-1291
This one I like on TradingView but I'm looking to make it work on TOS. Any suggestions?
https://www.tradingview.com/script/vjkErFo8-Michigandolf-s-30min-Opening-Range/
This script plots the 30min Opening Range as well as the previous day's high & low.

Description:
Blue Line = Top of the 30min Opening Range for the session
Pink Line = Bottom of the 30min Opening Range for the session
White Line = Mid-Point of the 30min Opening Range for the session
White Transparent Area = The full range of the 30min Opening Range

Green Line = Yesterday's High for the session
Red Line = Yesterday's Low for the session

Use:
The Opening Range will continue to expand until the first 30minutes of trading has passed, at which point the range will lock in place for the remainder of the trading session. Many traders use these important levels to gauge trade entries and exits (e.g. Mark Fisher's ACD strategy).

This script does not work currently work for futures (e.g. ES, NQ, RTY) due to the session start time.
a1.png

Ruby:
//@version=4
study("Michigandolf's 30min Opening Range", shorttitle="Michigandolf's OR", overlay = true)

input_or = input("0930-1000", type=input.session, title="Opening Range Time (EST)", tooltip="The duration of the opening range to be drawn.")

// Inputs
input_rth = input("0930-1600", type=input.session, title="Regular Session Time (EST)", tooltip="If you want to get full session (including overnight) high/low values, then change the regular session interval.  For example, on a 5-mninute chart, 1800-1655 will provide the high and low for the full daily session.")
or_session = time(timeframe.period,str.format("{0}:1234567", input_or), "America/New_York")
rth_session = time("1440",str.format("{0}:23456", input_rth), "America/New_York")

// Opening Range
var or_high = 0.0
var or_low = 0.0

if or_session
    if not or_session[1]
        or_low := low
        or_high := high
    else
        or_low := min(low, or_low)
        or_high := max(high, or_high)

or_mid = or_low + ((or_high - or_low) / 2)


// RTH High/Low

var float rth_high = na
var float rth_low = na
var float prior_rth_high = na
var float prior_rth_low = na

if rth_session
    if not rth_session[1]
        rth_low := low
        rth_high := high
    else
        rth_low := min(low, rth_low)
        rth_high := max(high, rth_high)
else
    prior_rth_low := rth_low
    prior_rth_high := rth_high


// Plots
or_high_plot = plot(not or_session ? or_high : na, title="ORH", color=#268FFF, linewidth=2, style=plot.style_linebr)
or_low_plot = plot(not or_session ? or_low : na, title="ORL", color=#FF217E, linewidth=2, style=plot.style_linebr)


plot(not or_session ? or_mid : na, title="ORM", color=#FFFFFF, linewidth=1, style=plot.style_linebr)

fill(or_high_plot, or_low_plot, title="OR Fill", color=color.new(color.white, 97))


plot(not rth_session ? rth_high : prior_rth_high, title="RTH", color=#1BE091, linewidth=1, style=plot.style_line)
plot(not rth_session ? rth_low : prior_rth_low, title="RTL", color=#E02B16, linewidth=1, style=plot.style_line)

//NOTE: To use for stocks or ETFs you'll need to turn on the Extended Hours on your chart. Right click the chart and go to sendings and select Extended Hours
 
Last edited by a moderator:

FutureTony

Member
VIP
Michigandolf's 30min Opening Range Tradingview
I'm looking for something similar to: https://usethinkscript.com/threads/...kout-indicator-for-thinkorswim.154/#post-1291
This one I like on TradingView but I'm looking to make it work on TOS. Any suggestions?
https://www.tradingview.com/script/vjkErFo8-Michigandolf-s-30min-Opening-Range/

View attachment 1083
Ruby:
//@version=4
study("Michigandolf's 30min Opening Range", shorttitle="Michigandolf's OR", overlay = true)

input_or = input("0930-1000", type=input.session, title="Opening Range Time (EST)", tooltip="The duration of the opening range to be drawn.")

// Inputs
input_rth = input("0930-1600", type=input.session, title="Regular Session Time (EST)", tooltip="If you want to get full session (including overnight) high/low values, then change the regular session interval.  For example, on a 5-mninute chart, 1800-1655 will provide the high and low for the full daily session.")
or_session = time(timeframe.period,str.format("{0}:1234567", input_or), "America/New_York")
rth_session = time("1440",str.format("{0}:23456", input_rth), "America/New_York")

// Opening Range
var or_high = 0.0
var or_low = 0.0

if or_session
    if not or_session[1]
        or_low := low
        or_high := high
    else
        or_low := min(low, or_low)
        or_high := max(high, or_high)

or_mid = or_low + ((or_high - or_low) / 2)


// RTH High/Low

var float rth_high = na
var float rth_low = na
var float prior_rth_high = na
var float prior_rth_low = na

if rth_session
    if not rth_session[1]
        rth_low := low
        rth_high := high
    else
        rth_low := min(low, rth_low)
        rth_high := max(high, rth_high)
else
    prior_rth_low := rth_low
    prior_rth_high := rth_high


// Plots
or_high_plot = plot(not or_session ? or_high : na, title="ORH", color=#268FFF, linewidth=2, style=plot.style_linebr)
or_low_plot = plot(not or_session ? or_low : na, title="ORL", color=#FF217E, linewidth=2, style=plot.style_linebr)


plot(not or_session ? or_mid : na, title="ORM", color=#FFFFFF, linewidth=1, style=plot.style_linebr)

fill(or_high_plot, or_low_plot, title="OR Fill", color=color.new(color.white, 97))


plot(not rth_session ? rth_high : prior_rth_high, title="RTH", color=#1BE091, linewidth=1, style=plot.style_line)
plot(not rth_session ? rth_low : prior_rth_low, title="RTL", color=#E02B16, linewidth=1, style=plot.style_line)

//NOTE: To use for stocks or ETFs you'll need to turn on the Extended Hours on your chart. Right click the chart and go to sendings and select Extended Hours
Have you looked at this one: https://usethinkscript.com/threads/opening-range-indicator-with-measured-moves-and-vwap.8256/

I wrote it based on his tweets.
 

Similar threads

Top