Source code for backtrader.indicators.contrib.xcci_histogram_vol_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__ = [
"XCCIHistogramVolIndicator",
]
[docs]
class XCCIHistogramVolIndicator(Indicator):
"""Compute volume-scaled XCCI histogram levels and color state."""
lines = ("color_state", "value", "max_level", "up_level", "dn_level", "min_level")
params = (
("cci_period", 14),
("high_level2", 100),
("high_level1", 80),
("low_level1", -80),
("low_level2", -100),
("ma_length", 12),
)
def __init__(self):
"""Initialize rolling CCI and volume histories."""
self._scaled_history = []
self._volume_history = []
self.addminperiod(max(self.p.cci_period, self.p.ma_length) + 3)
[docs]
def next(self):
"""Update scaled CCI, levels, and derived color state."""
vol = float(self.data.volume[0]) if len(self.data.volume) else 0.0
typical_prices = []
for idx in range(self.p.cci_period):
typical_prices.append(
(
float(self.data.high[-idx])
+ float(self.data.low[-idx])
+ float(self.data.close[-idx])
)
/ 3.0
)
tp_now = typical_prices[0]
tp_sma = sum(typical_prices) / float(len(typical_prices))
mean_dev = sum(abs(tp - tp_sma) for tp in typical_prices) / float(len(typical_prices))
if mean_dev <= 1e-12:
cci_value = 0.0
else:
cci_value = (tp_now - tp_sma) / (0.015 * mean_dev)
raw = cci_value * vol
self._scaled_history.append(raw)
self._volume_history.append(vol)
if len(self._scaled_history) > self.p.ma_length:
self._scaled_history.pop(0)
if len(self._volume_history) > self.p.ma_length:
self._volume_history.pop(0)
scaled = sum(self._scaled_history) / float(len(self._scaled_history))
avg_vol = (
sum(self._volume_history) / float(len(self._volume_history))
if self._volume_history
else max(vol, 1.0)
)
max_level = self.p.high_level2 * avg_vol
up_level = self.p.high_level1 * avg_vol
dn_level = self.p.low_level1 * avg_vol
min_level = self.p.low_level2 * avg_vol
clr = 2.0
if scaled > max_level:
clr = 0.0
elif scaled > up_level:
clr = 1.0
elif scaled < min_level:
clr = 4.0
elif scaled < dn_level:
clr = 3.0
self.lines.value[0] = scaled
self.lines.max_level[0] = max_level
self.lines.up_level[0] = up_level
self.lines.dn_level[0] = dn_level
self.lines.min_level[0] = min_level
self.lines.color_state[0] = clr