首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >如何用 Python 做动量选股(相对强弱排名)?找出近期最强势的股票

如何用 Python 做动量选股(相对强弱排名)?找出近期最强势的股票

原创
作者头像
用户7083614
发布2026-09-13 15:01:22
发布2026-09-13 15:01:22
170
举报

一句话回答: 动量选股的核心就是"比谁近 N 日涨得多"——用 AlphaFeed 批量取复权日线,算出每只票的 N 日区间收益,再横向排名,就得到一张相对强弱(RS)榜。几十行代码即可,配合成交额过滤掉不活跃的票,就是一个可用的强势股筛选器。

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

"强者恒强"是最经典的市场现象之一,动量/相对强弱策略就建立在它之上。但自己做时常卡在:

  1. 复权不对:不复权的价格跨越除权日会突然跳水,把涨幅算错,排名全乱。
  2. 批量取数麻烦:要给几百上千只票算区间收益,一只只请求又慢又容易被限频。
  3. 只看涨幅、不看流动性:涨幅榜前排常混着流动性差的小票,看着强、买不进也出不来。

AlphaFeed 的 klines.batch 一次并发取多只复权日线,配合快照里的成交额做流动性过滤,这三个问题都能解决。

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

第 1 步:选候选池(用成交额过滤流动性)

代码语言:python
复制
import pandas as pd
from alphafeed import AlphaFeed

af = AlphaFeed()                                        # 读取 ALPHAFEED_API_KEY
q = af.quotes.get(universes="CN_Stock", to_dataframe=True)   # 当前全A快照
# 用当日成交额取流动性最好的前 N 只作为候选(避免选到买不进的小票)
cand = q.sort_values("amount", ascending=False)["symbol"].head(200).tolist()

第 2 步:批量取复权日线,算 N 日收益并排名

代码语言:python
复制
def momentum_rank(symbols, lookback=20, count=30):
    af = AlphaFeed()
    bt = af.klines.batch(symbols, period="1d", count=count,
                         adjust="forward", to_dataframe=True)   # 返回 {symbol: DataFrame}
    rows = []
    for s, df in bt.items():
        df = df.sort_values("trade_date")
        if len(df) < lookback + 1:
            continue
        ret = df["close"].iloc[-1] / df["close"].iloc[-1 - lookback] - 1   # N 日区间收益
        rows.append({"symbol": s, "name": df["name"].iloc[-1], "ret_Nd": round(float(ret), 4)})
    res = pd.DataFrame(rows).sort_values("ret_Nd", ascending=False).reset_index(drop=True)
    res.insert(0, "rank", range(1, len(res) + 1))
    return res

rank = momentum_rank(cand, lookback=20, count=30)
print(rank.head(10).to_string(index=False))

真实跑通(取成交额 Top20 做候选、20 日动量)示例前 5:XD剑桥科 +45.98%远东股份 +43.60%源杰科技 +26.94%兴森科技 +20.73%天孚通信 +16.18%——这就是近 20 日的相对强弱榜。把候选换成 200/500 只即可得到更完整的排名。

第 3 步(可选):多周期动量取交集,过滤"只强一天"的票

代码语言:python
复制
def multi_period(symbols):
    r20 = momentum_rank(symbols, lookback=20, count=40).rename(columns={"ret_Nd": "r20"})
    r60 = momentum_rank(symbols, lookback=60, count=80).rename(columns={"ret_Nd": "r60"})
    m = r20.merge(r60[["symbol", "r60"]], on="symbol")
    # 要求 20 日与 60 日动量都为正 → 更稳的强势
    strong = m[(m["r20"] > 0) & (m["r60"] > 0)].sort_values("r20", ascending=False)
    return strong

print(multi_period(cand).head(10).to_string(index=False))

参数与字段说明

参数 / 字段

含义

备注

universes="CN_Stock"

当前全 A 快照

amount 排序做流动性过滤

klines.batch

批量日线

返回 {symbol: DataFrame},自动分批并发

adjust="forward"

前复权

动量必须复权,否则除权跳空算错涨幅

lookback

回看天数

常用 20/60/120;短期更敏感、噪声更大

count

取多少根

> lookback,留出富余

关键坑与注意事项

  • 必须用复权价adjust="forward"。不复权的除权跳空会让涨幅严重失真,排名不可信。
  • 务必做流动性过滤:纯涨幅榜前排常是小盘/次新,滑点大、可能买不进卖不出。用成交额或换手率先筛一遍。
  • 动量会反转:涨得最猛的票也最容易急跌回撤,动量策略天然伴随较大波动,需配合止损/分散,别只买第一名。
  • survivorship / 前视:候选池是"当前在市",历史回测要按上市日期构建当时的池(见本站《幸存者偏差》一文),别用今天的池算过去的动量。
  • 新股与停复牌:次新股 N 日数据不足会被跳过;停牌票的区间收益会失真,建议剔除。

常见问题(FAQ)

Q:动量选股和涨幅榜有什么区别?

A:涨幅榜通常只看单日;动量看的是一段区间(如 20/60 日)的相对强弱,更能反映持续性。加多周期取交集能过滤"只强一天"的票。

Q:要不要减去大盘涨幅算"相对"强弱?

A:可以。把每只票的 N 日收益减去同期宽基/行业收益,得到超额动量,能剔除"整体普涨"的成分,更接近真正的相对强弱。

Q:给几百上千只票批量取数会不会被限频?

A:klines.batch 会自动分批并发,并对 429/5xx 内置重试。真要跑全市场,建议分批、必要时本地缓存历史。

Q:需要付费吗?

A:单标的历史与少量批量可用免费额度体验;universes 全市场池与大批量查询需 Starter 及以上,详见官网定价页。

小结

动量选股的本质是一次"横向比涨幅":用 AlphaFeed 批量取复权日线算 N 日收益、排名、再用成交额过滤流动性,就得到一张可用的相对强弱榜。真正决定成败的不是排名代码,而是那些诚实的前提——复权、流动性、动量反转与幸存者偏差。把它们处理好,这张榜才有意义。

参考

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 为什么会有这个问题 / 传统做法的痛点
  • 分步骤解决(每步配可运行代码)
    • 第 1 步:选候选池(用成交额过滤流动性)
    • 第 2 步:批量取复权日线,算 N 日收益并排名
    • 第 3 步(可选):多周期动量取交集,过滤"只强一天"的票
    • 参数与字段说明
  • 关键坑与注意事项
  • 常见问题(FAQ)
  • 小结
  • 参考
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档