Source code for backtrader.indicators.contrib.loco_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__ = [
"LocoIndicator",
]
def _applied_price(data, mode, ago=0):
mode = str(mode).lower()
o = float(data.open[ago])
h = float(data.high[ago])
low_price = float(data.low[ago])
c = float(data.close[ago])
if mode in ("price_open", "open", "price_open_"):
return o
if mode in ("price_high", "high", "price_high_"):
return h
if mode in ("price_low", "low", "price_low_"):
return low_price
if mode in ("price_median", "median", "price_median_"):
return (h + low_price) / 2.0
if mode in ("price_typical", "typical", "price_typical_"):
return (h + low_price + c) / 3.0
if mode in ("price_weighted", "weighted", "price_weighted_"):
return (h + low_price + 2.0 * c) / 4.0
if mode in ("price_simpl", "simpl", "simple", "price_simpl_"):
return (o + c) / 2.0
if mode in ("price_quarter", "quarter", "price_quarter_"):
return (h + low_price + o + c) / 4.0
return c
[docs]
class LocoIndicator(Indicator):
"""Loco follow-through line with a binary bullish/bearish color flag.
Tracks the applied price and produces a ``loco`` line plus a ``color`` flag
(0 = bullish, 1 = bearish) that flips when price reverses its run of higher
or lower readings.
"""
lines = ("loco", "color")
params = (
("length", 1),
("ipc", "price_close_"),
("price_shift_points", 0.0),
)
def __init__(self):
"""Reserve the warm-up window and initialise carry-forward state."""
self.addminperiod(max(int(self.p.length), 1) + 2)
self._initialized = False
self._prev = None
[docs]
def next(self):
"""Update the Loco line and color flag for the current bar."""
series0 = _applied_price(self.data, self.p.ipc, 0)
if not self._initialized:
result = series0
color = 0
self._prev = result
self._initialized = True
else:
prev = float(self._prev)
ago = min(int(self.p.length), len(self.data) - 1)
series1 = _applied_price(self.data, self.p.ipc, -ago)
if series1 > prev and series0 > prev:
result = max(prev, series0 * 0.999)
color = 0
elif series1 < prev and series0 < prev:
result = min(prev, series0 * 1.001)
color = 1
else:
if series0 > prev:
result = series0 * 0.999
color = 0
else:
result = series0 * 1.001
color = 1
self._prev = result
self.lines.loco[0] = result + float(self.p.price_shift_points)
self.lines.color[0] = color