Data Analytic Investments
Volatility & BandsBeginnerBollinger Ball

Bollinger Bands

Bollinger Bands explained: how the bands, %B and Bandwidth are calculated, and what they describe — and what they do not. Educational content.

1H, 4H, Daily
Crypto, Forex, Equities, Commodities
Pine Script v5

What is it?

Created by John Bollinger in the 1980s, Bollinger Bands consist of a middle band (typically a 20-period SMA) and two outer bands plotted at ±2 standard deviations from the middle band. Because standard deviation is a measure of volatility, the bands widen when price is volatile and contract when it is quiet. Approximately 95% of price action falls within the bands under normal distribution assumptions — though crypto markets frequently violate this. The 'Bollinger Squeeze' (bands narrowing to a multi-month low) describes a period of unusually low volatility. It does not say when volatility will rise or in which direction price will move.

How it is calculated

  • Middle band: the simple moving average (SMA) of the last 20 closing prices.
  • Upper band: the middle band plus 2 × the standard deviation of the same 20 prices.
  • Lower band: the middle band minus 2 × that standard deviation.

Both the length (20) and the multiplier (2) are settings. 20 and 2 are the values John Bollinger suggested as a starting point.

Two derived measures: %B and Bandwidth

  • %B = (price − lower band) ÷ (upper band − lower band). A value of 1 means price is at the upper band, 0 means it is at the lower band, and 0.5 means it is at the middle band. Above 1 or below 0 means price closed outside the bands.
  • Bandwidth = (upper band − lower band) ÷ middle band. It shows how wide the bands are relative to price. The "squeeze" in the free template below is a Bandwidth reading close to its 125-bar low.

What the bands describe — and what they do not

  • They describe how far price is from its recent average, measured in units of recent volatility.
  • They do not describe direction, a future price, or whether a move will continue. A close outside the bands is a statistical observation, not a forecast.

Related indicators

  • Keltner Channels — an EMA middle line with bands based on ATR.
  • ATR — volatility measured in price units.
  • RSI — momentum on a 0–100 scale.

Common pitfalls

  • Touching the band is not an indication by itself. In a trending market, price can walk the upper band for dozens of candles. A band touch on its own says nothing about the trend.
  • The 2-standard-deviation setting means roughly 5% of closes will be outside the bands by definition — these are not rare events.
  • Bollinger Bands use a simple moving average as the middle band. An EMA-based middle band, as in the Keltner Channel, reacts faster to recent prices.
  • A squeeze describes low volatility. It does not tell you whether a larger move will follow, or in which direction.
  • Bands calculated on closing prices miss intraday wicks. A wick that pierces the band but closes inside it is not a confirmed band touch.

Indicator Rider — Bollinger Ball

The Bollinger Ball bounces between the upper and lower bands — cyan at the top, orange at the bottom — with squash-and-stretch physics on impact.

Free code template

Paste directly into TradingView Pine Editor → Add to chart.

Pine Script v5
/indicator("Bollinger Bands — DAI Template", overlay=true)

// ── Inputs ──────────────────────────────────────────────────────────────────
bbLen   = input.int(20,  "BB Length",     minval=1)
bbMult  = input.float(2.0, "Multiplier", minval=0.1, step=0.1)
src     = input.source(close, "Source")

// ── Calculation ─────────────────────────────────────────────────────────────
[mid, upper, lower] = ta.bb(src, bbLen, bbMult)
bandwidth = (upper - lower) / mid * 100

// ── Plots ───────────────────────────────────────────────────────────────────
pUpper = plot(upper, "Upper Band", color=color.new(#8b5cf6, 20), linewidth=1)
pLower = plot(lower, "Lower Band", color=color.new(#8b5cf6, 20), linewidth=1)
pMid   = plot(mid,   "Middle SMA", color=color.new(#94a3b8, 40), linewidth=1)
fill(pUpper, pLower, color.new(#8b5cf6, 92))

// ── Squeeze Detection ────────────────────────────────────────────────────────
bwLow  = ta.lowest(bandwidth, 125)  // 125-bar low of bandwidth
squeeze = bandwidth <= bwLow * 1.05  // within 5% of 125-bar low
bgcolor(squeeze ? color.new(#fbbf24, 90) : na, title="Squeeze Alert")

// ── Band Touch readings ───────────────────────────────────────────────────────
touchUpper = close >= upper
touchLower = close <= lower
plotshape(touchUpper, "Upper Touch", shape.circle, location.abovebar, #ef4444, size=size.tiny)
plotshape(touchLower, "Lower Touch", shape.circle, location.belowbar, #22c55e, size=size.tiny)

alertcondition(squeeze,     "BB Squeeze",      "Bollinger Bands in squeeze")
alertcondition(touchUpper,  "Upper Band Touch","Price closed at or above upper Bollinger Band")
alertcondition(touchLower,  "Lower Band Touch","Price closed at or below lower Bollinger Band")

Educational content. Not investment advice.