Source code for backtrader.indicators.contrib.altr_trend_signal_v22
#!/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 (
AverageDirectionalMovementIndex,
Indicator,
)
__all__ = [
"AltrTrendSignalV22",
]
[docs]
class AltrTrendSignalV22(Indicator):
"""Adaptive trend breakout indicator used by the strategy."""
lines = ("sell", "buy")
params = (
("k", 30),
("kstop", 0.5),
("kperiod", 150),
("per_adx", 14),
)
def __init__(self):
"""Create ADX trend indicator and initialize state."""
self.adx = AverageDirectionalMovementIndex(self.data, period=max(int(self.p.per_adx), 1))
self.addminperiod(max(int(self.p.per_adx), 1) + 2)
self._trend = 0
[docs]
def next(self):
"""Compute breakout level and emit short/long trigger values."""
self.lines.buy[0] = 0.0
self.lines.sell[0] = 0.0
adx_prev = float(self.adx[-1]) if len(self) > 1 else float(self.adx[0])
if math.isnan(adx_prev) or adx_prev <= 0:
return
ssp = max(int(math.ceil(float(self.p.kperiod) / adx_prev)), 1)
lookback = min(ssp, len(self.data))
if lookback <= 0:
return
highs = []
lows = []
avg_range = 0.0
for idx in range(lookback):
high = float(self.data.high[-idx])
low = float(self.data.low[-idx])
highs.append(high)
lows.append(low)
avg_range += abs(high - low)
trading_range = avg_range / (ssp + 1.0)
ss_max = max(highs)
ss_min = min(lows)
threshold = (ss_max - ss_min) * float(self.p.k) / 100.0
smin = ss_min + threshold
smax = ss_max - threshold
previous_trend = self._trend
trend = previous_trend
close = float(self.data.close[0])
if close < smin:
trend = -1
if close > smax:
trend = 1
if previous_trend == 0:
previous_trend = trend
if trend != previous_trend and close > smax:
self.lines.buy[0] = float(self.data.low[0]) - trading_range * float(self.p.kstop)
if trend != previous_trend and close < smin:
self.lines.sell[0] = float(self.data.high[0]) + trading_range * float(self.p.kstop)
self._trend = trend if trend != 0 else previous_trend