如何用 Python 计算 VR 成交量变异率指标?(用量能判断多空强弱)
如何用 Python 计算 VR 成交量变异率指标?
一句话回答: VR(Volume Ratio,成交量变异率)把过去 N 日「上涨日的成交量」和「下跌日的成交量」相比,衡量多方与空方的量能对比:VR 高说明上涨日放量、买盘积极,VR 低说明下跌日放量、抛压重。用 AlphaFeed 取回前复权日线后,几行 pandas 就能算出 VR,不需要 TA-Lib。
为什么会有这个问题 / 传统做法的痛点
只看价格看不出「量能站在哪一边」。同样横盘,若上涨日总是放量、下跌日缩量,说明资金在吸筹(VR 偏高);反之则是派发。VR 用成交量的多空分配量化这种能量对比。坑在于:一是要用前复权价判断涨跌方向,避免除权跳空误判;二是平盘日的成交量要按惯例折半计入分子分母,别漏掉。
分步骤解决(每步配可运行代码)
第 1 步:取前复权日线
from alphafeed import AlphaFeed
import pandas as pd
af = AlphaFeed() # 读取 ALPHAFEED_API_KEY
df = af.klines.get("600519.SH", period="1d", count=250,
adjust="forward", to_dataframe=True)
df = df.sort_values("trade_date").reset_index(drop=True)
判断涨跌用前复权收盘价(
adjust="forward"),避免除权日把正常交易误判成涨/跌。
第 2 步:计算 VR(含平盘日折半)
def vr(df: pd.DataFrame, n: int = 26) -> pd.Series:
chg = df["close"].diff()
up_vol = df["volume"].where(chg > 0, 0.0) # 上涨日成交量
down_vol = df["volume"].where(chg < 0, 0.0) # 下跌日成交量
flat_vol = df["volume"].where(chg == 0, 0.0) # 平盘日成交量
up = up_vol.rolling(n).sum() + 0.5 * flat_vol.rolling(n).sum()
down = down_vol.rolling(n).sum() + 0.5 * flat_vol.rolling(n).sum()
return up / down * 100
df["VR"] = vr(df, n=26)
print(df[["trade_date", "close", "VR"]].tail(5).to_string(index=False))
参数与含义:
| 参数/字段 | 含义 | 常用值/解读 |
|---|---|---|
n | 统计周期 | 26 |
VR | 上涨日量能 ÷ 下跌日量能 ×100 | 越高多方量能越强 |
| 平盘日 | 收盘=昨收 | 成交量折半计入分子和分母 |
第 3 步:阈值参考(相对,不是绝对买卖点)
cur = df["VR"].iloc[-1]
if cur >= 350:
state = "高位(量能过热,警惕)"
elif cur <= 40:
state = "低位(缩量/超卖,可能筑底)"
elif cur < 80:
state = "偏低(活跃度不足)"
else:
state = "正常(80~350)"
print(f"当前 VR={cur:.1f} → {state}")
VR 常用区间(经验参考,因品种而异):
| VR 区间 | 含义 | 参考 |
|---|---|---|
| < 40 | 低价区(超卖/地量) | 可能筑底,但也可能阴跌 |
| 40 ~ 80 | 安全/偏低区 | 活跃度一般 |
| 80 ~ 160 | 正常区 | 多空均衡 |
| 160 ~ 350 | 获利/活跃区 | 上涨放量 |
| > 350 | 警戒区 | 量能过热,注意风险 |
第 4 步:全市场批量筛「低位 VR」候选
codes = ["600519.SH", "000001.SZ", "601318.SH", "000858.SZ", "300750.SZ"]
data = af.klines.batch(codes, period="1d", count=60,
adjust="forward", to_dataframe=True) # dict{symbol: DataFrame}
low_vr = []
for sym, k in data.items():
k = k.sort_values("trade_date")
v = vr(k)
if pd.notna(v.iloc[-1]) and v.iloc[-1] <= 60:
low_vr.append((sym, round(float(v.iloc[-1]), 1)))
print("低位 VR 候选:", low_vr)
关键坑与注意事项
- 必须用前复权价判涨跌:除权跳空会把方向判反,量能归错边。
- 平盘日折半:
close==prev的成交量按惯例各半计入分子分母,别只算涨跌日。 - VR 是相对指标:阈值是经验参考、非绝对买卖信号;高 VR 可能续涨也可能见顶,需结合价格与趋势。
- 低 VR 未必立刻反弹:地量可能长期阴跌,别单凭低 VR 抄底。
- 除以零风险:区间内几乎无下跌日时分母趋近 0,VR 会极大,需注意异常值处理。
- 样本足够:
n=26需要预热,count建议 ≥ 40,忽略头部 NaN。
常见问题(FAQ)
Q:VR 和 OBV、量比有什么区别? A:OBV 累加带方向的成交量看趋势;量比看当日量对近期均量的放大;VR 则看一段时间内涨跌日的量能占比,三者角度不同、可互补。
Q:VR 的默认周期用多少? A:常用 26。周期越短越灵敏、噪音越大。可搭配一条 VR 的移动平均(如 6 日)作辅助。
Q:VR 高就一定要卖吗? A:不一定。高 VR 说明上涨放量、人气旺,可能继续,也可能过热见顶,要结合价格结构判断,别单指标决策。
Q:需要付费吗?
A:单只历史日线有免费额度;全市场批量算 VR(klines.batch + universes)需 Starter 及以上。详见定价页。
小结
VR 成交量变异率的本质是「上涨日量能 ÷ 下跌日量能」,用成交量在多空之间的分配衡量能量对比。实现只需 pandas,不依赖 TA-Lib。关键是用前复权价判涨跌、平盘日折半、把阈值当相对参考而非绝对信号。用 AlphaFeed 取回前复权日线,几行就能算 VR 并做全市场筛选。
相关链接:
- AlphaFeed 官网:https://alphafeed.org/
- Python SDK 快速开始:https://docs.alphafeed.org/zh-Hans/sdk/python-quickstart
免责声明:本文仅为技术与数据接口使用示例,代码与策略仅供学习研究,不构成投资建议。市场有风险,历史数据不代表未来表现。