Source code for backtrader.indicators.accdecoscillator
#!/usr/bin/env python
"""Acceleration/Deceleration Oscillator Module - AC indicator.
This module provides the Acceleration/Deceleration Oscillator (AC)
developed by Bill Williams to measure the acceleration of driving force.
Classes:
AccelerationDecelerationOscillator: AC indicator (alias: AccDeOsc).
Example:
class MyStrategy(bt.Strategy):
def __init__(self):
self.ac = bt.indicators.AccDeOsc(self.data)
def next(self):
if self.ac.accde[0] > 0 and self.ac.accde[-1] < 0:
self.buy()
"""
import math
from . import Indicator
from .awesomeoscillator import AwesomeOscillator
from .sma import SMA
__all__ = ["AccelerationDecelerationOscillator", "AccDeOsc"]
[docs]
class AccelerationDecelerationOscillator(Indicator):
"""
Acceleration/Deceleration Technical Indicator (AC) measures acceleration
and deceleration of the current driving force. This indicator will change
the direction before any changes in the driving force, which, it its turn, will
change its direction before the price.
Formula:
- AcdDecOsc = AwesomeOscillator - SMA(AwesomeOscillator, period)
See:
- https://www.metatrader5.com/en/terminal/help/indicators/bw_indicators/ao
- https://www.ifcmarkets.com/en/ntx-indicators/ntx-indicators-accelerator-decelerator-oscillator
"""
alias = ("AccDeOsc",)
lines = ("accde",)
params = (
("period", 5),
("movav", SMA),
)
plotlines = {"accde": {"_method": "bar", "alpha": 0.50, "width": 1.0}}
def __init__(self):
"""Initialize the AC indicator.
Creates an Awesome Oscillator sub-indicator for calculation.
"""
super().__init__()
self.ao = AwesomeOscillator(self.data)
[docs]
def next(self):
"""Calculate AC for the current bar.
Formula: AC = AO - SMA(AO, period)
"""
ao_val = self.ao[0]
period = self.p.period
# Calculate SMA of AO
ao_sum = ao_val
for i in range(1, period):
ao_sum += self.ao[-i]
ao_sma = ao_sum / period
self.lines.accde[0] = ao_val - ao_sma
[docs]
def once(self, start, end):
"""Calculate AC in runonce mode.
Calculates AC = AO - SMA(AO, period) for all bars.
"""
ao_array = self.ao.lines[0].array
larray = self.lines.accde.array
period = self.p.period
while len(larray) < end:
larray.append(float("nan"))
for i in range(start, min(end, len(ao_array))):
ao_val = ao_array[i] if i < len(ao_array) else 0.0
if isinstance(ao_val, float) and math.isnan(ao_val):
larray[i] = float("nan")
continue
if i < period - 1:
larray[i] = float("nan")
else:
ao_sum = 0.0
for j in range(period):
idx = i - j
if idx >= 0 and idx < len(ao_array):
ao_sum += ao_array[idx]
ao_sma = ao_sum / period
larray[i] = ao_val - ao_sma
AccDeOsc = AccelerationDecelerationOscillator