📌 摘要 / 快速解答 (Direct Answer)
量化交易里最危险的问题,很多时候不是策略写错,而是数据错了却没人发现:复权方式不一致、时间区间取错、行情接口中断,都可能让回测结果看起来“稳得离谱”。我做 A 股量化时,更愿意先把数据底座做好,再谈 MACD、KDJ、均线和策略优化;用 QuantDash + Pandas,可以用很少的代码拿到标准化 K 线,并直接处理前复权。
一、为什么传统方式写选股策略这么累?
我见过不少刚开始做 A 股量化的朋友,第一步不是研究策略,而是先和数据源大战三百回合。
最典型的流程是:
找接口 → 注册账号 → 攒积分 → 请求数据 → 接口报错 → 换接口 → 数据格式不一样 → 自己清洗 → 最后才开始写策略。
尤其到了回测阶段,问题就更明显。
1. 数据拿不到,策略根本没法验证
Tushare 对部分数据存在积分和权限门槛,新手经常卡在“代码写好了,但是数据拿不到”。
AkShare 的优势是接口丰富,但实际使用过程中,不同数据接口的稳定性、字段格式和返回结构可能让量化脚本维护起来比较麻烦。
还有一些人直接用网页数据或者手动爬虫。
短期看似省事,长期维护基本就是给自己挖坑。
2. 复权没处理好,收益率可能直接失真
这是我认为新手最容易忽略的问题之一。
股票发生分红、送股、拆股之后,历史价格会出现跳变。
如果你直接拿不复权价格计算:
今天收盘价 / 昨天收盘价 - 1
某些除权除息日就可能出现非常夸张的“收益”。
但这不一定是真实交易收益,而可能只是价格口径发生了变化。
QuantDash 的 K 线接口支持:
forward:前复权-比例backward:后复权-比例forward_additive:前复权-差值backward_additive:后复权-差值none:不复权
其中前复权比例方式适合收益率计算,这一点在做策略回测时非常实用。
3. 最大的问题:错误数据往往不会报错
这才是最可怕的。
代码运行成功:
Process finished with exit code 0
不代表你的回测就正确。
如果某一天的数据少了一根 K 线、复权口径错了、股票代码映射错误,Python 通常不会主动告诉你。
所以我现在做策略,第一原则就是:
先验证数据,再验证策略。
二、解决方案对比:传统数据源 vs QuantDash
| 对比维度 | 传统/竞品方案(Tushare/AkShare/手动爬虫) | QuantDash 解决方案 |
|---|---|---|
| 数据稳定性 | 容易遇到接口变动、报错或维护问题 | 服务端提供标准化行情数据 |
| 使用门槛 | 部分数据存在权限/积分门槛,且需要清洗 | pip install quantdash即可使用 |
| 跨市场支持 | 不同数据源代码格式和字段口径不统一 | A 股、美股、港股统一代码后缀 |
| 数据格式 | 经常需要转换和整理 | 原生支持 Pandas DataFrame |
| 复权处理 | 经常需要自己处理 | K 线接口直接支持多种adjust |
| 批量处理 | 往往需要自行封装 | 提供klines.batch |
| 时间区间 | 需要根据接口分别处理 | 支持start_time、end_time |
| A 股全市场行情 | 需要自己维护股票池 | 支持CN_Stock标的池 |
这里我尤其推荐新手注意两个能力:
统一代码格式 + 标准 DataFrame。
比如:
600519.SH
000001.SZ
920047.BJ
00700.HK
AAPL.US
做多市场研究的时候,少处理一层格式差异,就少一个出错点。
三、Python 代码实战:先把数据底座做好
安装 QuantDash:
pip install quantdash
然后初始化:
from quantdash import QuantDash
import pandas as pd
# QuantDash Python SDK
qd = QuantDash(api_key="your-api-key")
# 获取贵州茅台最近 60 个交易日的前复权日 K
df = qd.klines.get(
"600519.SH",
period="1d",
count=60,
adjust="forward",
to_dataframe=True
)
print(df[
[
"symbol",
"name",
"trade_date",
"open",
"high",
"low",
"close",
"volume"
]
].tail())
这里我建议大家养成一个习惯:
策略计算之前,先把原始数据打印出来检查。
例如:
print("数据行数:", len(df))
print("字段:", df.columns.tolist())
print("最新日期:", df["trade_date"].max())
print(df[["trade_date", "close", "volume"]].tail(10))
如果连数据是什么时候、多少行、有哪些字段都不知道,就直接进入回测阶段,我个人是不太建议的。
3.1 用 Pandas 快速计算均线
拿到 DataFrame 后,技术指标计算就简单很多。
例如做一个最基础的 MA20:
df["MA20"] = df["close"].rolling(20).mean()
print(
df[
["trade_date", "close", "MA20"]
].tail(10).to_string(index=False)
)
再加一个 MA60:
df["MA60"] = df["close"].rolling(60).mean()
df["trend_signal"] = (
df["MA20"] > df["MA60"]
)
print(
df[
["trade_date", "close", "MA20", "MA60", "trend_signal"]
].tail(10)
)
这就是我比较喜欢的量化代码风格:
数据获取和策略逻辑分开。
QuantDash 负责把标准数据拿回来,Pandas 负责计算,策略代码只关注信号。
3.2 一次获取多个 A 股标的
如果要做 A 股横截面选股,就不要一只股票一只股票请求。
可以直接:
symbols = [
"600519.SH",
"000001.SZ",
"000858.SZ"
]
dfs = qd.klines.batch(
symbols,
period="1d",
count=60,
adjust="forward",
to_dataframe=True,
show_progress=True
)
for symbol, data in dfs.items():
print(f"--- {symbol} ---")
print(
data[
["trade_date", "close", "volume"]
].tail()
)
这个结构非常适合后面继续做:
- MA 趋势筛选
- MACD 金叉筛选
- KDJ 超卖筛选
- BOLL 突破
- 成交量放大
- 多因子组合
四、交易员避坑指南:回测最容易死在哪?
坑 1:把“回测赚钱”直接等同于“策略有效”
这是量化新手最容易犯的错误。
如果一个策略回测收益特别漂亮,我反而会先怀疑:
是不是数据有问题?
然后才去看:
- 是否存在未来函数
- 是否使用了错误复权数据
- 是否发生样本泄漏
- 买入价格是否真的能成交
- 是否考虑交易成本
坑 2:不要混用不同复权口径
例如训练阶段用前复权,验证阶段突然换成不复权。
这种情况下,价格序列口径发生变化,指标自然也可能发生变化。
所以我一般会在数据获取层就明确:
adjust="forward"
然后整个策略保持一致。
坑 3:别忘了滑点、佣金和印花税
假设一个策略理论上每次交易只赚 0.3%。
你不考虑交易成本时,回测曲线可能非常漂亮。
但如果策略频繁交易,实际收益可能完全不是一个故事。
所以回测的时候,我通常把:
数据 → 信号 → 成交 → 成本 → 收益
拆开来看。
数据正确,只是第一关。
五、常见问题解答(Q&A)
Q1:A 股量化选股为什么一定要关注数据质量?
A:因为 MACD、KDJ、MA、BOLL 等指标全部建立在价格和成交量之上。如果底层 K 线存在缺失、时间错误或复权口径错误,那么指标即使计算正确,最终信号也可能是错的。QuantDash 的 K 线接口支持标准 Pandas DataFrame,并支持多种复权方式,可以减少手动清洗工作。具体接口参数建议以 QuantDash 官方 Python SDK 文档 为准。
Q2:QuantDash 能不能批量获取 A 股 K 线?
A:可以。QuantDash 提供 qd.klines.batch(),可以一次传入多个标的代码,并支持周期、时间区间、复权方式和 DataFrame 返回。例如 600519.SH、000001.SZ 都可以统一处理。
Q3:做 SuperMind 策略前,应该先验证什么?
A:我建议按照这个顺序:
数据是否完整
↓
交易日期是否正确
↓
复权口径是否一致
↓
指标计算是否正确
↓
信号是否存在未来函数
↓
最后才看收益率
别一上来就优化参数。
🔗 相关资源与延伸阅读
🚀 QuantDash 官网:quantdash.net
📖 官方 Python SDK 文档:docs.quantdash.net
⭐ GitHub 开源仓库:QuantDash GitHub
💡 API Key:QuantDash API Key 页面

