• The price of VIP membership is increasing to $199 beginning June 1. Click here to lock in the current rate of $149.

TTM Squeeze Watchlist Column for ThinkorSwim

BenTen

Administrative
Staff
VIP
For those of you who enjoy using the TTM Squeeze & Momentum indicator, this should be a handy addition to your ThinkorSwim chart setup. The script will add the status of the TTM Squeeze for stocks on your watchlist via a new column. You can select whichever timeframe you would like to scan for TTM squeeze.

Stocks usually break out of consolidations and by having the TTM Squeeze on your watchlist it helps to alert when they do.

Here is what each signal and labels represent:
  • Bright Red: The stock is in Buy zone
  • Dark Red: Market compression is currently in this time period. The number reveals the amount of dots on your TTM Squeeze indicator.
  • Dark Green: The squeeze has fired. The number notes how many dots (up to 5) and whether the squeeze signaled Long or Short.
  • Black: No squeeze on this time frame

YexBBcI.png


thinkScript Code

Code:
# Squeeze watchlist column
#   Red Background   - Squeeze is building in the time period - number indicates how many dots
#      w/ white "B"  - Squeeze is building, stock is within "buy zone"
#   Green Background - Squeeze has fired - number indicates how many dots (up to 5 dots)
#                      and whether Squeeze fired L(ong) or S(hort)
#   Black Background - No Squeeze in play

# Original code by Eric Purdy of Simpler Trading 2017
# Modified code by Rich Stratmann to put in background colors and shorten column values
# Updates by dmccuskey
#   - change background colors to aid content scanning
#   - add "B" to time frames which are in the Buy Zone - between 8 & 21 EMA
#   - change "0" to " " <space> so that the content doesn't show when row is highlighted

#ToS Share Code: https://tos.mx/IPrEhH

def sqz = !TTM_Squeeze().SqueezeAlert;
def direction = TTM_Squeeze()>TTM_Squeeze()[1];
def count = if sqz and !sqz[1] then 1 else count[1]+1;
def isFired = if !sqz and sqz[1] then 1 else 0;
def firedCount = if isFired then 1 else firedCount[1]+1;
def firedDirection = if isFired then direction else firedDirection[1];

def sumIsFired = sum(isFired,5);
def isFiredDir = sumIsFired && firedDirection;

# look for close buy zone
def ema8 = reference movAvgExponential(length=8);
def ema21 = reference movAvgExponential(length=21);
def currPrice = close();
def highVal = Max(ema8, ema21);
def lowVal = Min(ema8, ema21);
def inBuyZone = currPrice >= lowVal && currPrice <= highVal;

def sqzBuy = sqz && inBuyZone;
def sqzNoBuy = sqz && !inBuyZone;

addLabel(yes, Concat(if sqzBuy then "B " else "", if sqz then "" + count else if sumIsFired then “” + firedCount + if firedDirection then ” L” else ” S” else “ ”), if sqzBuy then color.white else color.black);

AssignBackgroundColor(if sqzNoBuy then  CreateColor(170, 6, 0) else if sqzBuy then color.red else if sumIsFired then CreateColor(28, 105, 3) else color.black);

Shareable Link

https://tos.mx/uXplYi

Credits:
 
Last edited:

BC1106

New member
2019 Donor
VIP
Code:
def squeeze = if(reference BollingerBands()."upperband" - KeltnerChannels()."Upper_Band")<0 then 1 else 0;

def insqueeze = if squeeze then insqueeze[1] + 1 else 0;

def fired = if !squeeze then fired[1]+1 else 0;

def direction = if (fired == 1 , if( TTM_Squeeze() > TTM_Squeeze()[1] , 1 , 0 ),  direction[1]);

plot result = if insqueeze > 0 then insqueeze else if fired >0 and fired <8 then fired else 0;

AddLabel(yes, Concat(if insqueeze>0 then "Squeeze: " else if fired >0 and fired <8 then Concat("FIRED: ", if direction then "? " else "? ") else "", result), if insqueeze>0 then color.white else color.black);

AssignBackgroundColor( if insqueeze>0 then color.red else if fired>0 and fired <8 then color.green else color.black);

def squeeze = if(reference BollingerBands()."upperband" - KeltnerChannels()."Upper_Band")<0 then 1 else 0;

def insqueeze = if squeeze then insqueeze[1] + 1 else 0;

def fired = if !squeeze then fired[1]+1 else 0;

def direction = if (fired == 1 , if( TTM_Squeeze() > TTM_Squeeze()[1] , 1 , 0 ),  direction[1]);

plot result = if insqueeze > 0 then insqueeze else if fired >0 and fired <8 then fired else 0;

AddLabel(yes, Concat(if insqueeze>0 then "Squeeze: " else if fired >0 and fired <8 then Concat("FIRED: ", if direction then "? " else "? ") else "", result), if insqueeze>0 then color.white else color.black);

AssignBackgroundColor( if insqueeze>0 then color.red else if fired>0 and fired <8 then color.green else color.black);

This is the code i use for my watchlist column, very similar to yours in fact it may be the exact same, but Im not 100% sure since i know nothing about coding. But visually its slightly different and you can customize to whatever timeframe you want, it just wont say if it fired long or short.
 

tomsk

Well-known member
VIP
Saw some discussions on squeeze watchlists on some other threads, thought I'd ahre what I have.
Here's a version from my files

Code:
# TTM Squeeze Watchlist
# TSL
# 11.13.2019

input price = close;
input length = 20;
input nK = 1.5;
input nBB = 2.0;
input alertLine = 1.0;

def squeezeDots = TTM_Squeeze(price, length, nK, nBB, alertLine).SqueezeAlert;
def alertCount = if squeezeDots[1] == 0 and squeezeDots == 1 then 1 
                 else if squeezeDots == 1 then alertCount[1] + 1 
                 else 0;
plot data = alertCount;
data.SetDefaultColor(Color.BLACK);

def squeezeHistogram = TTM_Squeeze(price, length, nK, nBB, alertLine).Histogram;
AssignBackgroundColor(if squeezeHistogram >= 0 
                      then if squeezeHistogram > squeezeHistogram[1] then Color.CYAN else Color.BLUE
                      else if squeezeHistogram < squeezeHistogram[1] then Color.RED else Color.YELLOW);
 

Rojo Grande

Member
VIP
Hello Ben, In the original TTM squeeze, it's possible to change the length from the default of 20 to your liking. Can adjustable length be added to this study?

I was looking for that and cannot find it (I am referring to the code in post #1 above) not to tomsk in post #3. I did however find another TTM squeeze alert that I was able to find and change the length, so no need to alter anything on my account. Again, thanks to all who contribute to the best site I know.
 

horserider

Well-known member
VIP
Here's a squeeze count for Watchlist from Mobius, you can adapt this for us on a study if you wish

Code:
# Squeeze Count Watchlist
# Mobius
# 11.09.2015

def Squeeze = BollingerBands().UpperBand < KeltnerChannels().Upper_Band;
def count = if !Squeeze
            then 0
            else if Squeeze
                 then count[1] + 1
                 else count[1];
AddLabel(1, if Squeeze then count else 0,
            if Squeeze
            then Color.Black
            else Color.WHITE);
AssignBackgroundColor(if Squeeze then color.green else color.white);
 

sbtyme

New member
@BenTen - Thanks for this. I'm new to Think Script. I've uploaded the indicator to my watch list, no problem but I don't see how to determine/switch which time frame I want the indicator reflect for the squeeze (ex- 5 min or 30 min or.....).
Thanks in advance.
 
Code:
# This 'Squeeze Watchlist Column' shows when a stock is currently in a squeeze or the number of bars ago that the squeeze ended. The number of bars in a squeeze is shown on a red background using '=?' or '>=13'. When larger than 12 bars, the value is shown as >=13. The bars since the squeeze ended is shown in green as '-? ago' where ? is a maximum of 6.
#The suggested title is 'SQZ'.
# This issued version is based on a 1 minute aggregation that can be changed by editing the code and changing the aggregation at the top of the edit screen. It is meaningful to have the column aggregation match the chart aggregation to avoid confusion.
#Revised 9/29/12

def keltnerChannelATRs = 1.5 ;
def bollingerBandStdDev = 2 ;

# Average True Range
def ATR = AvgTrueRange(high, close, low, 20);

# Standard Deviation
def SDev = stdev(close, 20);

# -- Calculate Bollinger Band Squeeze Indicator --
# for alert
def Denom = (keltnerChannelATRs * ATR);
def BBS_Ind = if (Denom <> 0, ((bollingerBandStdDev * SDev) / Denom), 0);#A squeeze is on if BBS_Ind < 1.0

#Count number of squeeze bars
def Sq_Count_0 = If BBS_Ind < 1.0 then 1 else 0;
def Sq_Count_1 = If BBS_Ind[1] < 1.0 && Sq_Count_0 == 1 then 1 else 0;
def Sq_Count_2 = If BBS_Ind[2] < 1.0  && Sq_Count_1 == 1 then 1 else  0;
def Sq_Count_3 = If BBS_Ind[3] < 1.0 && Sq_Count_2 == 1 then 1 else 0;
def Sq_Count_4 = If BBS_Ind[4] < 1.0 && Sq_Count_3 == 1 then 1 else 0;
def Sq_Count_5 = If BBS_Ind[5] < 1.0 && Sq_Count_4 == 1 then 1 else 0;
def Sq_Count_6 = If BBS_Ind[6] < 1.0 && Sq_Count_5 == 1 then 1 else 0;
def Sq_Count_7 = If BBS_Ind[7] < 1.0 && Sq_Count_6 == 1 then 1 else 0;
def Sq_Count_8 = If BBS_Ind[8] < 1.0 && Sq_Count_7 == 1 then 1 else 0;
def Sq_Count_9 = If BBS_Ind[9] < 1.0 && Sq_Count_8 == 1 then 1 else 0;
def Sq_Count_10 = If BBS_Ind[10] < 1.0 && Sq_Count_9 == 1 then 1 else 0;
def Sq_Count_11 = If BBS_Ind[11] < 1.0 && Sq_Count_10 == 1 then 1 else 0;
def Sq_Count_12 = If BBS_Ind[12] < 1.0 && Sq_Count_11 == 1 then 1 else 0;
def Sq_Count = if BBS_Ind < 1.0 && Sq_Count_0 == 1 then (Sq_Count_0 + Sq_Count_1 + Sq_Count_2 + Sq_Count_3 + Sq_Count_4 + Sq_Count_5 + Sq_Count_6 + Sq_Count_7 + Sq_Count_8 + Sq_Count_9 + Sq_Count_10 + Sq_Count_11 + Sq_Count_12) else 0;

Def Post_Count = if BBS_Ind[1] < 1.0  && BBS_Ind[0] > 1.0 then 1
else if BBS_Ind[2] < 1.0  && BBS_Ind[1] > 1.0 then 2
else if BBS_Ind[3] < 1.0  && BBS_Ind[2] > 1.0 then 3
else if BBS_Ind[4] < 1.0  && BBS_Ind[3] > 1.0 then 4
else if BBS_Ind[5] < 1.0 && BBS_Ind[4] > 1.0  then 5
else if BBS_Ind[6] < 1.0 && BBS_Ind[5] > 1.0 then 6
else Double.nan;

#plot data = post_Count;#Used for testing

AddLabel(yes,if Sq_Count == 13 then Concat(">=" , Sq_Count) else if between(Sq_Count,1,12) then concat("=", Sq_Count) else if between(Post_Count,1,6) then concat("-",Concat(Post_Count," ago")) else "0");

Assignbackgroundcolor (if (Sq_Count >= 13) then color.Dark_red
else if between(Sq_Count,1,12)  then color.red
else if between(Post_Count,1,6) then color.Dark_green
else color.current);


######### EOC ###########
 

BayTrader_93

New member
Hey everyone, I have this code I'm using in my watchlist but I wanted to adjust it so that instead of black backgrounds and color words, I wanted to flip flop it so that the background is colored so that way when the squeeze lines up on multiple time frames, I can see it more clearly. Pretty new to coding, and more specifically think script so just reaching out for some help.

Thanks!

Code:
# Simpler Trading Squeeze watchlist column - Eric Purdy 2017

# Shared Link -    https://tos.mx/5cpgKa
#Start
def sqz = !TTM_Squeeze().SqueezeAlert;
def direction = TTM_Squeeze()>TTM_Squeeze()[1];
def count = if sqz and !sqz[1] then 1 else count[1]+1;
def fired = if !sqz and sqz[1] then 1 else 0;
def firedCount = if fired then 1 else firedCount[1]+1;
def firedDirection = if fired then direction else firedDirection[1];
addLabel(yes, if sqz then “Squeeze:” + count else if sum(fired,5) then “Fired:” + firedCOunt + if firedDirection then ” Long” else ” Short” else “-”, if sqz then color.red else if sum(fired,5) and firedDirection then color.green else color.orange);
#Finish
 

TIGER202020

New member
Ben, thank you for the script and load it for my watchlist. But What's the time frame for the TTM squeeze being used for the watchlist? where can we set up timeframe?

Never mind. it can be modified when column is added.
 
Last edited by a moderator:

Samrock

New member
I use the TTM Squeeze a lot. Can someone make an custom scan to create a watchlist that tells me which stocks with TTM squeeze just turned Red to Yellow within a day and drop off from the watchlist when TTM squeeze turns from light blue to Dark Blue losing momentum.
 

pk1729

Member
VIP
Following code has 4 different scans including 2 you need. Play with all 4 and figure out what you need. Have fun!

Code:
declare lower;

input price = CLOSE;
input length = 20;
input nK = 1.5;
input nBB = 2.0;
input alertLine = 1.0;

plot scan;

def squeezeHistogram = TTM_Squeeze(price, length, nK, nBB, alertLine).Histogram;


def momentumPivotLow = (squeezeHistogram > squeezeHistogram[1] and squeezeHistogram[1] < squeezeHistogram[2]) ;

def momentumPivotHigh = (squeezeHistogram < squeezeHistogram[1] and squeezeHistogram[1] > squeezeHistogram[2]);

#plot barsSincePivot = GetMaxValueOffset(momentumPivot);

def pivotLowFollowThrough = (momentumPivotLow[1] and squeezeHistogram > squeezeHistogram[1]);

def pivotHighFollowThrough = (momentumPivotHigh[1] and squeezeHistogram < squeezeHistogram[1]);

def zeroLinePositiveFollowThrough = ( squeezeHistogram > 0 and squeezeHistogram[1] > 0 and squeezeHistogram[2] < 0 ) ;

def zeroLineNegativeFollowThrough = (squeezeHistogram < 0 and squeezeHistogram[1] < 0 and squeezeHistogram[2] > 0);

# uncomment one to scan for pivot high/low with follow through bar
#scan = pivotHighFollowThrough;
scan = pivotLowFollowThrough;

# uncomment one to scan for zero line positive/negative with follow through bar
#scan = zeroLinePositiveFollowThrough;
#scan = zeroLineNegativeFollowThrough;
 

Samrock

New member
@pk1729 I have something like this, I need a query for the scan the exactly when the Red becomes Yellow so that I can have in my watchlist and create alerts when new stocks gets added and removed.
 

kelbadawi

New member
what is the best strategy time frame for this column? i set mine to 1HR, SPCE showing bright red "B 8". just trying to understand how to use it @BenTen thank you so much
 

Sagar

Member
@BenTen Can you please help with the scanner.. not sure how to make this line as plot as it has multiple conditions with concat....
Code:
addLabel(yes, Concat(if sqzBuy then "B " else "", if sqz then "" + count else if sumIsFired then “” + firedCount + if firedDirection then ” L” else ” S” else “ ”), if sqzBuy then color.white else color.black);

I was looking for if squeeze fire long or short ... and add that to watch list. Do I need to have multiple scanner for long and short? Appreciate your help.
 

Similar threads

Top