Source code for backtrader.indicators.contrib.three_candles_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__ = [
"ThreeCandlesIndicator",
]
[docs]
class ThreeCandlesIndicator(Indicator):
"""Indicator producing three-candle reversal signal labels."""
lines = ("signal",)
params = (
("max_bar1", 300),
("volume_type", "tick"),
)
def __init__(self):
"""Require enough history before the indicator can emit stable signals."""
self.addminperiod(5)
[docs]
def next(self):
"""Evaluate bullish/bearish setups and emit normalized signal codes."""
self.lines.signal[0] = 2.0
chk_vol = True
range_points = float(self.data.high[-3] - self.data.low[-3])
point = float(getattr(self.data, "_point_value", 0.01) or 0.01)
if point > 0 and range_points / point > float(self.p.max_bar1):
chk_vol = False
bullish_setup = (
float(self.data.open[-3]) < float(self.data.close[-3])
and float(self.data.open[-2]) < float(self.data.close[-2])
and float(self.data.close[-2]) < float(self.data.high[-3])
and float(self.data.open[-1]) > float(self.data.close[-1])
and float(self.data.close[-1]) < float(self.data.open[-2])
)
bearish_setup = (
float(self.data.open[-3]) > float(self.data.close[-3])
and float(self.data.open[-2]) > float(self.data.close[-2])
and float(self.data.close[-2]) > float(self.data.low[-3])
and float(self.data.open[-1]) < float(self.data.close[-1])
and float(self.data.close[-1]) > float(self.data.open[-2])
)
vol_series = self.data.volume
def volume_filter_ok():
if not chk_vol or self.p.volume_type == "none":
return True
v3 = float(vol_series[-3])
v2 = float(vol_series[-2])
v1 = float(vol_series[-1])
return v3 < v2 or v1 > v2 or v1 > v3
if bullish_setup and volume_filter_ok():
self.lines.signal[0] = (
0.0 if float(self.data.close[0]) < float(self.data.open[0]) else 1.0
)
if bearish_setup and volume_filter_ok():
self.lines.signal[0] = (
3.0 if float(self.data.close[0]) < float(self.data.open[0]) else 4.0
)