Academy/Strategy Code Breakdown/Bollinger Squeeze — Code Walkthrough
Strategy Code BreakdownLesson 4

Bollinger Squeeze — Code Walkthrough

Understand how Bollinger Bands are constructed from standard deviation, what "bandwidth" means, and how the squeeze breakout signal is generated.

13 minute read
4 key takeaways

Bollinger Squeeze — Code Walkthrough

Bollinger Bands, developed by John Bollinger in the 1980s, are dynamic support/resistance levels that adapt to market volatility. This strategy exploits the "squeeze" — when bands contract, a big move is coming. The code detects when the expansion begins and price breaks out.

Step 1 — Configuration

typescript
export interface BollingerConfig {
  period: number;       // SMA/StdDev lookback window (default 20)
  stdDev: number;       // Band width multiplier (default 2.0)
  stopLossPct: number;  // 0.06 = stop at -6%
  takeProfitPct: number;// 0.18 = target +18%
}

export const defaultConfig: BollingerConfig = {
  period: 20,
  stdDev: 2.0,
  stopLossPct: 0.06,
  takeProfitPct: 0.18,
};

The 2.0 standard deviation multiplier means the bands contain ~95% of price action under normal market conditions (by the 68-95-99.7 rule). When price hits a band, it's statistically extreme.

Step 2 — calculateBollingerBands: Math Under the Hood

typescript
export function calculateBollingerBands(closes, config) {
  const { period, stdDev } = config;

  return closes.reduce((acc, _, i) => {
    if (i < period - 1) {
      // Push NaN placeholders during warmup
      acc.upper.push(NaN); acc.middle.push(NaN);
      acc.lower.push(NaN); acc.bandwidth.push(NaN);
      return acc;
    }

    const slice = closes.slice(i - period + 1, i + 1); // rolling window

    // Mean of the window (= middle band = 20-period SMA)
    const mean = slice.reduce((a, b) => a + b, 0) / period;

    // Population variance: average squared deviation from mean
    const variance = slice.reduce((sum, v) => sum + (v - mean) ** 2, 0) / period;
    const std = Math.sqrt(variance);

    const upper = mean + stdDev * std;   // upper band
    const lower = mean - stdDev * std;   // lower band

    // Bandwidth = (upper - lower) / middle
    // High bandwidth = bands wide = high volatility
    // Low bandwidth  = bands narrow = low volatility (squeeze!)
    acc.bandwidth.push((upper - lower) / mean);

    return acc;
  }, { upper: [], middle: [], lower: [], bandwidth: [] });
}

Population vs Sample Standard Deviation

The code divides by N (population), not N-1 (sample). Technically sample std (N-1) is the unbiased estimator, but for indicator purposes the difference is negligible and population std is the convention in most charting software including TradingView.

Step 3 — generateSignals: The Squeeze Breakout Logic

typescript
export function generateSignals(closes, config) {
  const bands = calculateBollingerBands(closes, config);

  return closes.map((price, i) => {
    const { upper, middle, lower } = { upper: bands.upper[i], middle: bands.middle[i], lower: bands.lower[i] };
    if (isNaN(upper)) return { index: i, signal: 0, upper, middle, lower };

    const prevBw = bands.bandwidth[i - 1] ?? NaN;

    // "Squeeze" = bandwidth is expanding (volatility returning after compression)
    const squeeze = !isNaN(prevBw) && bands.bandwidth[i] > prevBw;

    // Breakout up = bands expanding AND price closes above upper band
    const breakoutUp = squeeze && price > upper;

    // Exit = price falls below the middle band (mean)
    const exitSignal = price < middle;

    const signal = breakoutUp ? 1 : exitSignal ? -1 : 0;
    return { index: i, signal, upper, middle, lower };
  });
}
  • squeeze: True if bandwidth[i] > bandwidth[i-1]. Volatility is expanding — the squeeze is releasing.
  • breakoutUp: True if we're in a squeeze expansion AND price broke above the upper band. Strong bullish signal.
  • exitSignal: True if price drops below the middle band (the 20-SMA). Mean is reclaiming price — exit long.

One-Directional Strategy

This code only generates bullish breakout signals (price > upper band). A full implementation would also check breakouts below the lower band (price < lower) for short entries, making it symmetric.

Key Takeaways
  • Bollinger Bands = 20-period SMA ± (2 × rolling standard deviation)
  • Bandwidth measures how wide/tight the bands are relative to the middle
  • A "squeeze" is when volatility contracts; a breakout follows as volatility expands
  • Signal fires when bandwidth expands AND price closes above the upper band

Open Bollinger Strategy in Lab

Clone the Bollinger Squeeze strategy and run a live backtest