212f6fedad
- data/service.py: 数据拉取服务,从 TimescaleDB 读取 K 线/Ticker 等行情数据 - indicators/momentum.py: 动量类指标(RSI/MACD/Stochastic 等) - indicators/trend.py: 趋势类指标(EMA/SMA/ADX/SuperTrend 等) - indicators/volatility.py: 波动率指标(Bollinger/ATR/Keltner 等) - indicators/volume.py: 成交量指标(OBV/VWAP/MFI 等)
76 lines
1.8 KiB
Python
76 lines
1.8 KiB
Python
"""
|
|
成交量指标 — OBV、VWAP
|
|
|
|
所有函数返回与输入等长的 list[float],不足周期位置填 0.0。
|
|
"""
|
|
|
|
|
|
def obv(close: list[float], volume: list[float]) -> list[float]:
|
|
"""能量潮 (On-Balance Volume, OBV)
|
|
|
|
从 0 开始累加:
|
|
- 收盘价 > 前收盘价:OBV += 成交量
|
|
- 收盘价 < 前收盘价:OBV -= 成交量
|
|
- 收盘价 == 前收盘价:OBV 不变
|
|
|
|
Args:
|
|
close: 收盘价序列
|
|
volume: 成交量序列
|
|
|
|
Returns:
|
|
与输入等长的 OBV 序列
|
|
"""
|
|
n = len(close)
|
|
result = [0.0] * n
|
|
if n == 0:
|
|
return result
|
|
|
|
result[0] = volume[0]
|
|
for i in range(1, n):
|
|
if close[i] > close[i - 1]:
|
|
result[i] = result[i - 1] + volume[i]
|
|
elif close[i] < close[i - 1]:
|
|
result[i] = result[i - 1] - volume[i]
|
|
else:
|
|
result[i] = result[i - 1]
|
|
|
|
return result
|
|
|
|
|
|
def vwap(
|
|
high: list[float],
|
|
low: list[float],
|
|
close: list[float],
|
|
volume: list[float],
|
|
) -> list[float]:
|
|
"""成交量加权平均价 (VWAP)
|
|
|
|
累积计算:VWAP = Σ(典型价格 × 成交量) / Σ(成交量)
|
|
典型价格 = (high + low + close) / 3
|
|
|
|
Args:
|
|
high: 最高价序列
|
|
low: 最低价序列
|
|
close: 收盘价序列
|
|
volume: 成交量序列
|
|
|
|
Returns:
|
|
与输入等长的 VWAP 序列(从第一个有效 bar 开始累加)
|
|
"""
|
|
n = len(close)
|
|
result = [0.0] * n
|
|
if n == 0:
|
|
return result
|
|
|
|
cum_pv = 0.0 # cumulative price * volume
|
|
cum_vol = 0.0 # cumulative volume
|
|
|
|
for i in range(n):
|
|
typical_price = (high[i] + low[i] + close[i]) / 3.0
|
|
cum_pv += typical_price * volume[i]
|
|
cum_vol += volume[i]
|
|
if cum_vol > 0:
|
|
result[i] = cum_pv / cum_vol
|
|
|
|
return result
|