# ttm_stats_counts_durations
#https://usethinkscript.com/threads/ttm-squeeze.16135/
#TTM Squeeze
#AlphaOptions Oct 3, 2019 #1
#About two years ago I saw where a thinkscripter had developed labels to set general expectations for squeeze history, but I did not save the script unfortunately. While this label is not a trade trigger type of indicator, it can be used to quickly set expectations for squeeze occurrence frequency and duration. I would like to see if I can get some help building it as follows and others might also like to learn from the process as we go. Here are the steps I would propose:
#Start with a label (or what will be the initial showing in the ultimate label) that shows the number of bars in the chart being viewed (i.e. there are X number of bars on this chart).
#The next part of the label will say there are X total bars in the TTM squeeze on this chart.
#The other parts of the label are then just mathematical derivative parts of the label from these two measures which most interesting are:
#What percent of bars are in a squeeze (number of squeezes / total bars as a % ) - this shows how frequently this occurs of all bars
#How frequently does a squeeze series initiate - so number of unbroken series (prior bar no squeeze but current bar is squeeze) shows the number of not just the frequency of all bar in squeeze but how frequently a squeeze sequence initiates
#Average squeeze duration - shows of all the unbroken series how many bars would be in a squeeze - this is perhaps the most useful as you can characterize and instrument (or at least its period in the chart) to set expectations on how long that might last
#Other things are also possible like shortest, longest, longest between squeeze series ...
#Once the framework design is made, it is conceivable that any indicator occurrence could be substituted for the squeeze.
#--------------------------
def na = double.nan;
def bn = barnumber();
#--------------------------
# ref signal
# TTM_Squeeze
# TD Ameritrade IP Company, Inc. (c) 2009-2023
declare lower;
input price = CLOSE;
input length = 20;
input nK = 1.5;
input nBB = 2.0;
input alertLine = 1.0;
#plot Histogram = Double.NaN;
#plot VolComp = Double.NaN;
#plot SqueezeAlert = Double.NaN;
def ttm_histo = TTM_Squeeze(price, length, nk, nbb, alertline).histogram;
def ttm_volcomp = TTM_Squeeze(price, length, nk, nbb, alertline).volcomp;
def ttm_sqz = TTM_Squeeze(price, length, nk, nbb, alertline).SqueezeAlert;
# ttm_sqz , 1 , green , no squeeze . 0 , red , squeeze
input show_histo = yes;
plot zttm_histo = if isnan(close) then na else ttm_histo;
zttm_histo.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
zttm_histo.AssignValueColor(
if ttm_histo > 0 and ttm_histo > ttm_histo[1] then color.cyan
else if ttm_histo > 0 and ttm_histo < ttm_histo[1] then color.blue
else if ttm_histo < 0 and ttm_histo > ttm_histo[1] then color.yellow
else if ttm_histo < 0 and ttm_histo < ttm_histo[1] then color.red
else color.gray);
zttm_histo.setlineweight(3);
zttm_histo.SetHiding(!show_histo);
def offpt = 5;
input offset_points = yes;
def pt = if !offset_points then 0
else if ttm_histo > 0 then -offpt
else if ttm_histo < 0 then offpt
else 0;
input show_sqz_points = yes;
plot zsqz = if isnan(close) then na else pt;
zsqz.SetPaintingStrategy(PaintingStrategy.POINTS);
zsqz.AssignValueColor(if ttm_sqz then color.green else color.red);
zsqz.setlineweight(3);
zsqz.SetHiding(!show_sqz_points);
#--------------------------
# ttm_sqz = 0
def signal_start = !ttm_sqz;
# ttm_sqz = 1
def signal_end = ttm_sqz;
# create a pulse, stays = 1 during signals , until a non signal, then 0
def signal = if bn == 1 then 0
else if signal_end then 0
else if signal_start then 1
else signal[1];
#--------------------------
# labels,
# 1. there are X number of bars on this chart
def bar_cnt = highestall(if isnan(close) then 0 else bn);
# 2. there are X total bars in the TTM squeezes on this chart.
def sig_cnt = if bn == 1 then 0
else if signal == 1 then sig_cnt[1] + 1
else sig_cnt[1];
# 3a. What percent of bars are in a squeeze (number of squeezes / total bars as a % ) - this shows how frequently this occurs of all bars
# count how many squeezes, count the groups of signals
def sig_group_cnt = if bn == 1 then 0
else if signal_start and signal_end[1] then sig_group_cnt[1] + 1
else sig_group_cnt[1];
# calc with bn, not bncnt, to use the qty of bars up to the active bar (not all of them. (the last bar will use all the bars)
def sqz_bars_per = round(100 * sig_group_cnt / bn, 1);
# 3b how frequently does a squeeze series initiate - so number of unbroken series (prior bar no squeeze but current bar is squeeze) shows the number of not just the frequency of all bar in squeeze but how frequently a squeeze sequence initiates
# ????
# same as 3a % ?
# 3c. Average squeeze duration - shows of all the unbroken series how many bars would be in a squeeze
# this is perhaps the most useful as you can characterize and instrument (or at least its period in the chart) to set expectations on how long that might last
# avg bar len of groups (sqz)
def avg_group_len = round(sig_cnt/sig_group_cnt, 1);
# Other things are also possible like shortest, longest, longest between squeeze series ...
#----------------
# if last bar has a signal (in a sqz)
# then plot a vert line after last bar, to show est last bar of current sqz, based on the avg group (sqz) len
def lastbar_sig = if (bn == bar_cnt and signal_start) then 1 else 0;
def n = 400;
def last_group_bars = if bn == 1 then 0
else if lastbar_sig then fold e = 0 to n
with p
while getvalue(signal_start, e)
do p + 1
else lastbar_sig[1];
def future_bars = if isnan(close) then future_bars[1]
else if last_group_bars > 0 then (rounddown(avg_group_len,0) - last_group_bars)
else 0;
#def x = !isnan(close[future_bars+1]) and isnan(close[future_bars+0]);
def x = !isnan(getvalue(close, future_bars+1)) and isnan(getvalue(close, future_bars+0));
addverticalline(x, future_bars, color.cyan);
#----------------
input show_labels = yes;
addlabel(show_labels, bar_cnt + " total bars", color.yellow);
addlabel(show_labels, sig_cnt + " signals", color.yellow);
addlabel(show_labels, sig_group_cnt + " groups", color.yellow);
addlabel(show_labels, sqz_bars_per + " % of bars in groups", color.yellow);
#addlabel(show_labels, , color.yellow);
addlabel(show_labels, avg_group_len + " avg group len", color.yellow);
addlabel(show_labels, last_group_bars + " last group len", color.green);
addlabel(show_labels, future_bars + " bars remaining", color.green);
#------------------------
# test stuff
addchartbubble(0, 0,
ttm_histo + " h\n" +
ttm_volcomp + " v\n" +
ttm_sqz + "sqz"
, color.yellow, no);
addchartbubble(0, 50,
# ttm_histo + " h\n" +
ttm_volcomp + " v\n"
# ttm_sqz + "sqz"
, (if ttm_volcomp then color.yellow else color.gray), yes);
input test1_data = no;
addchartbubble(test1_data and !isnan(close), -15,
bn + "\n" +
bar_cnt + " bn\n" +
sig_cnt + " Sbars\n" +
sig_group_cnt + " Sqty\n" +
sqz_bars_per + " %bars\n" +
avg_group_len + " avg len\n" +
last_group_bars + " last"
#future_bars
#x
, color.yellow, no);
input test2_data = no;
addchartbubble(test2_data, -15,
avg_group_len + " avg len\n" +
last_group_bars + " last\n" +
future_bars + " x\n" +
x
, color.yellow, no);
#