Skip to content
Open RaamTrade

BollingerBandwidth — Bollinger Bandwidth

The width of the Bollinger bands as a fraction of the middle band — the squeeze detector. Bandwidth at a multi-month low is the compression that precedes expansion; the direction of the break is someone else’s job.

Signature

BollingerBandwidth(period, multiplier, on=<source>)
Argument Type Required Notes
period int Param or literal Yes Bollinger window. Default 20, bounds 2–400.
multiplier float Param or literal Yes Band width in standard deviations. Default 2.0, bounds 0.1–10.0.
on= symbol, OHLCV field, or indicator No Source. Defaults to the trade symbol’s close.

Formula

$$ \text{BW} = \frac{\text{upper} - \text{lower}}{\text{mid}} = \frac{2m,\sigma(C,n)}{\text{SMA}(C,n)} $$

Warmup

period bars; 0 until then.

Reading the value

bw.value
bw < 0.04

Being single-value, it can be chained: low_bw = DonchianLow(120, on=bw) gives the rolling bandwidth low the squeeze rule wants.

Example

class SqueezeWatch(Strategy):
"""Enter the expansion after a bandwidth squeeze."""
trade = Symbol()
sizing = FixedCapital()
def execute(self):
bw = BollingerBandwidth(20, 2.0, on=self.trade)
low_bw = DonchianLow(120, on=bw)
sma = SMA(20, on=self.trade)
if bw.value <= low_bw.value * 1.05 and self.trade.close > sma.value and self.trade.is_flat:
self.buy(self.trade, reason=f"Squeeze {bw.value:.3f}")
if self.trade.close < sma.value and self.trade.is_long:
self.sell(self.trade, self.trade.position, reason="Below mid")

Notes

  • John Bollinger, Bollinger on Bollinger Bands (2001).
  • Computed inline from the same window as the seeded BollingerBands (chaining onto a multi-value indicator is not possible), with the platform’s population standard deviation.
  • Proven by an assert-via-trade run on SPY daily (matched a strategy-side reference to 1e-4 on every bar; zero alarm trades).