Source code for backtrader.indicators.contrib.xmacd_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 (
EMA,
SMA,
Indicator,
)
__all__ = [
"XMACDIndicator",
]
[docs]
class XMACDIndicator(Indicator):
"""Configurable MACD indicator with selectable MA methods and price.
Computes the MACD line as the difference of a fast and slow moving average
of a chosen applied price, then a signal line by smoothing the MACD. The
moving-average type, signal-smoothing type, periods and applied price are all
configurable via parameters.
"""
lines = (
"macd",
"signal",
)
params = (
("ma_method", "ema"),
("signal_method", "sma"),
("fast_period", 12),
("slow_period", 26),
("signal_period", 9),
("applied_price", "close"),
)
def __init__(self):
"""Build the fast/slow MAs, MACD and signal lines and set min period."""
ma_cls = EMA if str(self.p.ma_method).lower() == "ema" else SMA
signal_cls = EMA if str(self.p.signal_method).lower() == "ema" else SMA
price = self._price_line()
fast = ma_cls(price, period=self.p.fast_period)
slow = ma_cls(price, period=self.p.slow_period)
self.lines.macd = fast - slow
self.lines.signal = signal_cls(self.lines.macd, period=self.p.signal_period)
self.addminperiod(max(self.p.fast_period, self.p.slow_period) + self.p.signal_period + 5)
def _price_line(self):
mode = str(self.p.applied_price).lower()
if mode == "open":
return self.data.open
if mode == "high":
return self.data.high
if mode == "low":
return self.data.low
if mode == "median":
return (self.data.high + self.data.low) / 2.0
if mode == "typical":
return (self.data.high + self.data.low + self.data.close) / 3.0
if mode == "weighted":
return (self.data.high + self.data.low + self.data.close + self.data.close) / 4.0
if mode == "simpl":
return (self.data.open + self.data.close) / 2.0
if mode == "quarter":
return (self.data.high + self.data.low + self.data.open + self.data.close) / 4.0
return self.data.close