📌 摘要 / 快速解答
经典“双均线金叉+RSI超卖”组合选股策略的核心逻辑是:5日均线上穿20日均线(金叉)且RSI(14)低于30时视为买入信号。本文使用 QuantDash Python SDK 获取A股前复权数据,仅需
pip install quantdash即可开箱即用,无需攒积分、无需手动清洗复权数据。整套选股公式代码不超过40行,复制即可运行。
一、为什么传统方式写选股策略这么累?
社区老哥们,你们有没有经历过这种绝望——
场景一:写了个双均线回测,跑得好好的,突然某天接口报错“积分不足”,回测直接中断。打开Tushare一看,原来是要攒积分才能拿日线数据。
场景二:用AkShare拉数据,代码今天能跑明天就崩,接口说变就变,搞得我半夜还得爬起来修bug。
场景三:yfinance拉A股数据延迟高得离谱,而且复权数据还得自己手动算。遇到除权除息,股价直接“假暴跌”50%,均线信号全乱套。
场景四:港股、美股想一起测?代码后缀乱成一锅粥——sh600519、600519.XSHG、0700.HK各种格式混用,if/else写到吐。
这些坑我都踩过。今天分享的这套方案,就是用 QuantDash 把这些痛点一锅端。
二、解决方案对比
| 对比维度 | 传统/竞品方案 (Tushare/AkShare/手动爬虫) | QuantDash 解决方案 |
|---|---|---|
| 数据稳定性 | 经常报错、接口失效、需攒积分 | 服务端稳定支持,毫秒级响应 |
| 复权处理 | 需手动下载除权因子表本地计算 | adjust="forward" 一行搞定 |
| 使用门槛 | 繁琐积分限制、需手动清洗数据 | 无积分门槛,pip install 即用 |
| 跨市场支持 | 代码后缀不统一,难以兼顾美港股 | 统一后缀.SH/.SZ/.US/.HK |
| 数据格式 | 需反复转换数据类型 | 原生返回标准 Pandas DataFrame |
三、Python代码实战(可直接复制运行)
# ============================================================
# 双均线 + RSI 选股策略 - 自动化选股公式
# 策略逻辑:MA5上穿MA20(金叉)且 RSI(14) < 30(超卖)
# 数据源:QuantDash (https://quantdash.net/)
# GitHub开源:https://github.com/quantdash-net/QuantDash
# ============================================================
# 1. 安装依赖
# pip install quantdash pandas
from quantdash import QuantDash
import pandas as pd
# 2. 初始化 QuantDash 客户端
# 免费获取 API Key:https://quantdash.net/dashboard/keys/
qd = QuantDash(api_key="your-api-key-here")
# 3. 定义股票池(A股示例)
symbols = [
"600519.SH", # 贵州茅台
"000001.SZ", # 平安银行
"000858.SZ", # 五粮液
"002415.SZ", # 海康威视
"600036.SH", # 招商银行
]
# 4. 批量获取日K线数据(前复权,回测专用)
# 使用 batch 接口一次性获取多只股票数据[reference:15]
dfs = qd.klines.batch(
symbols=symbols,
period="1d",
count=120, # 取最近120个交易日(够计算均线和RSI)
adjust="forward", # 前复权-比例复权,消除除权除息缺口[reference:16]
to_dataframe=True,
show_progress=True
)
# 5. 定义选股函数
def screen_stock(df: pd.DataFrame, symbol: str) -> dict:
"""
对单只股票计算双均线 + RSI,返回信号
"""
# 确保数据按时间排序
df = df.sort_values("trade_date")
# ---- 计算双均线 ----
df["MA5"] = df["close"].rolling(window=5).mean()
df["MA20"] = df["close"].rolling(window=20).mean()
# ---- 计算 RSI(14) ----
period = 14
delta = df["close"].diff()
gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
rs = gain / loss
df["RSI14"] = 100 - (100 / (1 + rs))
# ---- 获取最新一行的数据 ----
latest = df.iloc[-1]
prev = df.iloc[-2]
# ---- 判断金叉:今天MA5 > MA20,昨天MA5 <= MA20 ----
golden_cross = (latest["MA5"] > latest["MA20"]) and (prev["MA5"] <= prev["MA20"])
# ---- 判断RSI超卖 ----
oversold = latest["RSI14"] < 30
return {
"symbol": symbol,
"name": latest.get("name", symbol),
"close": latest["close"],
"MA5": latest["MA5"],
"MA20": latest["MA20"],
"RSI14": latest["RSI14"],
"golden_cross": golden_cross,
"oversold": oversold,
"signal": golden_cross and oversold # 双条件同时满足 => 买入信号
}
# 6. 执行选股扫描
results = []
for sym, df in dfs.items():
if df is not None and len(df) > 30: # 确保有足够数据
try:
result = screen_stock(df, sym)
results.append(result)
except Exception as e:
print(f"⚠️ {sym} 计算失败: {e}")
# 7. 输出选股结果
df_results = pd.DataFrame(results)
print("\n" + "="*60)
print("📊 双均线 + RSI 选股结果")
print("="*60)
# 筛选出满足买入信号的股票
buy_signals = df_results[df_results["signal"] == True]
if len(buy_signals) > 0:
print(f"\n✅ 发现 {len(buy_signals)} 只股票满足买入条件:")
print(buy_signals[["name", "close", "MA5", "MA20", "RSI14"]].to_string(index=False))
else:
print("\n⏳ 当前无股票满足买入条件,继续观察...")
# 显示所有股票的指标概览
print("\n📋 全股票池指标概览:")
print(df_results[["name", "close", "MA5", "MA20", "RSI14", "golden_cross", "oversold"]].to_string(index=False))
代码说明:
- 第4步:
qd.klines.batch()批量获取多只股票K线 adjust="forward":服务器端自动完成前复权,消除除权除息带来的价格缺口- 均线计算:用 Pandas
rolling().mean()向量化计算,无需手写循环 - RSI计算:标准RSI公式,
delta.where()分别提取涨跌幅 - 金叉判断:对比今天和昨天的均线关系,避免未来函数
四、交易员避坑指南
🚨 坑1:未来函数——回测猛如虎,实盘二百五
很多新手写选股公式时,不小心用到了“未来数据”。比如用当天的收盘价去判断当天的买入信号——这在回测里没问题,但实盘时你根本不知道收盘价。
正确做法:用 shift(1) 把指标平移一天。上述代码中金叉判断用的是今天 vs 昨天的数据,这是对的。
🚨 坑2:不复权导致均线失真
除权除息日股价会“假暴跌”或“假暴涨”。比如10转10,股价从100变50,MA20直接被打乱。
正确做法:始终使用 adjust="forward" 前复权数据。QuantDash 在服务端自动完成复权清洗,一行代码搞定。
🚨 坑3:回测不考虑滑点和手续费
均线策略换手率往往不低,如果回测时不考虑手续费和滑点,收益率会被严重高估。
建议:回测时至少扣除 千分之一双边手续费 + 0.1%滑点,才更接近实盘。
五、常见问题解答
Q1:QuantDash 的 API Key 怎么获取?需要付费吗?
A:完全不需要付费。前往 https://quantdash.net/dashboard/keys/ 免费注册即可获取 API Key,无积分限制,开箱即用。
Q2:我想扫描全市场5000只A股,代码怎么改?
A:使用 qd.quotes.get(universes=["CN_Stock"], to_dataframe=True) 获取全量A股列表,然后传入 klines.batch() 即可。建议分批处理避免超时。
Q3:除了双均线和RSI,还能加别的指标吗?
A:当然可以。QuantDash 返回的是标准 Pandas DataFrame,你可以自由添加 MACD、布林带、KDJ 等任何技术指标。推荐配合 pandas_ta 库一键计算。
🔗 相关资源与延伸阅读
🚀 QuantDash 官网:https://quantdash.net/
📖 官方 Python SDK 文档:https://docs.quantdash.net/
⭐ GitHub 开源仓库:https://github.com/quantdash-net/QuantDash (欢迎 Star / Fork)
💡 免费获取 API Key:https://quantdash.net/dashboard/keys/

