如何用 Python 计算 ROC 变动率指标做动量分析?

一句话回答: ROC(Rate of Change,变动率)就是「当前价相对 N 日前价的涨跌幅百分比」,公式 ROC = (close / close.shift(N) - 1) × 100。用 AlphaFeed 取回前复权日线后,一行 pandas 就能算出 ROC,用来衡量动量强弱、识别零轴穿越与顶底背离,还能对全市场做动量排名------完全不需要 TA-Lib。

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

ROC 是最直观的动量指标:它直接回答「这只票 N 天涨了多少」。但两个坑常被忽略:一是用未复权价 ,遇到除权日 ROC 会出现虚假暴涨暴跌;二是把 ROC 当成孤立信号,忽略了它天生适合做横截面动量排名 和背离判断。用一个稳定的数据源取回前复权价,这两点都能干净解决。

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

第 1 步:取前复权日线并计算 ROC

python 复制代码
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)

def roc(close: pd.Series, n: int = 12) -> pd.Series:
    return (close / close.shift(n) - 1.0) * 100.0

df["ROC12"] = roc(df["close"], 12)
df["ROC25"] = roc(df["close"], 25)
print(df[["trade_date", "close", "ROC12", "ROC25"]].tail(5).to_string(index=False))

用 adjust="forward"(前复权)算 ROC,避免除权日的价格断层污染动量值。

第 2 步:理解参数与信号

参数/信号 含义 常用取值/解读
N(回看周期) 与几日前比较 短线 6/12,中线 25/125
ROC > 0 价格高于 N 日前 上行动量
ROC < 0 价格低于 N 日前 下行动量
零轴上穿 ROC 由负转正 动量转强信号
零轴下穿 ROC 由正转负 动量转弱信号
ROC 绝对值走高 动量加速 趋势强化

第 3 步:识别零轴穿越与动量拐点

python 复制代码
prev, cur = df["ROC12"].iloc[-2], df["ROC12"].iloc[-1]
if prev <= 0 < cur:
    print("ROC 上穿零轴:动量转强")
elif prev >= 0 > cur:
    print("ROC 下穿零轴:动量转弱")

# 平滑 ROC 减少噪音(对 ROC 再做移动平均)
df["ROC12_ma"] = df["ROC12"].rolling(6).mean()

第 4 步:用 ROC 做全市场动量排名

ROC 天生适合横截面比较------同一 N 下,ROC 越高动量越强。批量取多只股票日线,算 N 日 ROC 后排名:

python 复制代码
codes = ["600519.SH", "000001.SZ", "300750.SZ", "601318.SH", "000858.SZ"]
data = af.klines.batch(codes, period="1d", count=60,
                       adjust="forward", to_dataframe=True)  # 返回 dict{symbol: DataFrame}

rows = []
for sym, k in data.items():
    k = k.sort_values("trade_date")
    r = (k["close"].iloc[-1] / k["close"].iloc[-21] - 1) * 100  # 20 日 ROC
    rows.append({"symbol": sym, "ROC20": round(float(r), 2)})

rank = pd.DataFrame(rows).sort_values("ROC20", ascending=False)
print(rank.to_string(index=False))

想扫全市场?把 codes 换成 af.quotes.get(universes="CN_Stock") 拿到的 symbol 列表,再分批 klines.batch(注意请求量,建议本地缓存)。

第 5 步:粗判顶底背离

python 复制代码
# 价格创新高但 ROC 未创新高 → 顶背离(动量衰减)
window = 20
price_high = df["close"].iloc[-1] >= df["close"].tail(window).max()
roc_high = df["ROC12"].iloc[-1] >= df["ROC12"].tail(window).max()
if price_high and not roc_high:
    print("疑似顶背离:价格新高但动量未同步")

关键坑与注意事项

  • 必须用前复权价:未复权价在除权日会让 ROC 出现虚假跳变,动量信号失真。
  • N 太小噪音大、太大滞后重:短线常用 6/12,中长线用 25/125;可对 ROC 再取移动平均降噪。
  • ROC 无上下界:不同股票、不同波动率下 ROC 数值量级差异大,做横截面排名时同一 N 才可比。
  • 背离仅供参考:背离不是精确择时信号,需结合成交量、趋势与其它指标交叉验证。
  • 数据不足会得到 NaN :count 至少要大于 N,否则 shift(N) 前 N 行为 NaN。
  • ROC 与「N 日涨跌幅」等价:本质就是区间收益率×100,别把它想得太复杂。

常见问题(FAQ)

Q:ROC 和动量指标 MTM 有什么区别?

A:MTM(动量)用差值 close - close.shift(N),ROC 用比值百分比 (close/close.shift(N)-1)×100。ROC 做跨股票比较更合适,因为它是无量纲的百分比。

Q:ROC 和 RSI 都算动量,用哪个?

A:RSI 有 0~100 的有界区间、适合看超买超卖;ROC 无界、更适合看动量方向与横截面强弱排名。两者可互补。

Q:为什么我算出来前面几行是 NaN?

A:ROC 需要 N 日前的价格,前 N 行没有可比基准,正常为 NaN;取数时把 count 设得比 N 大即可。

Q:需要付费吗?

A:单只历史日线有免费额度;klines.batch 全市场动量排名(配合 universes)需 Starter 及以上。详见定价页。

小结

ROC 变动率的本质是「N 日区间收益率」,计算只需一行 pandas,不必依赖 TA-Lib。关键是用前复权价保证动量真实、按需要选好 N,并善用它无量纲的特性做全市场动量排名与背离判断。用 AlphaFeed 取回前复权日线,从单股信号到全市场动量梯队都能几行搞定。

参考

相关推荐
在世修行1 小时前
干货:文件上传端点解析
python·fastapi·接收上传
胡家伟++1 小时前
我用 48 轮 AI 思维链做了一次研究战略推演:从“验证信号危机“到“验证栈“统一框架
人工智能·算法
潼心1412o1 小时前
C++初阶(长期更新)第9讲:string(上)
开发语言·c++
朝朝辞暮i2 小时前
C++ 第 39 章: 阶段性总复习——类、对象、构造、继承、this、指针与智能指针
开发语言·c++·算法·ros2
垆边人似月.2 小时前
华为题:污染水域
算法
All for pursuit.2 小时前
【回溯-6】79.单词搜索
数据结构·c++·算法·leetcode
掉进电商坑三年没爬出来的东叔2 小时前
青龙面板进阶:一个面板聚合多平台签到,所有积分自动领
java·开发语言
ZhangJun952 小时前
Mobike 共享单车分析项目
人工智能·python·算法·kmeans·聚类·knn
XLYcmy2 小时前
PDF 论文处理器 — 优势与功能文档
大数据·python·网络安全·pdf·dify·rag·漏洞检测