Indicator · Pine Script v5 · Own pane

BB Keltner Squeeze Oscillator

by g-moe· code credited to goodgains

The BB Keltner Squeeze Oscillator combines Bollinger Bands and Keltner Channels to identify market volatility squeezes alongside dual moving average momentum oscillators.

View on GitHub

GitHub stars3on the repository
Pine versionv5runs as is
Lines of code90
Settings13inputs
LicenceNone statedfile: MPL-2.0
Last update5 months ago27 May 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

90 lines of Pine Script v5 from Tradingview/bb-keltner-squeeze-oscillator.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

bb-keltner-squeeze-oscillator.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © goodgains


//@version=5
indicator("BB Keltner Squeeze Oscillator", overlay = false)

// @keywords: bollinger-bands, keltner-channel, volatility-squeeze, squeeze-oscillator, dual-oscillator, column-histogram, average-true-range, standard-deviation, bollinger-upper-band, keltner-upper-band, hull-smoothing, zero-line-cross, volatility-compression, squeeze-release, momentum-oscillator, configurable-moving-average, oscillator-crossover, squeeze-filter-signals, triangle-markers, band-squeeze-comparison

price = input.source(close, title = 'Price')

nHoMA = input.int(8)
nHo1 = input.int(17)
nHo2 = input.int(34)
nHoSm = input.int(8)

hoTypeMA = input.string("EMA", options = ["EMA", "SMA", "HMA", "WMA"])
hoType1 = input.string("EMA", options = ["EMA", "SMA", "HMA", "WMA"])
hoType2 = input.string("EMA", options = ["EMA", "SMA", "HMA", "WMA"])
hoTypeSM = input.string("EMA", options = ["EMA", "SMA", "HMA", "WMA"])


bbKcLength = input.int(20)
bbDevUp = input.float(2.0)
kcFactor = input.float(1.5)
bbKcAvgType = input.string("SMA", options = ["EMA", "SMA", "HMA", "WMA"])


ma(source, maType, maLength) =>
    float ma = switch maType
        "EMA" => ta.ema(source, maLength)
        "SMA" => ta.sma(source, maLength)
        "HMA" => ta.hma(source, maLength)
        "WMA" => ta.wma(source, maLength)
        => ta.wma(source, maLength)


atr = ta.atr(bbKcLength)

sDev = ta.stdev(price, bbKcLength)
ma = ma(price, bbKcAvgType, bbKcLength)
bbUB = ma + bbDevUp * sDev
kcUB = ma + (kcFactor * atr)
squeezed = bbUB < kcUB

p = ((nHoMA - 1)  * ma(price, hoTypeMA, nHoMA)[1] + price) / nHoMA
pr1 = price
pr2 = price

var float rHo1 = 0.00
rHo1_src = ma(pr1, hoType1, math.abs(nHo1)) 
rHo1 := rHo1_src
var float rHo2 = 0.00
rHo2_src = ma(pr2, hoType2, math.abs(nHo2)) 
rHo2 := rHo2_src

p1_repaint = math.abs((-nHo1 / 2) + 1)
p2_repaint = math.abs((-nHo2 / 2) + 1)

historicalP1 = p[p1_repaint]
historicalP2 = p[p2_repaint]

osc2 = ma(rHo2-historicalP2, hoTypeSM, nHoSm)
plot(osc2, style = plot.style_columns, linewidth = 1, offset = -0,
     color = osc2 > 0 and osc2 > osc2[1] ? color.rgb(34, 39, 199) : osc2 > 0 ? color.rgb(23, 161, 207)
     : osc2 < osc2[1] ? color.rgb(224, 174, 213) : color.rgb(233, 23, 201))

osc1 = ma(rHo1-historicalP1, hoTypeSM, nHoSm)
plot(osc1, style = plot.style_columns, linewidth = 1, offset = -0,
     color = osc1 > 0 and osc1 > osc1[1] ? color.green : osc1 > 0 ? color.rgb(48, 82, 49)
     : osc1 < osc1[1] ? color.red : color.rgb(146, 39, 39))

plot(0, style = plot.style_circles, color = squeezed ? color.red : color.new(#000000,0), linewidth = 2)


crossOver = ta.crossover(osc2, 0)
crossUnder = ta.crossunder(osc2, 0)
cr1 = crossOver ? 1 : crossUnder ? -1 : 0


u1 = osc1 > 0 and cr1 > 0 and not squeezed ? -5 : na
d1 = osc1 < 0 and cr1 < 0 and not squeezed ? 5 : na
plotshape(u1, title = 'u1', style = shape.triangleup, color = color.rgb(0, 185, 213), location = location.bottom, size = size.tiny)
plotshape(d1, title = 'd1', style = shape.triangledown, color = color.rgb(198, 0, 165), location = location.top, size = size.tiny)


u2 = osc1 > 0 and cr1 > 0 and squeezed ? -5 : na
d2 = osc1 < 0 and cr1 < 0 and squeezed ? 5 : na
plotshape(u2, title = 'u2', style = shape.triangleup, color = color.green, location = location.bottom, size = size.tiny)
plotshape(d2, title = 'd2', style = shape.triangledown, color = color.red, location = location.top, size = size.tiny)

Overview

BB Keltner Squeeze Oscillator plots two column histograms and zero-line squeeze dots in a separate pane below the price chart. Squeezes occur when Bollinger Bands contract within Keltner Channels. The indicator identifies directional momentum crosses using configurable moving averages (EMA, SMA, HMA, or WMA) and marks momentum signals with triangular shapes. Traders can adjust smoothing lengths, moving average types, standard deviation multipliers, and ATR factors.

Details

Published by

g-moe on GitHub

Code credit

goodgains, as written in the script's header

Type

Indicator, Pine Script v5

Draws

Separate pane below the chart

Category

Volatility & bands, Oscillators & momentum, Moving averages

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Pricesourcecloseprice
nHoMAint8nHoMA
nHo1int17nHo1
nHo2int34nHo2
nHoSmint8nHoSm
hoTypeMAstringEMAhoTypeMA
hoType1stringEMAhoType1
hoType2stringEMAhoType2
hoTypeSMstringEMAhoTypeSM
bbKcLengthint20bbKcLength
bbDevUpfloat2.0bbDevUp
kcFactorfloat1.5kcFactor
Show all 13 settings
SettingTypeDefaultVariable
bbKcAvgTypestringSMAbbKcAvgType
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

MACD-V

by harryguiacorn
219 stars

MACD-V is a volatility-normalized momentum indicator based on research by Alex Spiroglou. It calculates the standard MACD histogram and normalizes it by dividing by the Average True Range (ATR). Plotted in a separate pane as a colored histogram, it includes us

Indicator v5 Oscillators & momentumVolatility & bands
Updated 1 year ago · None stated GitHub repository of MACD-V

MultiIndicator

by capissimo
114 stars

MultiIndicator combines multiple technical indicators into a single separate pane to save chart space. It calculates and displays market regime detection based on ordinary least squares regression, a Holt exponential smoothing crossover, normalized RSI, ADX, a

Indicator v4 Oscillators & momentumTrend
Updated 1 year ago · None stated GitHub repository of MultiIndicator

PPO ATR Bands

by cryptorife
75 stars

PPO ATR Bands plots a percentage price oscillator in a separate pane. It compares a Hull average of typical price with a volume-weighted exponential average of Parabolic SAR, then scales three true-range bands around the slow average into matching oscillator l

Indicator v4 Oscillators & momentumMoving averages
Updated 3 years ago · GPL-3.0 GitHub repository of PPO ATR Bands

This indicator plots a relative strength index in a separate pane. It calculates RSI from the average of the previous ten opens rather than the current bar, so that source does not change during the live candle. A moving average of the RSI is plotted and can b

Indicator v5 Oscillators & momentumMoving averages
Updated 2 years ago · None stated GitHub repository of No Repaint - Relative Strength Index

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers