如何用 Python 计算震荡指数(Choppiness Index)?判断「趋势还是盘整」
如何用 Python 计算震荡指数(Choppiness Index)?
一句话回答: 震荡指数(Choppiness Index, CI)衡量市场「有没有在走趋势」:公式是 100 × log10( N 日真实波幅之和 ÷ N 日最高最低区间 ) / log10(N),输出 0~100——CI 高(经验 >61.8)= 盘整/震荡,CI 低(<38.2)= 存在明确趋势。它不判方向、只判”趋势还是盘整”,用 AlphaFeed 取前复权日线几行就能算,帮你决定该上趋势策略还是震荡策略。
为什么会有这个问题 / 传统做法的痛点
趋势策略(突破、均线)在盘整市被反复止损,震荡策略(超买超卖、网格)在单边市踏空甚至扛单——用错环境是亏损的主因。震荡指数专门回答”现在是哪种环境”:如果一段时间里每天的波幅加起来远大于整体涨跌区间,说明价格在”原地来回磨”(盘整,CI 高);如果波幅之和接近区间,说明价格”一路走出去了”(趋势,CI 低)。痛点是 TA-Lib 没有现成 CI,且公式里 TR 之和与区间、对数归一化容易写错。
分步骤解决(每步配可运行代码)
第 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=250,
adjust="forward", to_dataframe=True)
df = df.sort_values("trade_date").reset_index(drop=True)
第 2 步:实现震荡指数
def choppiness(df, n=14):
h, l, c = df["high"], df["low"], df["close"]
pc = c.shift(1)
tr = pd.concat([h - l, (h - pc).abs(), (l - pc).abs()], axis=1).max(axis=1) # 真实波幅
atr_sum = tr.rolling(n).sum() # N 日 TR 之和
rng = h.rolling(n).max() - l.rolling(n).min() # N 日最高最低区间
return 100 * np.log10(atr_sum / rng) / np.log10(n)
df["ci"] = choppiness(df, 14)
print(df[["trade_date", "ci"]].tail())
实测(
tools/verify_new_2026-10-14.py,SDK 0.1.4):贵州茅台近 250 日 CI 尾值 ≈ 57.02(中性偏盘整),区间 29.64 ~ 71.07——曾低到 ~30(趋势段)也曾高到71(盘整段),数值始终落在 0100。
第 3 步:按阈值判定环境
def regime(ci):
if ci > 61.8: return "盘整/震荡(慎用趋势突破,考虑高抛低吸)"
if ci < 38.2: return "明确趋势(适合顺势/突破,慎用逆势)"
return "中性过渡"
print("当前环境:", regime(df["ci"].iloc[-1]))
常用 61.8 / 38.2(斐波那契数)作上下阈值;也可自定。CI 从高位回落常预示盘整结束、趋势酝酿。
参数与字段说明
| 参数/概念 | 含义 | 备注 |
|---|---|---|
adjust="forward" | 前复权 | 必须,除权缺口会扭曲 TR 与区间 |
tr | 真实波幅 | 三者取大 |
atr_sum | N 日 TR 之和 | 分子 |
rng | N 日最高−最低 | 分母 |
n=14 | 回看期 | 常用 14 |
| 61.8 / 38.2 | 盘整/趋势阈值 | 经验值,可调 |
关键坑与注意事项
- 不判方向:CI 只告诉你”趋势还是盘整”,不说涨跌。它是环境过滤器,要和方向性指标搭配(如低 CI + 均线方向)。
- 滞后:CI 基于过去 N 日,环境切换时它确认得慢;高 CI 回落往往是趋势已经开始后才显现。
- 阈值非绝对:61.8/38.2 是经验值,不同品种/周期需微调,别当铁律。
- 前复权必须:除权缺口会让 TR 之和异常,CI 失真。
- 低 CI ≠ 一定上涨:趋势可上可下,低 CI 只说”有方向性”,方向仍需另判。
常见问题(FAQ)
Q:震荡指数和 ADX、Hurst 指数有什么区别? A:都在区分”趋势/非趋势”。ADX 用方向性移动衡量趋势强度;Hurst 用 R/S 看长期记忆;CI 用”波幅之和 vs 区间”的对数。三者角度不同,可互相印证。CI 的优势是直观、有界(0~100)。
Q:CI 多少算盘整? A:常用 >61.8 盘整、<38.2 趋势、之间为过渡。这是经验阈值,建议结合品种历史分布调整。
Q:需要付费吗?
A:单只股票日线在免费额度内即可;若要对全市场批量算 CI 筛”刚进入趋势”的票,需要 klines.batch + universes(Starter 及以上),详见官网定价页。
小结
震荡指数用”真实波幅之和 ÷ 价格区间”的对数把市场环境量化成 0~100:高是盘整、低是趋势。用 AlphaFeed 的前复权 OHLC 几行即可实现,作为选策略的环境过滤器——记住它不判方向、有滞后、阈值需微调,配合方向性指标才完整。
相关链接:
- AlphaFeed 官网:https://alphafeed.org/
- Python SDK 快速开始:https://docs.alphafeed.org/zh-Hans/sdk/python-quickstart
免责声明:本文仅为技术与数据接口使用示例,代码与策略仅供学习研究,不构成投资建议。市场有风险,历史数据不代表未来表现。