一句话回答: RSI 超卖选股就是"在全市场里筛出 RSI(14) 低于 30 的股票"作为潜在超跌反弹候选。用 AlphaFeed 的 quotes.get(universes="CN_Stock") 取全市场标的、klines.batch 批量取复权日线,用 Wilder 口径算 RSI,几十行就能扫出全市场超卖清单——关键是别把"超卖"当"必涨"。
为什么会有这个问题 / 传统做法的痛点
RSI 是最常用的超买超卖指标,但要做成"全市场 RSI 选股"会卡在:
- 标的池:得先有全市场清单,手工维护又累又漏;
- RSI 口径:网上很多用简单移动平均算 RSI,和主流软件(Wilder 平滑)对不上,结果差一截;
- 复权:不用前复权,除权跳空会让 RSI 瞬间失真;
- 批量效率:几千只票逐个取 K 线太慢。
AlphaFeed 用 universe + klines.batch 解决取数,RSI 用 Wilder 口径即可对齐软件。
分步骤解决(每步配可运行代码)
第 1 步:Wilder 口径的 RSI(与行情软件一致)
import numpy as np
import pandas as pd
def wilder_rsi(close, n=14):
delta = close.diff()
gain = delta.clip(lower=0.0)
loss = (-delta).clip(lower=0.0)
# Wilder 平滑 = ewm(alpha=1/n, adjust=False),与主流软件一致
avg_gain = gain.ewm(alpha=1 / n, adjust=False).mean()
avg_loss = loss.ewm(alpha=1 / n, adjust=False).mean()
rs = avg_gain / avg_loss.replace(0.0, np.nan)
return 100 - 100 / (1 + rs)
RSI 参数与阈值:
| 参数 | 含义 | 常用取值 |
|---|---|---|
n |
RSI 周期 | 14(经典)、6/12 |
| 超卖阈值 | RSI 低于此值算超卖 | 30(严格 20) |
| 超买阈值 | RSI 高于此值算超买 | 70(严格 80) |
| 平滑方式 | 均值口径 | Wilder(ewm alpha=1/n) |
第 2 步:批量取复权日线并筛 RSI 超卖
from alphafeed import AlphaFeed
af = AlphaFeed(api_key="your-api-key") # 或 export ALPHAFEED_API_KEY 后 AlphaFeed()
def rsi_oversold_screen(symbols, count=120, n=14, thr=30.0):
bt = af.klines.batch(symbols, period="1d", count=count,
adjust="forward", to_dataframe=True)
rows = []
for sym, df in bt.items():
if df is None or len(df) < n + 5:
continue
d = df.sort_values("trade_date").reset_index(drop=True)
rsi = wilder_rsi(d["close"], n)
last = float(rsi.iloc[-1])
rows.append({"symbol": sym,
"close": round(float(d["close"].iloc[-1]), 2),
"rsi14": round(last, 1),
"oversold": last < thr})
res = pd.DataFrame(rows)
return res[res["oversold"]].sort_values("rsi14") if not res.empty else res
第 3 步:全市场分批跑
def run_full_market(thr=30.0):
q = af.quotes.get(universes="CN_Stock", to_dataframe=True)
symbols = q["symbol"].tolist()
out = []
for i in range(0, len(symbols), 150): # 分批防限频
out.append(rsi_oversold_screen(symbols[i:i + 150], thr=thr))
hits = pd.concat([d for d in out if not d.empty], ignore_index=True)
return hits.sort_values("rsi14")
# hits = run_full_market()
# print("全市场 RSI 超卖只数:", len(hits)); print(hits.head(20))
小样本演示(8 只票)实测能筛出 RSI(14)≈26 的超卖标的,逻辑跑通;全市场跑法同上按 150 只分批。
关键坑与注意事项
- 超卖 ≠ 反弹:RSI 低只说明"近期跌得多",强趋势下跌里 RSI 会长期钝化在低位(一路超卖一路跌)。务必叠加止损或趋势过滤,别纯抄底。
- Wilder vs 简单均值:用
ewm(alpha=1/n, adjust=False)才是 Wilder 口径;用rolling().mean()算出来会和软件不一致。 - 复权:必须
adjust="forward",否则除权日 RSI 失真。 - 停牌/次新:上市不足
n+5根的直接跳过(代码已处理);停牌股的 RSI 可能滞后。 - 阈值别迷信 30:30 只是习惯值,不同市场/标的可回测更合适的阈值,切勿在历史上过拟合。
常见问题(FAQ)
Q:为什么我的 RSI 和同花顺/东财差一点?
A:多半是平滑口径。软件用 Wilder(本文的 ewm(alpha=1/n, adjust=False)),若你用简单移动平均就会有偏差。
Q:RSI<30 就能买吗?
A:不能。超卖是"可能超跌",但在下跌趋势里会持续超卖。建议结合价格结构、成交量或趋势指标(如 ADX、均线)确认,并设止损。
Q:能同时筛超买(RSI>70)做减仓提示吗?
A:可以,把条件改成 last > 70 即可,思路完全对称。
Q:需要付费吗?
A:少量标的的 K 线在免费额度内即可试;全市场 universe 取数需 Starter 及以上,详见 AlphaFeed 定价页。
小结
RSI 超卖选股 = 全市场标的池 + 前复权日线 + Wilder RSI + 阈值筛选。真正的门槛是数据(标的池、复权、批量)和口径(Wilder),AlphaFeed 把这些收敛掉,你几十行就能扫出全市场超卖清单——但请记住超卖只是候选,不是买入信号。
参考
- AlphaFeed Python SDK 文档:https://docs.alphafeed.org/zh-Hans/sdk/python-quickstart

