Edgoro
Volatility indicator

Squeeze momentum indicator: formula, settings and Pine Script v6 code

How the squeeze flags low volatility when Bollinger Bands move inside Keltner Channels, how traders read the release and momentum, and a free script.

What it measures

The squeeze compares two volatility envelopes. Bollinger Bands use the standard deviation of closes; Keltner Channels use the average bar range. When a market goes quiet, the standard deviation usually shrinks faster than the average range, and the Bollinger Bands move inside the Keltner Channel. That condition is the squeeze: volatility is compressed. When the bands move back outside, the squeeze releases.

John Carter described the setup, as the TTM Squeeze, in his book Mastering the Trade. The version most people use on TradingView adds a momentum histogram to suggest the direction of the release.

The formula in words

  1. Bollinger Bands: 20-period SMA of the close ± 2 standard deviations.
  2. Keltner Channel: 20-period SMA ± 1.5 × the 20-period average of the true range.
  3. Squeeze on while the upper Bollinger Band is below the upper Keltner band and the lower Bollinger Band is above the lower Keltner band.
  4. Release on the first bar after a squeeze when that's no longer true.
  5. Momentum: take the close minus the average of two references, the midpoint of the 20-bar high-low range and the 20-period SMA. Fit a 20-bar linear regression line to that series and take its latest value.

Step 5 follows the widely shared open-source version of the indicator. It's a smoothed measure of where the close sits relative to its recent range: positive when the close is above the middle of that range.

How traders read it

  • The dots. The script draws a row of dots on the zero line: orange while the squeeze is on, grey while it's off. A long run of orange dots means a long quiet period.
  • The release. The first grey dot after a run of orange ones is the release. Traders read the histogram at that moment for direction: above zero and rising suggests an upside expansion, below zero and falling a downside one.
  • Histogram shades. Bright bars mean momentum is growing in that direction; faded bars mean it's fading. A change from bright to faded is often used as an exit cue.
  • Context. A squeeze says volatility is low, not which way it will expand. Many traders take releases only in the direction of a higher-timeframe trend.

Common settings

SettingTypical valueNotes
Bollinger Bands20, 2The standard Bollinger settings.
Keltner Channel20, 1.51.0 gives fewer squeezes, 2.0 many more.
Momentum length20Matches the band lengths.

The Keltner multiplier decides how strict the squeeze is. With 2.0 the bands sit inside the channel often; with 1.0, only during very quiet periods.

Pine Script v6 code

The complete, self-contained script is below. Copy it into a new indicator in TradingView's Pine Editor, or download the .pine file.

Pine Script v6
//@version=6
indicator("Squeeze momentum (Bollinger inside Keltner)", shorttitle = "Squeeze")

bbLen  = input.int(20, "Length", minval = 2, group = "Bollinger Bands")
bbMult = input.float(2.0, "Width (x standard deviation)", minval = 0.1, step = 0.1, group = "Bollinger Bands")
kcLen  = input.int(20, "Length", minval = 1, group = "Keltner Channels")
kcMult = input.float(1.5, "Width (x average range)", minval = 0.1, step = 0.1, group = "Keltner Channels")
useTr  = input.bool(true, "Use true range for the width", group = "Keltner Channels")
momLen = input.int(20, "Length", minval = 2, group = "Momentum")

// Bollinger Bands: SMA +/- a multiple of the standard deviation.
basis   = ta.sma(close, bbLen)
dev     = bbMult * ta.stdev(close, bbLen)
upperBB = basis + dev
lowerBB = basis - dev

// Keltner Channels: SMA +/- a multiple of the average range.
kcMid   = ta.sma(close, kcLen)
trueRng = ta.tr(true)
rng     = useTr ? trueRng : high - low
rangeMa = ta.sma(rng, kcLen)
upperKC = kcMid + kcMult * rangeMa
lowerKC = kcMid - kcMult * rangeMa

// The squeeze is on while both Bollinger Bands sit inside the Keltner Channel.
sqzOn    = upperBB < upperKC and lowerBB > lowerKC
sqzStart = sqzOn and not sqzOn[1]
released = not sqzOn and sqzOn[1]

// Momentum: linear regression of the close's distance from the middle of the recent range and its average.
hh  = ta.highest(high, momLen)
ll  = ta.lowest(low, momLen)
avg = ta.sma(close, momLen)
mom = ta.linreg(close - math.avg(math.avg(hh, ll), avg), momLen, 0)

releaseUp   = released and mom > 0
releaseDown = released and mom < 0

momCol = mom >= 0 ? (mom > mom[1] ? color.new(color.teal, 0) : color.new(color.teal, 55)) : (mom < mom[1] ? color.new(color.red, 0) : color.new(color.red, 55))
plot(mom, "Momentum", color = momCol, style = plot.style_columns)
plot(0, "Squeeze", color = sqzOn ? color.new(color.orange, 0) : color.new(color.gray, 40), style = plot.style_circles, linewidth = 3)

alertcondition(sqzStart, "Squeeze starts", "Bollinger Bands moved inside the Keltner Channel on {{ticker}} ({{interval}})")
alertcondition(releaseUp, "Squeeze releases up", "The squeeze released with positive momentum on {{ticker}} ({{interval}})")
alertcondition(releaseDown, "Squeeze releases down", "The squeeze released with negative momentum on {{ticker}} ({{interval}})")

The momentum histogram uses four shades: bright green and red while momentum grows, faded while it shrinks. Dots on the zero line show the squeeze state. Every length and width is an input, including whether the Keltner width uses the true range or the plain high-low range.

Three alert conditions cover the start of a squeeze and a release with positive or negative momentum. A release is decided on the close, so set alerts to Once per bar close.

Add it to your chart

  1. Open any chart on TradingView and open the Pine Editor.
  2. Create a new indicator, delete the template code and paste the script.
  3. Click Save, then Add to chart. Change lengths and levels from the indicator's settings.

Stuck on an error? See how to add a Pine Script indicator to TradingView.

Pitfalls

  • A squeeze is not a direction. Low volatility tends to be followed by higher volatility, but the release can go either way, and the first move is often reversed.
  • Long squeezes. Volatility can stay compressed for a long time. Entering because a release feels "due" ties up risk without a trigger.
  • Momentum lag. The histogram is a 20-bar regression. It confirms direction after the move has started.
  • Different versions. Commercial and open-source versions use slightly different bands and momentum formulas. Compare settings before comparing signals.

The script is an educational example: test it on your own markets before relying on it. Indicators describe the past; they don't predict the future. Trading involves substantial risk of loss and is not suitable for every investor. Edgoro is a software tool, not a broker or financial adviser: nothing it produces is investment advice, and past or backtested performance does not guarantee future results.

Make it yours with Edgoro

Describe the change in plain English and Edgoro writes the Pine Script v6 for you, ready to paste. For example:

“Show a Bollinger-inside-Keltner squeeze (20, 2, 1.5) and alert on the first release with positive momentum when the daily close is above the daily 50 EMA.”

Build your Squeeze momentum indicator