Source code for backtrader.indicators.contrib.laguerre_plus_di_proxy

#!/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 Indicator

__all__ = [
    "LaguerrePlusDiProxy",
]


[docs] class LaguerrePlusDiProxy(Indicator): """Laguerre-style +DI proxy normalized to the 0..1 range. Approximates the directional-movement balance used by the original EA by computing positive/negative directional movement and true range over the lookback period and emitting the normalized +DI share. """ lines = ("value",) params = (("period", 14),) def __init__(self): """Set the minimum period required before emitting values.""" self.addminperiod(self.p.period + 3)
[docs] def next(self): """Compute the normalized +DI ratio for the current bar.""" pdm_vals = [] mdm_vals = [] tr_vals = [] for idx in range(self.p.period): high0 = float(self.data.high[-idx]) high1 = float(self.data.high[-idx - 1]) low0 = float(self.data.low[-idx]) low1 = float(self.data.low[-idx - 1]) close1 = float(self.data.close[-idx - 1]) up_move = high0 - high1 down_move = low1 - low0 pdm = up_move if up_move > down_move and up_move > 0 else 0.0 mdm = down_move if down_move > up_move and down_move > 0 else 0.0 tr = max(high0 - low0, abs(high0 - close1), abs(low0 - close1)) pdm_vals.append(pdm) mdm_vals.append(mdm) tr_vals.append(tr) tr_sum = sum(tr_vals) if tr_sum <= 1e-12: self.lines.value[0] = 0.5 return pdi = 100.0 * sum(pdm_vals) / tr_sum mdi = 100.0 * sum(mdm_vals) / tr_sum denom = pdi + mdi ratio = 0.5 if denom <= 1e-12 else pdi / denom self.lines.value[0] = max(0.0, min(1.0, ratio))