Volatility

Bollinger Bands Signals: Touches, Compression and Breakouts

Distinguish band-touch, compression and breakout rules with a Pine Script example. Check the exact conditions instead of assuming a measured reversal probability.

Bollinger Bands Signal Interpretation

Quick-reference guide to 5 signal types you will see on the chart.

Signal TypeIndicator ConditionMarket MeaningInterpretation limits
Lower-band rejection exampleLow touches/breaches lower band, close returns above it, and close exceeds openThe completed bar recovered relative to its final lower band.Does not prove a bottom; the band also moves during the bar.
Upper-band rejection exampleHigh touches/breaches upper band, close returns below it, and close is below openThe completed bar retreated relative to its final upper band.Does not prove a top or require a subsequent decline.
Compression stateRaw band width is below its moving average and below its value one lookback agoThis example’s exact two-comparison definition.Not necessarily the lowest width in the window.
Breakout following compressionPrior bar satisfied compression; current close finishes outside a bandA one-bar sequence of defined events.No minimum expansion size or duration is implied.
Three closes outside a bandThree consecutive closes beyond the same boundaryAn example of persistence rather than a bounce.Can continue or fail; no reliability score is established.

Bollinger Bands Pine Script Signal Code

Educational indicator example. Review its exact rules and compare its plots with your intended calculation in TradingView. It does not place orders or establish profitability.

Pine Script v6
//@version=6
indicator("Bollinger Band Condition Examples", overlay=true)

bbLength = input.int(20, "BB Length", minval=1)
bbMult = input.float(2.0, "BB Std Dev", minval=0.1)
src = input.source(close, "Source")
squeezeLookback = input.int(20, "Squeeze Lookback", minval=1, tooltip="Number of bars for squeeze comparison baseline")

// Bollinger Bands calculation
basis = ta.sma(src, bbLength)
dev = bbMult * ta.stdev(src, bbLength)
upper = basis + dev
lower = basis - dev

// Band width
bandWidth = upper - lower
avgBandWidth = ta.sma(bandWidth, squeezeLookback)

// Buy signal: price touches lower band, closes back inside
lowerTouch = low <= lower
lowerBounce = close > lower
buySignal = barstate.isconfirmed and lowerTouch and lowerBounce and close > open

// Sell signal: price touches upper band, closes back inside
upperTouch = high >= upper
upperReject = close < upper
sellSignal = barstate.isconfirmed and upperTouch and upperReject and close < open

// Squeeze detection
isSqueeze = bandWidth < avgBandWidth and bandWidth < bandWidth[squeezeLookback]
squeezeBreakoutUp = barstate.isconfirmed and isSqueeze[1] and close > upper
squeezeBreakoutDown = barstate.isconfirmed and isSqueeze[1] and close < lower

// Band walk detection: 3+ consecutive closes outside a band
walkUp = barstate.isconfirmed and close > upper and close[1] > upper[1] and close[2] > upper[2]
walkDown = barstate.isconfirmed and close < lower and close[1] < lower[1] and close[2] < lower[2]

// Plot Bollinger Bands
plot(basis, "Basis", color=#2962FF, linewidth=2)
p1 = plot(upper, "Upper", color=#FF5252, linewidth=1)
p2 = plot(lower, "Lower", color=#4CAF50, linewidth=1)
fill(p1, p2, color=color.new(color.gray, 92), title="Band Fill")

// Plot buy and sell signals on the price chart
plotshape(buySignal, "Lower-band rejection", shape.triangleup, location.belowbar, color=#4CAF50, size=size.small)
plotshape(sellSignal, "Upper-band rejection", shape.triangledown, location.abovebar, color=#FF5252, size=size.small)

// Squeeze markers
plotshape(squeezeBreakoutUp, "Squeeze Buy", shape.labelup, location.belowbar, color=#00BCD4, size=size.small)
plotshape(squeezeBreakoutDown, "Squeeze Sell", shape.labeldown, location.abovebar, color=#FF9800, size=size.small)

// Band walk labels
plotshape(walkUp, "Band Walk Up", shape.circle, location.abovebar, color=#E040FB, size=size.tiny)
plotshape(walkDown, "Band Walk Down", shape.circle, location.belowbar, color=#E040FB, size=size.tiny)

// Band width subplot
plot(bandWidth, "Band Width", color=#757575, display=display.none)

alertcondition(buySignal, "BB Lower Band Rejection", "Price closed above the lower Bollinger Band after touching it")
alertcondition(sellSignal, "BB Upper Band Rejection", "Price closed below the upper Bollinger Band after touching it")
alertcondition(barstate.isconfirmed and isSqueeze, "BB Squeeze", "Confirmed width below its average and its lookback-ago value")
alertcondition(squeezeBreakoutUp, "BB Squeeze Breakout Up", "Price broke above upper band after a squeeze")
alertcondition(squeezeBreakoutDown, "BB Squeeze Breakout Down", "Price broke below lower band after a squeeze")

Example settings for Bollinger Bands

Record the inputs used by the example. These settings are not an optimized trading recommendation.

Feature comparison table: Default vs Description
ParameterDefaultDescription
BB Length20, exampleLookback for the SMA basis and standard deviation. The script uses an SMA rather than every available built-in basis type.
BB Std Dev2.0, exampleMultiplier applied to measured dispersion. It does not establish 95% coverage for future prices.
SourceCloseUsed for band calculation; touch rules separately compare chart high, low, open and close.
Squeeze Lookback20, exampleControls the width average and the single past-width comparison. It is not a rolling minimum operator.

Turn the condition into an explicit rule

Specify the calculation, confirmation time, entry and exit rules before asking Pineify to draft or revise Pine Script. Review the code and simulate realistic costs before evaluating a strategy.

Explore Pine Script coding

FAQ

Bollinger Bands Signals FAQ

Is a band touch an instruction to buy or sell?
No. A band is a calculated boundary and price can continue outside it. The example requires a particular completed candle for its rejection marker, without claiming that this predicts the next move.
What does the compression rule actually test?
It compares raw width with its moving average and one value a lookback ago. To test a rolling minimum, percentile or Keltner-channel squeeze, implement that different definition explicitly. Do not label these interchangeable.
How is %B different from width?
%B expresses the source’s position between lower and upper bands; it can be below zero or above one. Width measures separation. A %B of 0.5 corresponds to the basis, not a confirmed trend re-entry. The example does not emit %B alerts.
Are Bollinger Bands always wider than Keltner Channels?
No. They use different dispersion measures and inputs. Neither relative width nor comparative win rate is fixed across markets.
How should I evaluate combined RSI and band conditions?
Write both conditions and their confirmation times, then compare the complete rule with a baseline using costs and reserved data. Adding an oscillator does not itself establish improved accuracy.
What happens during news or an open bar?
New observations can change the bands, and a wick is compared with the final calculated boundary in this example. Markers wait for close. This is a bar-based condition, not a reconstruction of the exact intrabar order of touches.