Source code for backtrader.indicators.contrib.bb_squeeze_indicator

#!/usr/bin/env python
"""Functional-test indicators migrated to contrib.

Generated from a single functional strategy module to preserve file-local
helper functions and constants without cross-test name collisions.
"""

from .. import (
    ATR,
    SMA,
    BollingerBands,
    Indicator,
    Momentum,
)

__all__ = [
    "BBSqueezeIndicator",
]


[docs] class BBSqueezeIndicator(Indicator): """ Bollinger Band Squeeze: measures BB width relative to Keltner Channel. Histogram = close - midline of (BB + KC) / 2, colored by whether BB is inside KC (squeeze on) or outside (squeeze off). Simplified: histogram = momentum (close - SMA), signal direction by BB bandwidth vs KC bandwidth. """ lines = ( "squeeze", "momentum", ) params = ( ("bb_period", 20), ("bb_dev", 2.0), ("kc_period", 20), ("kc_mult", 1.5), ("mom_period", 12), ) def __init__(self): """Instantiate BB, ATR, SMA, and momentum indicators used by the squeeze.""" self.bb = BollingerBands(self.data.close, period=self.p.bb_period, devfactor=self.p.bb_dev) self.atr = ATR(self.data, period=self.p.kc_period) self.sma = SMA(self.data.close, period=self.p.kc_period) self.mom = Momentum(self.data.close, period=self.p.mom_period)
[docs] def next(self): """Calculate squeeze state and momentum for every new bar.""" bb_upper = float(self.bb.top[0]) bb_lower = float(self.bb.bot[0]) bb_width = bb_upper - bb_lower kc_upper = float(self.sma[0]) + self.p.kc_mult * float(self.atr[0]) kc_lower = float(self.sma[0]) - self.p.kc_mult * float(self.atr[0]) kc_width = kc_upper - kc_lower self.lines.squeeze[0] = 1.0 if bb_width < kc_width else -1.0 self.lines.momentum[0] = float(self.mom[0])