Source code for backtrader.indicators.contrib.volume_weighted_ma_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__ = [
    "VolumeWeightedMAIndicator",
]


def _applied_price(data, price_type, ago=0):
    o = float(data.open[-ago])
    h = float(data.high[-ago])
    low_price = float(data.low[-ago])
    c = float(data.close[-ago])
    if price_type == 0:
        return c
    if price_type == 1:
        return o
    if price_type == 2:
        return h
    if price_type == 3:
        return low_price
    if price_type == 4:
        return (h + low_price) / 2.0
    if price_type == 5:
        return (h + low_price + c) / 3.0
    if price_type == 6:
        return (h + low_price + c + c) / 4.0
    return c


[docs] class VolumeWeightedMAIndicator(Indicator): """Volume-weighted moving average of an applied price. Averages the applied price (selected by ``ipc``) over ``length`` bars, weighting each bar by its tick volume (or open interest when ``use_tick_volume`` is False); falls back to the plain applied price when the total weight is zero. """ lines = ("vwma",) params = ( ("length", 12), ("ipc", 0), ("use_tick_volume", True), ) def __init__(self): """Set the minimum period to cover the averaging window.""" self.addminperiod(int(self.p.length) + 2)
[docs] def next(self): """Compute the volume-weighted average price for the current bar.""" length = int(self.p.length) weights = [] total = 0.0 for i in range(length): vol = ( float(self.data.volume[-i]) if self.p.use_tick_volume else float(self.data.openinterest[-i]) ) if vol < 0: vol = 0.0 weights.append(vol) total += vol if total == 0.0: self.lines.vwma[0] = _applied_price(self.data, int(self.p.ipc), 0) return value = 0.0 for i in range(length): value += _applied_price(self.data, int(self.p.ipc), i) * (weights[i] / total) self.lines.vwma[0] = value