Source code for backtrader.indicators.contrib.arrows_curves_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__ = [
"ArrowsCurvesIndicator",
]
[docs]
class ArrowsCurvesIndicator(Indicator):
"""Custom Arrows and Curves technical indicator.
Calculates channel boundaries (smax, smin, smax2, smin2) based on highest high and lowest low windows
and returns trade entry signals (buy, sell, buy_stop, sell_stop).
"""
lines = ("sell", "buy", "sell_stop", "buy_stop", "smax", "smin", "smax2", "smin2")
params = (
("ssp", 20),
("channel", 0),
("ch_stop", 30),
("relay", 10),
)
def __init__(self):
"""Initializes trends, state flags, and sets indicator minimum period requirement."""
self.addminperiod(self.p.ssp + self.p.relay + 2)
self._uptrend = False
self._old = False
self._uptrend2 = False
self._old2 = False
[docs]
def next(self):
"""Calculates channel lines and signals for each bar.
Generates buy/sell and buy_stop/sell_stop triggers based on price crossovers
and trend state switches.
"""
if len(self.data) <= self.p.ssp + self.p.relay:
for line in self.lines:
line[0] = 0.0
return
high_window = [
float(self.data.high[-shift])
for shift in range(self.p.relay, self.p.relay + self.p.ssp)
]
low_window = [
float(self.data.low[-shift]) for shift in range(self.p.relay, self.p.relay + self.p.ssp)
]
close0 = float(self.data.close[0])
high_val = max(high_window)
low_val = min(low_window)
smax = high_val - (low_val - high_val) * self.p.channel / 100.0
smin = low_val + (high_val - low_val) * self.p.channel / 100.0
smax2 = high_val - (high_val - low_val) * (self.p.channel + self.p.ch_stop) / 100.0
smin2 = low_val + (high_val - low_val) * (self.p.channel + self.p.ch_stop) / 100.0
sell_signal = 0.0
buy_signal = 0.0
sell_stop = 0.0
buy_stop = 0.0
uptrend = self._uptrend
uptrend2 = self._uptrend2
old = self._old
old2 = self._old2
if close0 < smin and close0 < smax and uptrend2 is True:
uptrend = False
if close0 > smax and close0 > smin and uptrend2 is False:
uptrend = True
if (close0 > smax2 or close0 > smin2) and uptrend is False:
uptrend2 = False
if (close0 < smin2 or close0 < smax2) and uptrend is True:
uptrend2 = True
if close0 < smin and close0 < smax and uptrend2 is False:
sell_signal = low_val
uptrend2 = True
if close0 > smax and close0 > smin and uptrend2 is True:
buy_signal = high_val
uptrend2 = False
if uptrend != old and uptrend is False:
sell_signal = low_val
if uptrend != old and uptrend is True:
buy_signal = high_val
if uptrend2 != old2 and uptrend2 is True:
buy_stop = smax2
if uptrend2 != old2 and uptrend2 is False:
sell_stop = smin2
self.lines.sell[0] = sell_signal
self.lines.buy[0] = buy_signal
self.lines.sell_stop[0] = sell_stop
self.lines.buy_stop[0] = buy_stop
self.lines.smax[0] = smax
self.lines.smin[0] = smin
self.lines.smax2[0] = smax2
self.lines.smin2[0] = smin2
self._old = uptrend
self._old2 = uptrend2
self._uptrend = uptrend
self._uptrend2 = uptrend2