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

__all__ = [
    "DerivativeIndicator",
]


APPLIED_PRICE_MAP = {
    "PRICE_CLOSE": 0,
    "PRICE_OPEN": 1,
    "PRICE_HIGH": 2,
    "PRICE_LOW": 3,
    "PRICE_MEDIAN": 4,
    "PRICE_TYPICAL": 5,
    "PRICE_WEIGHTED": 6,
    "PRICE_OPEN_CLOSE": 8,
    "PRICE_OHLC_AVERAGE": 9,
    "PRICE_DEMARK": 10,
    "PRICE_AVERAGE_DEMARK": 11,
}


[docs] class DerivativeIndicator(Indicator): """Derivative indicator derived from a selected applied price. The computed `value` line is a momentum-like slope: ``100 * (price[0] - price[-i_slowing]) / i_slowing``. """ lines = ("value",) params = ( ("i_slowing", 34), ("applied_price", "PRICE_WEIGHTED"), ) def __init__(self): """Require at least ``i_slowing + 1`` bars before emitting values.""" self.addminperiod(int(self.p.i_slowing) + 1) def _mode_value(self, value, default_value): if isinstance(value, str): return APPLIED_PRICE_MAP.get(value, default_value) return int(value) def _price(self, ago=0): mode = self._mode_value(self.p.applied_price, 0) open_ = float(self.data.open[ago]) high = float(self.data.high[ago]) low = float(self.data.low[ago]) close = float(self.data.close[ago]) if mode == 0: return close if mode == 1: return open_ if mode == 2: return high if mode == 3: return low if mode == 4: return (high + low) / 2.0 if mode == 5: return (close + high + low) / 3.0 if mode == 6: return (2.0 * close + high + low) / 4.0 if mode == 8: return (open_ + close) / 2.0 if mode == 9: return (open_ + close + high + low) / 4.0 if mode == 10: if close > open_: return high if close < open_: return low return close if mode == 11: if close > open_: return (high + close) / 2.0 if close < open_: return (low + close) / 2.0 return close return close
[docs] def next(self): """Update the derivative value for the current bar.""" lag = int(self.p.i_slowing) current = self._price(0) past = self._price(-lag) self.lines.value[0] = 100.0 * (current - past) / float(lag)