Source code for backtrader.indicators.contrib.laguerre_adx_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.
"""

import math

from .. import (
    Indicator,
    MinusDirectionalIndicator,
    PlusDirectionalIndicator,
)

__all__ = [
    "LaguerreAdxIndicator",
]


[docs] class LaguerreAdxIndicator(Indicator): """Laguerre-filtered ADX directional components built from +/- DI.""" lines = ("up", "down") params = ( ("adx_period", 14), ("gamma", 0.764), ) def __init__(self): """Initialize DI inputs, laguerre states, and minimum period.""" self.addminperiod(int(self.p.adx_period) + 5) self.plus_di = PlusDirectionalIndicator(self.data, period=int(self.p.adx_period)) self.minus_di = MinusDirectionalIndicator(self.data, period=int(self.p.adx_period)) self._p = {"l0": 0.0, "l1": 0.0, "l2": 0.0, "l3": 0.0} self._m = {"l0": 0.0, "l1": 0.0, "l2": 0.0, "l3": 0.0} def _laguerre_step(self, value, state, previous_output): gamma = float(self.p.gamma) l0a = state["l0"] l1a = state["l1"] l2a = state["l2"] l3a = state["l3"] l0 = (1.0 - gamma) * value + gamma * l0a l1 = -gamma * l0 + l0a + gamma * l1a l2 = -gamma * l1 + l1a + gamma * l2a l3 = -gamma * l2 + l2a + gamma * l3a state["l0"] = l0 state["l1"] = l1 state["l2"] = l2 state["l3"] = l3 cu = 0.0 cd = 0.0 if l0 >= l1: cu = l0 - l1 else: cd = l1 - l0 if l1 >= l2: cu += l1 - l2 else: cd += l2 - l1 if l2 >= l3: cu += l2 - l3 else: cd += l3 - l2 if cu + cd != 0.0: return cu / (cu + cd) return previous_output
[docs] def next(self): """Compute smoothed up/down values from directional indicators.""" prev_up = ( float(self.lines.up[-1]) if len(self) > 0 and math.isfinite(float(self.lines.up[-1])) else 0.0 ) prev_down = ( float(self.lines.down[-1]) if len(self) > 0 and math.isfinite(float(self.lines.down[-1])) else 0.0 ) plus_value = float(self.plus_di[0]) if math.isfinite(float(self.plus_di[0])) else 0.0 minus_value = float(self.minus_di[0]) if math.isfinite(float(self.minus_di[0])) else 0.0 self.lines.up[0] = self._laguerre_step(plus_value, self._p, prev_up) self.lines.down[0] = self._laguerre_step(minus_value, self._m, prev_down)