Source code for backtrader.indicators.contrib.i_stoch_komposter_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,
    Indicator,
)

__all__ = [
    "IStochKomposterIndicator",
]


[docs] class IStochKomposterIndicator(Indicator): """Stochastic-and-ATR composite that prints offset buy/sell markers. Emits a buy line below the bar low (and a sell line above the bar high), offset by 3/8 of ATR, whenever the slowed %K stochastic crosses up through the lower level or down through the upper level respectively. """ lines = ("sell", "buy", "sto", "atr") params = ( ("atr_period", 14), ("k_period", 5), ("d_period", 3), ("slowing", 3), ("up_level", 70), ("dn_level", 30), ) def __init__(self): """Build the ATR sub-indicator and set the warm-up minimum period.""" self._atr = ATR(self.data, period=int(self.p.atr_period)) self.addminperiod( max( int(self.p.atr_period), int(self.p.k_period) + int(self.p.d_period) + int(self.p.slowing) + 1, ) + 2 ) def _raw_k(self, ago): period = int(self.p.k_period) highs = [float(self.data.high[-(ago + i)]) for i in range(period)] lows = [float(self.data.low[-(ago + i)]) for i in range(period)] hh = max(highs) ll = min(lows) cp = float(self.data.close[-ago]) if hh == ll: return 50.0 return 100.0 * (cp - ll) / (hh - ll) def _main_stochastic(self): slowing = int(self.p.slowing) vals = [self._raw_k(i) for i in range(slowing)] return sum(vals) / len(vals)
[docs] def next(self): """Compute the slowed stochastic and emit ATR-offset cross markers.""" self.lines.sell[0] = float("nan") self.lines.buy[0] = float("nan") sto_now = self._main_stochastic() self.lines.sto[0] = sto_now self.lines.atr[0] = float(self._atr[0]) if len(self) < 2: return sto_prev = float(self.lines.sto[-1]) atr_now = float(self._atr[0]) if sto_now > float(self.p.dn_level) and sto_prev <= float(self.p.dn_level): self.lines.buy[0] = float(self.data.low[0]) - atr_now * 3.0 / 8.0 if sto_now < float(self.p.up_level) and sto_prev >= float(self.p.up_level): self.lines.sell[0] = float(self.data.high[0]) + atr_now * 3.0 / 8.0