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

__all__ = [
    "XFisherIndicator",
]


[docs] class XFisherIndicator(Indicator): """Fisher Transform of Williams %R position with an EMA-smoothed signal line.""" lines = ("xfisher", "signal") params = ( ("flength", 7), ("ma_length", 5), ) def __init__(self): """Set the warm-up period, recurrence seeds, and EMA smoothing factor.""" self.addminperiod(self.p.flength + self.p.ma_length + 2) self._value_prev = 0.0 self._fish_prev = 0.0 self._smooth_prev = None self._alpha = 2.0 / (self.p.ma_length + 1.0)
[docs] def next(self): """Compute the smoothed Fisher value and store it with its lagged signal.""" highs = [float(self.data.high[-i]) for i in range(self.p.flength)] lows = [float(self.data.low[-i]) for i in range(self.p.flength)] smax = max(highs) smin = min(lows) spread = smax - smin if spread == 0: spread = 1e-12 price = float(self.data.close[0]) wpr = (price - smin) / spread value = (wpr - 0.5) + 0.67 * self._value_prev value = max(min(value, 0.999), -0.999) ratio = (1.0 + value) / (1.0 - value) ratio = max(ratio, 1e-7) fish = 0.5 * math.log(ratio) + 0.5 * self._fish_prev smooth = ( fish if self._smooth_prev is None else self._smooth_prev + self._alpha * (fish - self._smooth_prev) ) prev_smooth = smooth if len(self) <= 1 else float(self.lines.xfisher[-1]) self.lines.xfisher[0] = smooth self.lines.signal[0] = prev_smooth self._value_prev = value self._fish_prev = fish self._smooth_prev = smooth