Explosive Bollinger Bandwidth Squeeze Scan For ThinkOrSwim

justAnotherTrader

Active member
VIP
VIP Enthusiast
This one is fun. It uses the bollinger bandwidth as a measure of volatility.

The scan setup is simple:
  • High Average Bandwidth > 30 (This implies very high volatility. For instance the 60 day average bandwidth on TSLA is 43 compared to SPY which is 8)
  • Current Bandwidth < 15 (A low volatility state in a high volatility stock means squeeze is coming, the lower the volatility the better)

Here is the indicator:

Code:
declare lower;

input averageType = AverageType.Simple;
input price = close;
input displace = 0;
input length = 20;
input Num_Dev_Dn = -2.0;
input Num_Dev_Up = 2.0;
input BulgeLength = 150;
input SqueezeLength = 150;

def upperBand = BollingerBands(price, displace, length, Num_Dev_Dn, Num_Dev_Up, averageType).UpperBand;
def lowerBand = BollingerBands(price, displace, length, Num_Dev_Dn, Num_Dev_Up, averageType).LowerBand;
def midLine = BollingerBands(price, displace, length, Num_Dev_Dn, Num_Dev_Up, averageType).MidLine;

plot Bandwidth = (upperBand - lowerBand) / midLine * 100;
Bandwidth.SetDefaultColor(Color.GREEN);

plot Bulge = Highest(Bandwidth, BulgeLength);
Bulge.SetDefaultColor(GetColor(8));
Bulge.setStyle(Curve.SHORT_DASH);

plot Squeeze = Lowest(Bandwidth, SqueezeLength);
Squeeze.SetDefaultColor(GetColor(8));
Squeeze.setStyle(Curve.SHORT_DASH);

#Bandwidth Label
AddLabel(Bandwidth, Concat("CurrentVolatility = ", Bandwidth), color.GREEN);

#Moving Average Volatility
def var = Bandwidth;
input len = 7;
input len1 = 14;
input len2 = 60;
input len3 = 120;
def displace1 = 0;
plot AvgVolatility7 = ExpAverage(var[-displace], len);
plot AvgVolatility14 = ExpAverage(var[-displace], len1);
plot AvgVolatility60 = ExpAverage(var[-displace], len2);
plot AvgVolatility120 = ExpAverage(var[-displace], len3);

AvgVolatility7.SetDefaultColor(Color.Dark_Green);
AvgVolatility14.SetDefaultColor(Color.Yellow);
AvgVolatility60.SetDefaultColor(Color.Blue);
AvgVolatility120.SetDefaultColor(Color.Magenta);

#Average Volatility Labels
AddLabel(AvgVolatility7, Concat("7VolatilityAverage = ", AvgVolatility7), color.DARK_GREEN);
AddLabel(AvgVolatility14, Concat("14VolatilityAverage = ", AvgVolatility14), color.YELLOW);
AddLabel(AvgVolatility60, Concat("60VolatilityAverage = ", AvgVolatility60), color.BLUE);
AddLabel(AvgVolatility120, Concat("120VolatilityAverage = ", AvgVolatility120), color.MAGENTA);
 
Last edited by a moderator:
Did this for me, but others might want to use it. It's the same thing but it's a customizable scan. Save it as a chart study first and when you bring it up as a custom study on the scan tab you can adjust the bollinger bands, the bandwidth average length, the bandwidth average minimum, and the current bandwidth maximum. Just change your variables and select "is true" (which just confirms all your conditions are correct) Seems to work like a charm. Good job, JustAnotherTrader!!

Code:
# ExplosiveSqueeze by JustAnotherTrader
# Custom scan mods by WTF_Dude

input averageType = AverageType.Simple;
input price = close;
input length = 20;
input Num_Dev_Dn = -2.0;
input Num_Dev_Up = 2.0;
def displace = 0;

def upperBand = BollingerBands(price, displace, length, Num_Dev_Dn, Num_Dev_Up, averageType).UpperBand;
def lowerBand = BollingerBands(price, displace, length, Num_Dev_Dn, Num_Dev_Up, averageType).LowerBand;
def midLine = BollingerBands(price, displace, length, Num_Dev_Dn, Num_Dev_Up, averageType).MidLine;
def Bandwidth = (upperBand - lowerBand) / midLine * 100;   #current bandwidth

#Moving Average Volatility
input BandwidthAverageLength = 60; #length of bandwidth average
def BandwidthAverage = ExpAverage(Bandwidth[-displace], BandwidthAverageLength);

input BandwidthMax = 15;
def TBW = Bandwidth <= BandwidthMax;

input BandwidthAvgMin = 30;
def TBWA = Bandwidthaverage > BandwidthAvgMin;
#def TBWA = BandwidthAvgMin is greater than BandwidthAverage;

plot ExplosiveSqueeze = TBW and TBWA;
 
This is interesting. trying to figure out how you use it. can you share? thanks
I found two ways I like using it so far. The first way is on the daily chart top identify squeezes and buy/ sell the breakout and breakdown. Another way is to reverse the idea and look for a relatively low volatility average and a high volatility currently. I use this second idea intraday to identify stocks that possibly got some fundamentally changing news and is breaking up/ down. I'm still playing around with it but my thoughts are there are many ways to alter the strategy to find stocks in certain stages of boom bust cycles.
 
So I see multiple timeframe volatity marks on the indicator, right? So how do you determine the squeeze? I’m used to Keltner over bollinger version. And how do you determine the post squeeze trajectory projection?

On the labels in the indicator, what does the number before the label mean? Is that the number of bars the average value is based on?
 
So I see multiple timeframe volatity marks on the indicator, right? So how do you determine the squeeze? I’m used to Keltner over bollinger version. And how do you determine the post squeeze trajectory projection?

On the labels in the indicator, what does the number before the label mean? Is that the number of bars the average value is based on?
I think you've misunderstood what he made here... This isn't a squeeze based on keltner channels. This indicator is based strictly on the width of the bollingers (how far away the top and bottom are from each other. Its a different indicator so there is no need for Keltners) goin way below their longtime average. Those aren't "marks" based on timeframe. Those are different smoothing averages you can use to compare the current bandwidth against.

Post squeeze trajectory isn't even a part of this. You'd need something else for that
 
@justAnotherTrader how to set up a scan condition wizard that specify:

1. BB bandwidth >= 30 and
2. AvgVolatility7 <= 15
or
3. AvgVolatility14<= 15?!

How to write ac script that calculate (BB_Upperband - BB_Lowerband) - 1 = %; and condition that scan the above value which is great or lesser than a particular %.

def PercentBandwidth = ((upperBand - lowerBand) - 1 )* 100; #current bandwidth percentage
 
Hey @wtf_dude, thanks for your scan. What settings on the scan in the inputs section have you found work well?

ie what settings do you find are good for finding candidates?

What do you usually select under the inputs tab on the scan for
bandwidth avg length
bandwidth max
bandwidth avg min

I guess I was having trouble figuring out which selection on the input tab will give you stocks with current bandwidth of <15 and avg> 30 but it seems that these are already in there as default settings correct? and the one that specifies the current bandwidth is called "bandwidth max" correct?

thanks again
 
I think you've misunderstood what he made here... This isn't a squeeze based on keltner channels. This indicator is based strictly on the width of the bollingers (how far away the top and bottom are from each other. Its a different indicator so there is no need for Keltners) goin way below their longtime average. Those aren't "marks" based on timeframe. Those are different smoothing averages you can use to compare the current bandwidth against.

Post squeeze trajectory isn't even a part of this. You'd need something else for that
Is this something in the right direction,...otherwise difficult to understand explanation all around without an example http://tos.mx/XXxoGRV
 
Did this for me, but others might want to use it. It's the same thing but it's a customizable scan. Save it as a chart study first and when you bring it up as a custom study on the scan tab you can adjust the bollinger bands, the bandwidth average length, the bandwidth average minimum, and the current bandwidth maximum. Just change your variables and select "is true" (which just confirms all your conditions are correct) Seems to work like a charm. Good job, JustAnotherTrader!!

Code:
# ExplosiveSqueeze by JustAnotherTrader
# Custom scan mods by WTF_Dude

input averageType = AverageType.Simple;
input price = close;
input length = 20;
input Num_Dev_Dn = -2.0;
input Num_Dev_Up = 2.0;
def displace = 0;

def upperBand = BollingerBands(price, displace, length, Num_Dev_Dn, Num_Dev_Up, averageType).UpperBand;
def lowerBand = BollingerBands(price, displace, length, Num_Dev_Dn, Num_Dev_Up, averageType).LowerBand;
def midLine = BollingerBands(price, displace, length, Num_Dev_Dn, Num_Dev_Up, averageType).MidLine;
def Bandwidth = (upperBand - lowerBand) / midLine * 100;   #current bandwidth

#Moving Average Volatility
input BandwidthAverageLength = 60; #length of bandwidth average
def BandwidthAverage = ExpAverage(Bandwidth[-displace], BandwidthAverageLength);

input BandwidthMax = 15;
def TBW = Bandwidth <= BandwidthMax;

input BandwidthAvgMin = 30;
def TBWA = Bandwidthaverage > BandwidthAvgMin;
#def TBWA = BandwidthAvgMin is greater than BandwidthAverage;

plot ExplosiveSqueeze = TBW and TBWA;


[/QUOTE]
following the steps above and starting a trial scan, but Can't find the choice of parameters: BB, bandwidth length, etc...Only
Any suggestion ?

[ATTACH=full]11511[/ATTACH]

tks
e6Zqxx8.png
 
@TY_Joe Technically, the scripts for studies, watchlists, and scans could be the same. Study scripts are saved under the study tab. Watchlist scripts are saved as Watch List columns, and scanning scripts are referenced in scans.

However, in reality, the chart studies and watchlists end up being slightly different, mostly because how you want to format a chart is different from how you format the watchlist column.

As for scans, a majority of the studies on this forum can be directly referenced in scans. Occasionally, a separate scan needs to be set up because of the complexity of the script, customization of the conditions upon which to scan, use of secondary aggregations, and other peculiarities of the TOS platform.
 
Explosive Squeeze Watchlist

a2.png

Shared Link for Explosive Squeeze watchlist: http://tos.mx/wYCkrrw
Click here for --> Easiest way to load shared links
Ruby:
# ExplosiveSqueeze by JustAnotherTrader
# Custom scan mods by WTF_Dude

input averageType = AverageType.Simple;
input price = close;
input length = 20;
input Num_Dev_Dn = -2.0;
input Num_Dev_Up = 2.0;
def displace = 0;

def upperBand = BollingerBands(price, displace, length, Num_Dev_Dn, Num_Dev_Up, averageType).UpperBand;
def lowerBand = BollingerBands(price, displace, length, Num_Dev_Dn, Num_Dev_Up, averageType).LowerBand;
def midLine = BollingerBands(price, displace, length, Num_Dev_Dn, Num_Dev_Up, averageType).MidLine;
def Bandwidth = (upperBand - lowerBand) / midLine * 100;   #current bandwidth

#Moving Average Volatility
input BandwidthAverageLength = 60; #length of bandwidth average
plot BandwidthAverage = ExpAverage(Bandwidth[-displace], BandwidthAverageLength);

input BandwidthMax = 15;
def TBW = Bandwidth <= BandwidthMax;

input BandwidthAvgMin = 30;
def TBWA = Bandwidthaverage > BandwidthAvgMin;
#def TBWA = BandwidthAvgMin is greater than BandwidthAverage;

def ExplosiveSqueeze = TBW and TBWA;
AssignBackGroundColor(if ExplosiveSqueeze then color.dark_orange else color.violet) ;
@TY_Joe
 
Explosive Squeeze Watchlist

View attachment 725
Shared Link for Explosive Squeeze watchlist: http://tos.mx/wYCkrrw
Click here for --> Easiest way to load shared links
Ruby:
# ExplosiveSqueeze by JustAnotherTrader
# Custom scan mods by WTF_Dude

input averageType = AverageType.Simple;
input price = close;
input length = 20;
input Num_Dev_Dn = -2.0;
input Num_Dev_Up = 2.0;
def displace = 0;

def upperBand = BollingerBands(price, displace, length, Num_Dev_Dn, Num_Dev_Up, averageType).UpperBand;
def lowerBand = BollingerBands(price, displace, length, Num_Dev_Dn, Num_Dev_Up, averageType).LowerBand;
def midLine = BollingerBands(price, displace, length, Num_Dev_Dn, Num_Dev_Up, averageType).MidLine;
def Bandwidth = (upperBand - lowerBand) / midLine * 100;   #current bandwidth

#Moving Average Volatility
input BandwidthAverageLength = 60; #length of bandwidth average
plot BandwidthAverage = ExpAverage(Bandwidth[-displace], BandwidthAverageLength);

input BandwidthMax = 15;
def TBW = Bandwidth <= BandwidthMax;

input BandwidthAvgMin = 30;
def TBWA = Bandwidthaverage > BandwidthAvgMin;
#def TBWA = BandwidthAvgMin is greater than BandwidthAverage;

def ExplosiveSqueeze = TBW and TBWA;
AssignBackGroundColor(if ExplosiveSqueeze then color.dark_orange else color.violet) ;
@TY_Joe
I tried to use the import shared item under Setup in TOS but the shared items list is blank after it says successfully imported, what am I doing wrong? Is this the same thing as Short Squeeze scan?
 
@Almighty1 When you saved the watchlist, do you remember what name you saved it under? If not, follow these instructions exactly
--> Easiest way to load shared links again, to load the watchlist column again, making sure to write down what name you save the watchlist column under.

After that follow these instructions ---> https://usethinkscript.com/threads/answers-to-commonly-asked-questions.6006/#post-70999 to find that watchlist column so you can load it to your watchlist.

In answer to your question, The explosive squeeze is not EXACTLY like other squeeze indicators. The squeeze indicators on the forum are all slightly different flavors. I have found that reading through the threads, is the best way to understand the nuances between them as well as picking up tips as to how other members are using these indicators.
 

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
435 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top