@laketrader This is excellent with labels. It does complain if current timeframe is larger than a timeframe on the study. For eg, won't show a 5 minute sqz with 15 min chart complaining "Secondary period cannot be less than primary." I recently attended one of the webinars where they were selling something similar with another row of labels to show histogram colors as well and I was thinking if I can code this. I have never really coded in thinkscript but I will give it a go tomorrow. Another thing I might attempt will be to combine all the studies in 1 so upper study doesn't get flooded. Thank you so much for this!
declare weak_volume_dependency;
input timeFrame = AggregationPeriod.HOUR;
input length = 20;
def price = close("Period" = timeFrame);
#Borrowed from Momentum Squeeze - Mobius
def K = (Highest(high("Period" = timeFrame), length) + Lowest(low("Period" = timeFrame), length) + ExpAverage(price, length)) / 3;
def Momo = Inertia(price - K, length);
def cyan = Momo > 0 and Momo > Momo[1];
def blue = Momo > 0 and Momo < Momo[1];
def red = Momo < 0 and Momo < Momo[1];
def yellow = Momo < 0 and Momo > Momo[1];
AddLabel(yes, if timeFrame == aggregationPeriod.MONTH then "M"
else
if timeFrame == aggregationPeriod.WEEK then "W"
else
if timeFrame == aggregationPeriod.FOUR_DAYS then "4D"
else
if timeFrame == aggregationPeriod.THREE_DAYS then "3D"
else
if timeFrame == aggregationPeriod.TWO_DAYS then "2D"
else
if timeFrame == aggregationPeriod.DAY then "D"
else
if timeFrame == aggregationPeriod.FOUR_HOURS then "4H"
else
if timeFrame == aggregationPeriod.TWO_HOURS then "2H"
else
if timeFrame == aggregationPeriod.HOUR then "60m"
else
if timeFrame == aggregationPeriod.THIRTY_MIN then "30m"
else
if timeFrame == aggregationPeriod.TWENTY_MIN then "20m"
else
if timeFrame == aggregationPeriod.FIFTEEN_MIN then "15m"
else
if timeFrame == aggregationPeriod.TEN_MIN then "10m"
else
if timeFrame == aggregationPeriod.FIVE_MIN then "5m"
else
if timeFrame == aggregationPeriod.FOUR_MIN then "4m"
else
if timeFrame == aggregationPeriod.THREE_MIN then "3m"
else
if timeFrame == aggregationPeriod.TWO_MIN then "2m"
else
if timeFrame == aggregationPeriod.MIN then "1m"
else "", if cyan then Color.CYAN
else if blue then Color.BLUE
else if red then Color.RED
else if yellow then Color.YELLOW
else Color.BLACK
);
#Borrowed from Momentum Squeeze - Mobius def K = (Highest(high("Period" = timeFrame), length) + Lowest(low("Period" = timeFrame), length) + ExpAverage(price, length)) / 3; def Momo = Inertia(price - K, length);
I see. So this is the magic squeeze formula? Does this exactly match with TTM_Squeeze? I was trying to use TTM_Squeeze histogram and I could get it working for current timeframe, but not for multiple timeframes as it doesn't take time/aggregation period as inputs. But I tried to do it some other way as described here but so far no luck.
I will try this one. Thank you!
Do I have to add the link and customize for each timeframe?
When I add the study, I only get one label. Was curious if there is a way to set how many timeframes in the code?
Understood and thank you for the quick reply.You have to add it multiple times to get multiple timeframes.
input triggerBars = 6;
input LongShortDefinition = { default HistAboveBelowZero, HistRisingFalling, HistRisingFromBelowFallingFromAbove};
def nBB = 2.0;
def Length = 20.0;
def nK_High = 1.0;
def nK_Mid = 1.5;
def nK_Low = 2.0;
def price = close;
input signalOffsetFactor = 1.0;
def momentum = TTM_Squeeze(price = price, length = length, nk = nk_Mid, nbb = nbb)."Histogram";
def oscillator = momentum;
def BolKelDelta_Mid = reference BollingerBands("num_dev_up" = nBB, "length" = Length )."upperband" - KeltnerChannels("factor" = nK_Mid, "length" = Length)."Upper_Band";
def BolKelDelta_Low = reference BollingerBands("num_dev_up" = nBB, "length" = Length )."upperband" - KeltnerChannels("factor" = nK_Low, "length" = Length)."Upper_Band";
def BolKelDelta_High = reference BollingerBands("num_dev_up" = nBB, "length" = Length )."upperband" - KeltnerChannels("factor" = nK_High, "length" = Length)."Upper_Band";
def signalOffset = Average(TrueRange(high, close, low), 10) * signalOffsetFactor;
def lowSqueeze = BolKelDelta_Low <= 0;
def triggerLow = if sum(lowSqueeze,triggerBars) == triggerBars and !lowSqueeze[triggerBars] then 1 else 0;
plot signalLowLong = if triggerLow and ((LongShortDefinition == LongShortDefinition.HistAboveBelowZero and oscillator > 0) or (LongShortDefinition == LongShortDefinition.HistRisingFalling and oscillator > oscillator[1]) or (LongShortDefinition == LongShortDefinition.HistRisingFromBelowFallingFromAbove and oscillator > oscillator[1] and oscillator < 0 )) then low-signalOffset else double.nan;
signalLowLong.SetPaintingStrategy(paintingStrategy.ARROW_UP);
signalLowLong.setDefaultColor(color.black);
signalLowLong.setLineWeight(5);
plot signalLowShort = if triggerLow and ((LongShortDefinition == LongShortDefinition.HistAboveBelowZero and oscillator <= 0) or (LongShortDefinition == LongShortDefinition.HistRisingFalling and oscillator < oscillator[1]) or (LongShortDefinition == LongShortDefinition.HistRisingFromBelowFallingFromAbove and oscillator < oscillator[1] and oscillator > 0 )) then high+signalOffset else double.nan;
signalLowShort.SetPaintingStrategy(paintingStrategy.ARROW_Down);
signalLowShort.setDefaultColor(color.black);
signalLowShort.setLineWeight(5);
Understood and thank you for the quick reply.
One more question: How would I insert this version of squeeze (below) into your code?
I think this is for lower, but I'd like to use in the upper.
Thoughts?
Code:input triggerBars = 6; input LongShortDefinition = { default HistAboveBelowZero, HistRisingFalling, HistRisingFromBelowFallingFromAbove}; def nBB = 2.0; def Length = 20.0; def nK_High = 1.0; def nK_Mid = 1.5; def nK_Low = 2.0; def price = close; input signalOffsetFactor = 1.0; def momentum = TTM_Squeeze(price = price, length = length, nk = nk_Mid, nbb = nbb)."Histogram"; def oscillator = momentum; def BolKelDelta_Mid = reference BollingerBands("num_dev_up" = nBB, "length" = Length )."upperband" - KeltnerChannels("factor" = nK_Mid, "length" = Length)."Upper_Band"; def BolKelDelta_Low = reference BollingerBands("num_dev_up" = nBB, "length" = Length )."upperband" - KeltnerChannels("factor" = nK_Low, "length" = Length)."Upper_Band"; def BolKelDelta_High = reference BollingerBands("num_dev_up" = nBB, "length" = Length )."upperband" - KeltnerChannels("factor" = nK_High, "length" = Length)."Upper_Band"; def signalOffset = Average(TrueRange(high, close, low), 10) * signalOffsetFactor; def lowSqueeze = BolKelDelta_Low <= 0; def triggerLow = if sum(lowSqueeze,triggerBars) == triggerBars and !lowSqueeze[triggerBars] then 1 else 0; plot signalLowLong = if triggerLow and ((LongShortDefinition == LongShortDefinition.HistAboveBelowZero and oscillator > 0) or (LongShortDefinition == LongShortDefinition.HistRisingFalling and oscillator > oscillator[1]) or (LongShortDefinition == LongShortDefinition.HistRisingFromBelowFallingFromAbove and oscillator > oscillator[1] and oscillator < 0 )) then low-signalOffset else double.nan; signalLowLong.SetPaintingStrategy(paintingStrategy.ARROW_UP); signalLowLong.setDefaultColor(color.black); signalLowLong.setLineWeight(5); plot signalLowShort = if triggerLow and ((LongShortDefinition == LongShortDefinition.HistAboveBelowZero and oscillator <= 0) or (LongShortDefinition == LongShortDefinition.HistRisingFalling and oscillator < oscillator[1]) or (LongShortDefinition == LongShortDefinition.HistRisingFromBelowFallingFromAbove and oscillator < oscillator[1] and oscillator > 0 )) then high+signalOffset else double.nan; signalLowShort.SetPaintingStrategy(paintingStrategy.ARROW_Down); signalLowShort.setDefaultColor(color.black); signalLowShort.setLineWeight(5);
Are you talking about the multiple timeframe squeeze?
Yes. In another chat, someone said this is a better version of squeeze, but I am not sure what I am looking at.
So I was curious if the squeeze code in your MTF script could somehow be replaced with the code I posted.
def midSqueeze = BolKelDelta_Mid <= 0;
def triggerMid = if sum(midSqueeze,triggerBars) == triggerBars and !midSqueeze[triggerBars] then 1 else 0;
plot signalMidLong = if triggerMid and ((LongShortDefinition == LongShortDefinition.HistAboveBelowZero and oscillator > 0) or (LongShortDefinition == LongShortDefinition.HistRisingFalling and oscillator > oscillator[1]) or (LongShortDefinition == LongShortDefinition.HistRisingFromBelowFallingFromAbove and oscillator > oscillator[1] and oscillator < 0 )) then low-signalOffset else double.nan;
signalMidLong.SetPaintingStrategy(paintingStrategy.ARROW_UP);
signalMidLong.setDefaultColor(color.red);
signalMidLong.setLineWeight(5);
plot signalMidShort = if triggerMid and ((LongShortDefinition == LongShortDefinition.HistAboveBelowZero and oscillator <= 0) or (LongShortDefinition == LongShortDefinition.HistRisingFalling and oscillator < oscillator[1]) or (LongShortDefinition == LongShortDefinition.HistRisingFromBelowFallingFromAbove and oscillator < oscillator[1] and oscillator > 0 )) then high+signalOffset else double.nan;
signalMidShort.SetPaintingStrategy(paintingStrategy.ARROW_Down);
signalMidShort.setDefaultColor(color.red);
signalMidShort.setLineWeight(5);
def highSqueeze = BolKelDelta_High <= 0;
def triggerHigh = if sum(highSqueeze,triggerBars) == triggerBars and !highSqueeze[triggerBars] then 1 else 0;
plot signalHighLong = if triggerHigh and ((LongShortDefinition == LongShortDefinition.HistAboveBelowZero and oscillator > 0) or (LongShortDefinition == LongShortDefinition.HistRisingFalling and oscillator > oscillator[1]) or (LongShortDefinition == LongShortDefinition.HistRisingFromBelowFallingFromAbove and oscillator > oscillator[1] and oscillator < 0 )) then low-signalOffset else double.nan;
signalHighLong.SetPaintingStrategy(paintingStrategy.ARROW_UP);
signalHighLong.setDefaultColor(color.dark_orange);
signalHighLong.setLineWeight(5);
plot signalHighShort = if triggerHigh and ((LongShortDefinition == LongShortDefinition.HistAboveBelowZero and oscillator <= 0) or (LongShortDefinition == LongShortDefinition.HistRisingFalling and oscillator < oscillator[1]) or (LongShortDefinition == LongShortDefinition.HistRisingFromBelowFallingFromAbove and oscillator < oscillator[1] and oscillator > 0 )) then high+signalOffset else double.nan;
signalHighShort.SetPaintingStrategy(paintingStrategy.ARROW_Down);
signalHighShort.setDefaultColor(color.dark_orange);
signalHighShort.setLineWeight(5);
All - I've been working on building a comparable setup to John Carter's squeeze pro labels + histogram labels.
I was able to modify code I found here to accomplish the "squeeze pro" portion of this. Unfortunately, it is tough to find a histogram that matches Carter's. Mobius' code has a good histogram but I find it not nearly as smooth as John Carter's. However, I found the "Awesome Oscillator" in TOS to be very close to the TTM_Squeeze histogram when you modify the 2 period lengths in the code to be 9 & 21 instead of 5 & 34. I took this logic and built an "MTF histogram label" that sits just underneath the squeeze label...similar to JC's. I've watched several of his videos and confirmed that the squeeze portion of my code works verbatim to his. The histogram is not exact but it is "damn close."
Pic of my setup here: https://ibb.co/VVTH65K
Here is a link to my shared grid, containing the histogram & squeeze labels: https://tos.mx/xkLakTN
Color legend for those unfamiliar:
- Top row are the squeezes - Gray = low squeeze, Red = med squeeze (same as the original TTM_Squeeze indicator) and Yellow = high squeeze (this is the tightest squeeze).
- Bottom row contains histograms: Cyan = increasing positive momentum, Blue = waning positive momentum, Red = increasing negative momentum & Yellow = waning negative momentum.
Let me know your thoughts...
Join useThinkScript to post your question to a community of 21,000+ developers and traders.
Start a new thread and receive assistance from our community.
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.
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.