"""从 OHLC DataFrame 计算指标,不触碰缠论结构对象。""" from __future__ import annotations from typing import Optional import talib.abstract as ta import pandas as pd from .config import IndicatorConfig from .store import IndicatorStore def _volume_ratio(df: pd.DataFrame, window: int = 10) -> pd.Series: vol = df["volume"].astype(float) ma = vol.rolling(window=window).mean() ratio = vol / ma return ratio.fillna(1.0) class IndicatorEngine: def __init__(self, config: Optional[IndicatorConfig] = None): self.config = config or IndicatorConfig() def compute(self, df: pd.DataFrame, config: Optional[IndicatorConfig] = None) -> IndicatorStore: cfg = config or self.config out = df.copy() fast, slow, period = cfg.macd_fast, cfg.macd_slow, cfg.macd_signal macd = ta.MACD(out, fastperiod=fast, slowperiod=slow, signalperiod=period) out["macd"] = macd["macd"] out["macdsignal"] = macd["macdsignal"] out["macdhist"] = macd["macdhist"] for period_n in cfg.ema_periods: out[f"ema{period_n}"] = ta.EMA(out, timeperiod=period_n) out["rsi"] = ta.RSI(out, timeperiod=cfg.rsi_period) out["atr"] = ta.ATR(out, timeperiod=cfg.atr_period) out["volume_ratio"] = _volume_ratio(out) bb_middle = ta.SMA(out, timeperiod=cfg.bb_middle_sma_period) for bb_period, nbup, nbdn, suffix in cfg.bbands: bb = ta.BBANDS( out, timeperiod=bb_period, nbdevup=nbup, nbdevdn=nbdn, matype=0, ) bbp = (out["close"] - bb["lowerband"]) / (bb["upperband"] - bb["lowerband"]) if suffix == "2633": out["bb2633upper"] = bb["upperband"] out["bb2633lower"] = bb["lowerband"] out["bb2633middle"] = bb["middleband"] out["bbp2633"] = bbp elif suffix == "365": out["bbup365"] = bb["upperband"] out["bblow365"] = bb["lowerband"] out["bbp365"] = bbp elif suffix == "120": out["bbup120"] = bb["upperband"] out["bblow120"] = bb["lowerband"] out["bbp120"] = bbp elif suffix == "30": out["bbup30"] = bb["upperband"] out["bblow30"] = bb["lowerband"] out["bbmiddle30"] = bb_middle out["bbp30"] = bbp elif suffix == "302": out["bbup302"] = bb["upperband"] out["bblow302"] = bb["lowerband"] out["bbp302"] = bbp return IndicatorStore(out)