AlphaFeed Blog

如何用 Python 计算涡旋指标(Vortex Indicator, VI+/VI−)判断趋势方向?不用 TA-Lib

分析与指标 · 代码验证于 2026-10-12

如何用 Python 计算涡旋指标(Vortex Indicator)判断趋势方向?

一句话回答: 涡旋指标(Vortex Indicator)用两条线刻画多空力量:VI+(上行涡旋) 与 VI−(下行涡旋),分别由「今日高 − 昨日低」和「今日低 − 昨日高」的 N 日累加除以 N 日真实波幅(TR)之和得到。VI+ 上穿 VI− 视为趋势转多、下穿转空。用 AlphaFeed 取前复权日线的 OHLC,十几行就能实现,不需要 TA-Lib。

为什么会有这个问题 / 传统做法的痛点

判断「趋势是不是启动了、往哪个方向」时,均线滞后、MACD 在震荡市反复。涡旋指标由 Botes 和 Siepman 提出,灵感来自水流的涡旋运动:用相邻两日的高低价”反向差”来量化上行力量与下行力量,再用真实波幅归一化,于是 VI+ 和 VI− 的交叉能较早提示趋势转向。痛点是 TA-Lib 没有现成函数,且 VM+/VM− 用的是「今日高减昨日低」「今日低减昨日高」这种交叉项,容易写反。

分步骤解决(每步配可运行代码)

第 1 步:取前复权日线(要 OHLC)

from alphafeed import AlphaFeed
import numpy as np, pandas as pd

af = AlphaFeed(api_key="your-api-key")  # 或 export ALPHAFEED_API_KEY 后 AlphaFeed()

df = af.klines.get("600519.SH", period="1d", count=300,
                   adjust="forward", to_dataframe=True)
df = df.sort_values("trade_date").reset_index(drop=True)

第 2 步:实现涡旋指标 VI+ / VI−

def vortex(df, n=14):
    h, l, c = df["high"], df["low"], df["close"]
    pc, ph, pl = c.shift(1), h.shift(1), l.shift(1)      # 昨收/昨高/昨低
    tr  = pd.concat([h - l, (h - pc).abs(), (l - pc).abs()], axis=1).max(axis=1)  # 真实波幅
    vmp = (h - pl).abs()      # 上行涡旋位移:今日高 - 昨日低
    vmn = (l - ph).abs()      # 下行涡旋位移:今日低 - 昨日高
    str_ = tr.rolling(n).sum()
    vip = vmp.rolling(n).sum() / str_      # VI+
    vin = vmn.rolling(n).sum() / str_      # VI-
    return vip, vin

df["vi_plus"], df["vi_minus"] = vortex(df, 14)
print(df[["trade_date", "vi_plus", "vi_minus"]].tail())

实测(tools/verify_new_2026-10-12.py,SDK 0.1.4):贵州茅台近 300 日 VI+ 尾值 ≈ 0.961、VI− 尾值 ≈ 1.008(VI− 略高于 VI+,当下偏空),区间内 VI+ 上穿 VI− 共 18 次。

第 3 步:检测金叉/死叉信号

golden = (df["vi_plus"].shift(1) <= df["vi_minus"].shift(1)) & (df["vi_plus"] > df["vi_minus"])
dead   = (df["vi_plus"].shift(1) >= df["vi_minus"].shift(1)) & (df["vi_plus"] < df["vi_minus"])
print("最近一次 VI+ 上穿 VI−:", df.loc[golden, "trade_date"].tail(1).tolist())

VI+ 上穿 VI− 偏多、下穿偏空;两线同时走高/走低也反映趋势强弱。

参数与字段说明

参数/概念含义备注
adjust="forward"前复权必须,除权缺口会污染 TR/VM
tr真实波幅三者取大,做归一化分母
vmp今日高 − 昨日低上行涡旋位移
vmn今日低 − 昨日高下行涡旋位移
n=14累加窗口常用 14,可调
VI+ / VI−VM 的 N 日和 ÷ TR 的 N 日和交叉判方向

关键坑与注意事项

常见问题(FAQ)

Q:涡旋指标和 DMI/ADX 有什么区别? A:都用来判趋势方向与强弱。DMI 的 +DI/−DI 基于方向性移动(DM);涡旋指标用相邻两日高低的交叉位移(VM)除以 TR。思路相近、构造不同,可互相印证。

Q:VI+ 和 VI− 的取值范围是多少? A:都为正数,通常在 1 附近波动:VI+ > VI− 偏多、VI+ < VI− 偏空;两者偏离 1 越远,方向性越强。

Q:需要付费吗? A:单只股票日线在免费额度内即可;若要对全市场批量扫 VI+ 刚上穿 VI− 的票,需要 klines.batch + universes(Starter 及以上),详见官网定价页。

小结

涡旋指标用 VI+ 与 VI− 两条线把上行与下行力量分开量化,交叉提示趋势方向转换。用 AlphaFeed 的前复权 OHLC,十几行即可实现并检测金叉——记住 VM 的交叉项别写反、震荡市假信号多、它给的是方向倾向而非精确买卖点。

相关链接:


免责声明:本文仅为技术与数据接口使用示例,代码与策略仅供学习研究,不构成投资建议。市场有风险,历史数据不代表未来表现。