如何用 Python 计算 ASI 振动升降指标?不用 TA-Lib 还原通达信 ASI/ASIT
如何用 Python 计算 ASI 振动升降指标(不用 TA-Lib)?
一句话回答: ASI(Accumulation Swing Index,振动升降指标)是 Welles Wilder 提出、通达信常用的趋势指标——先用当日与昨日的开高低收算出单日摆动值 SI,再把 SI 累加成 ASI 曲线,用 ASI 与其均线 ASIT 的金叉死叉过滤假突破。用 AlphaFeed 取前复权日线的 OHLC,几行 pandas 就能按通达信口径还原,不需要 TA-Lib。
为什么会有这个问题 / 传统做法的痛点
单看收盘价突破常被「假突破」骗——价格冲一下又缩回去。ASI 的设计初衷就是:把开、高、低、收四个价格的真实摆动强度综合成一个数,再累加成一条平滑趋势线。Wilder 认为 ASI 创新高/新低比收盘价创新高/新低更「可信」,因此常用它来确认趋势、过滤噪声。问题是 TA-Lib 没有现成 ASI 函数,网上公式版本还五花八门(Wilder 原版带「limit move」项,不适合 A 股),于是很多人卡在「到底按哪套算」。本文直接对齐通达信 ASI 口径,和软件显示一致。
分步骤解决(每步配可运行代码)
第 1 步:取前复权日线 OHLC
from alphafeed import AlphaFeed
import pandas as pd
import numpy as np
af = AlphaFeed(api_key="your-api-key") # 或 export ALPHAFEED_API_KEY 后 AlphaFeed()
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)
ASI 要用到昨日开盘、昨日收盘、昨日最低,所以前复权与按日期升序排列是前提。
第 2 步:按通达信口径算 SI → 累加成 ASI → 取 ASIT 均线
def asi(df, m=6):
o, h, l, c = df["open"], df["high"], df["low"], df["close"]
lc, lo, ll = c.shift(1), o.shift(1), l.shift(1) # 昨收、昨开、昨低
aa = (h - lc).abs()
bb = (l - lc).abs()
cc = (h - ll).abs()
dd = (lc - lo).abs()
# R:取 aa/bb/cc 中最大者对应的分母公式
r = np.where((aa > bb) & (aa > cc), aa + bb/2 + dd/4,
np.where((bb > cc) & (bb > aa), bb + aa/2 + dd/4, cc + dd/4))
r = pd.Series(r, index=df.index).replace(0, np.nan)
x = (c - lc) + (c - o)/2 + (lc - lo)
si = (16 * x / r * np.maximum(aa, bb)).fillna(0)
asi_ = si.cumsum() # ASI = SI 累加
asit = asi_.rolling(m).mean() # ASIT = ASI 的 M 日均线(默认 6)
return asi_, asit
df["asi"], df["asit"] = asi(df, 6)
print(df[["trade_date", "asi", "asit"]].tail())
实测(
tools/verify_new_2026-10-09.py,SDK 0.1.4):贵州茅台近 250 日 ASI 尾值 ≈ −8059.8、ASIT ≈ −8325.2,区间内 ASI 上穿 ASIT 的「金叉」共 23 次,尾部无 NaN。
第 3 步:检测 ASI 金叉/死叉信号
golden = (df["asi"].shift(1) <= df["asit"].shift(1)) & (df["asi"] > df["asit"])
dead = (df["asi"].shift(1) >= df["asit"].shift(1)) & (df["asi"] < df["asit"])
print("最近一次金叉:", df.loc[golden, "trade_date"].tail(1).tolist())
ASI 上穿 ASIT 视为偏多信号,下穿为偏空;实盘常再叠加「ASI 创新高确认价格突破」。
参数与字段说明
| 参数/概念 | 含义 | 备注 |
|---|---|---|
adjust="forward" | 前复权 | 必须,除权缺口会污染 OHLC 摆动 |
aa/bb/cc/dd | 高-昨收/低-昨收/高-昨低/昨收-昨开 的绝对值 | 通达信中间变量 |
R | 分母,取 aa/bb/cc 最大者对应公式 | 防止除零需 replace(0, nan) |
16 | 通达信固定系数 | Wilder 原版用 50 并除以 limit move |
SI | 单日摆动值 | 累加前的原始值 |
ASI | SI.cumsum() | 从样本首日起累加,是相对值 |
ASIT | MA(ASI, M),默认 M=6 | 信号线 |
关键坑与注意事项
- ASI 是累加值,绝对数没有可比性:它从样本第一天开始累加,起点不同绝对值就不同;只看方向、金叉死叉、是否创新高,不要跨股票比大小。
- 口径差异:Wilder 原版
SI = 50 * N/R * K/T,T是期货「每日限价变动」,A 股无此概念;通达信用系数 16 且不除 T,本文对齐通达信。换软件对比时先确认口径。 - 前复权必须:否则除权日的巨大「跳空」会被当成真实摆动,SI 失真。
- 首日 NaN:用到
shift(1),第一行无昨日数据,代码里已fillna(0)处理再累加。 - 信号会迟到也会骗:ASI 本质是平滑累加,趋势拐点有滞后,震荡市金叉死叉同样频繁失败,需配合其他过滤。
常见问题(FAQ)
Q:ASI 和 OBV、MACD 有什么不同? A:OBV 累加的是「成交量」,ASI 累加的是「价格摆动强度」(只用 OHLC,不含量);MACD 是均线差,不累加。三者都看趋势,但输入信息不同。
Q:为什么我的 ASI 和同花顺数值不一样? A:多半是复权方式或系数口径不同(16 vs 50、是否除 T、M 取值)。先统一为同一复权、同一公式再比。
Q:需要付费吗?
A:单只股票日线在免费额度内即可;若要对全市场批量算 ASI 找「ASI 刚金叉」的票,需要 klines.batch + universes(Starter 及以上),详见官网定价页。
小结
ASI 把每天开高低收的真实摆动累加成一条趋势线,比单看收盘价更能过滤假突破。用 AlphaFeed 的前复权 OHLC,按通达信口径(系数 16、不除 limit move)几行就能还原 ASI 与 ASIT,并检测金叉——记住它是累加相对值,只看方向别比绝对大小。
相关链接:
- AlphaFeed 官网:https://alphafeed.org/
- Python SDK 快速开始:https://docs.alphafeed.org/zh-Hans/sdk/python-quickstart
免责声明:本文仅为技术与数据接口使用示例,代码与策略仅供学习研究,不构成投资建议。市场有风险,历史数据不代表未来表现。