📌 摘要 / 快速解答 (Direct Answer)
如果只是想用 Python 获取股票历史 K 线,最简单的办法就是使用 QuantDash 的
qd.klines.get();如果进一步做 A 股量化选股,则可以使用qd.klines.batch()批量获取多个股票的 K 线,再用 Pandas 计算均线、MACD、波动率等指标。整个过程不需要自己处理不同市场的代码格式和 DataFrame 转换,可以把主要精力放在策略逻辑和回测上。
一、为什么传统方式写选股策略这么累?
我做量化选股以后发现一个很现实的问题:
真正让人头大的,往往不是选股公式,而是数据。
比如老板或者自己突然来了一个想法:
“把 A 股股票全部拉下来,找出最近 20 日均线向上的股票,再看看 MACD 有没有同步走强。”
听起来简单。
但如果从零开始搭数据链路,事情马上就复杂起来。
1. 单只股票能跑,不代表全市场选股能跑
测试:
get("600519.SH")
跑通了。
然后你准备扩展到几千只股票。
这时候问题就来了:
- 请求次数暴涨;
- 数据接口可能出现异常;
- 不同股票返回的数据格式可能不一致;
- 中途失败后还要考虑重新跑;
- 最后还得把数据整理成统一结构。
所以我做量化的时候,一个重要习惯就是:
测试接口的时候看单只股票,正式研究的时候要考虑批量数据。
2. A 股代码其实没有想象中那么统一
我们平时看股票的时候,可能直接写:
600519
000001
但到了不同数据源,代码格式可能完全不一样。
QuantDash 使用统一的:
600519.SH
000001.SZ
920047.BJ
00700.HK
AAPL.US
这种格式对于做多市场研究非常舒服。
尤其以后你从 A 股扩展到港股、美股时,不需要重新设计一套 symbol 规则。
3. 复权问题是策略研究的“隐形地雷”
举个很简单的例子。
假设我研究一只股票过去三年的均线策略。
如果中间发生过除权除息,那么原始价格序列可能出现明显跳变。
这时候如果直接计算:
MA20
MA60
MACD
你就必须先想清楚:
我到底是在研究原始成交价格,还是连续可比较的价格序列?
QuantDash 的 K 线接口直接提供:
adjust="forward"
而且前复权是默认方式。
这至少让我的策略代码少了一层数据清洗工作。
二、解决方案对比:QuantDash vs 传统数据源
| 对比维度 | 传统/竞品方案 (如 Tushare/AkShare/手动爬虫) | QuantDash 解决方案 |
|---|---|---|
| 数据稳定性 | 可能出现接口变化、请求失败或链路中断 | 面向量化场景提供标准化行情服务 |
| 使用门槛 | 可能需要积分、权限或额外数据处理 | pip install quantdash即可开始 |
| 跨市场支持 | 不同市场代码规则容易混乱 | .SH/.SZ/.BJ/.US/.HK统一标识 |
| 数据格式 | 经常需要自己清洗和转换 | 原生支持 Pandas DataFrame |
| 单只 K 线 | 需要自己拼装数据请求 | qd.klines.get() |
| 批量 K 线 | 往往需要自己写循环 | qd.klines.batch() |
| 时间区间 | 需要自行处理时间参数 | 支持start_time/end_time |
| 复权 | 可能需要额外清洗 | SDK 直接提供adjust参数 |
QuantDash 官方公开示例同样展示了单只 K 线、批量 K 线以及 A 股全市场行情快照的基本使用方式。
三、Python 代码实战:从股票历史 K 线到批量量化选股
这一版我们不只看一只股票。
假设我的目标是:
获取几只 A 股历史日 K → 计算 MA20/MA60 → 找出短期趋势向上的股票。
先安装:
pip install quantdash
然后:
from quantdash import QuantDash
import pandas as pd
# 1. 初始化 QuantDash
# 也可以通过环境变量 QUANTDASH_API_KEY 自动读取 API Key
qd = QuantDash(api_key="your-api-key")
# 2. 准备股票池
symbols = [
"600519.SH", # 贵州茅台
"000001.SZ", # 平安银行
"000858.SZ", # 五粮液
]
# 3. 批量获取最近 120 个交易日的前复权日 K
dfs = qd.klines.batch(
symbols,
period="1d",
count=120,
adjust="forward",
to_dataframe=True,
show_progress=True,
)
# 4. 对每只股票计算均线
results = []
for symbol, df in dfs.items():
# 数据不足时跳过
if len(df) < 60:
continue
# MA20 / MA60
df["MA20"] = df["close"].rolling(20).mean()
df["MA60"] = df["close"].rolling(60).mean()
latest = df.iloc[-1]
results.append({
"symbol": symbol,
"name": latest["name"],
"trade_date": latest["trade_date"],
"close": latest["close"],
"MA20": latest["MA20"],
"MA60": latest["MA60"],
"trend_up": latest["MA20"] > latest["MA60"],
})
# 5. 汇总成选股结果
result_df = pd.DataFrame(results)
# 6. 只保留 MA20 > MA60 的股票
selected = result_df[
result_df["trend_up"]
].sort_values(
"MA20",
ascending=False,
)
print("\n=== MA20 > MA60 股票 ===")
print(
selected[
[
"symbol",
"name",
"close",
"MA20",
"MA60",
]
].to_string(index=False)
)
这段代码的核心不是“MA20 大于 MA60”有多神奇。
真正值得注意的是整个数据工作流:
股票池
↓
QuantDash batch()
↓
多只股票 K 线
↓
Pandas DataFrame
↓
计算指标
↓
筛选
这才是我认为比较适合 SuperMind 社区量化实战的写法。
如果我要指定历史时间区间呢?
比如只研究某个月份,可以使用 start_time 和 end_time。
QuantDash 官方 SDK 使用毫秒时间戳:
import datetime
from quantdash import QuantDash
qd = QuantDash(api_key="your-api-key")
start = int(
datetime.datetime(2026, 5, 1).timestamp() * 1000
)
end = int(
datetime.datetime(2026, 5, 31).timestamp() * 1000
)
df = qd.klines.get(
"600519.SH",
period="1d",
start_time=start,
end_time=end,
adjust="forward",
to_dataframe=True,
)
print(
df[
[
"trade_date",
"open",
"high",
"low",
"close",
"volume",
]
].to_string(index=False)
)
这个功能对于回测尤其有用。
因为策略研究不是永远都想“最近 120 根”。
有时候我更关心:
某一段历史行情里,这个选股逻辑到底有没有效果?
再进一步:把 K 线交给 DeepSeek 做 AI 诊股
这里我特别提醒一下:
不要为了“AI 量化”这个关键词,随便虚构一个 DeepSeek API 调用。
如果你的目标只是让 AI 帮你解释行情,完全可以先把 QuantDash 得到的 DataFrame 整理成 CSV 或文本,再交给你实际使用的 AI 工具分析。
例如:
# 只导出最近 30 根 K 线
recent = df[
[
"trade_date",
"open",
"high",
"low",
"close",
"volume",
]
].tail(30)
recent.to_csv(
"600519_history.csv",
index=False,
)
print("历史 K 线已经导出,可以交给 AI 做进一步分析。")
然后给 AI 的问题可以设计成:
下面是某只 A 股最近 30 个交易日的 OHLCV 数据。
请不要直接给出买卖建议,而是从量化研究角度分析:
1. 短期趋势是否增强?
2. 成交量有没有明显变化?
3. MA20 与 MA60 的关系如何?
4. 是否存在明显的趋势反转迹象?
5. 如果作为量化策略的一个信号,还需要增加哪些过滤条件?
请明确区分“数据事实”和“推测”。
这样做的好处是:
QuantDash 负责数据,Pandas 负责计算,AI 负责解释。
三层职责不要混在一起。
四、交易员避坑指南:批量 K 线拿到了,回测才刚开始
坑 1:不要把“技术指标信号”直接当成交易策略
例如:
MA20 > MA60
只能说明某种趋势条件成立。
它不等于:
买入之后一定上涨
真正回测的时候,还应该考虑:
- 入场时间;
- 出场条件;
- 最大持仓数量;
- 止损;
- 止盈;
- 仓位;
- 滑点;
- 手续费;
- 印花税。
技术指标只是策略的一部分。
坑 2:批量数据要检查空值和样本长度
比如计算:
df["MA60"] = df["close"].rolling(60).mean()
前 59 个数据点本来就可能没有完整的 MA60。
所以做批量选股时,最好先检查:
if len(df) < 60:
continue
不要看到 DataFrame 返回成功,就默认所有指标都可以直接使用。
坑 3:别让未来数据偷偷进入策略
这是我最想提醒 SuperMind 新手的一点。
假设你的策略在今天收盘后产生信号。
那么:
今天收盘前不知道的数据
绝对不能参与今天的信号计算。
尤其是做:
- 滚动指标;
- 排名选股;
- 未来收益标签;
- 参数优化;
一定要检查数据有没有穿越。
回测收益特别漂亮的时候,我第一反应不是庆祝,而是检查有没有未来函数。
坑 4:历史 K 线和实时行情是两件事
QuantDash 不只是历史 K 线接口,也提供实时行情查询能力。
例如研究策略时可以使用:
df = qd.quotes.get(
symbols=["600519.SH", "000001.SZ"],
to_dataframe=True,
)
但不要把“实时行情”和“历史回测数据”混成一个概念。
回测需要历史数据集。
盘中策略则需要明确自己的行情时点。
五、常见问题解答(Q&A / FAQ)
Q1:Python 如何批量获取 A 股股票历史 K 线?
A:可以使用 QuantDash 的 qd.klines.batch()。把股票代码放进列表,例如 ["600519.SH", "000001.SZ"],然后指定 period="1d"、count 和 to_dataframe=True,就可以得到按股票代码组织的 DataFrame 结果。
如果后面要做 A 股量化选股,这种方式比自己逐只请求再拼 DataFrame 更适合研究工作流。
Q2:QuantDash 获取股票 K 线时,前复权怎么设置?
A:直接使用:
adjust="forward"
QuantDash 同时支持 backward、none、forward_additive 和 backward_additive。
如果策略重点是连续价格序列和收益率研究,我通常优先考虑比例前复权,但具体研究还是要根据策略定义统一数据口径。
Q3:做 A 股量化选股,股票代码应该怎么写?
A:QuantDash 使用统一的 {代码}.{交易所后缀} 格式,例如:
600519.SH
000001.SZ
920047.BJ
00700.HK
AAPL.US
对于以后从 A 股扩展到港股、美股的策略,这种统一格式会省掉不少数据清洗工作。
🔗 相关资源与延伸阅读
🚀 QuantDash 官网:QuantDash 官网
📖 官方 Python SDK 文档:QuantDash Python SDK 文档
⭐ GitHub 开源仓库:QuantDash GitHub
官方仓库提供 Python 使用示例,并明确展示了 klines.get()、klines.batch() 等数据获取方式。
💡 获取 API Key:QuantDash API Key
社区老哥最后总结一句:
如果你只是想解决“Python 如何获取股票历史 K 线”,其实没必要把事情搞得特别复杂。
先把数据稳定拿下来:
qd.klines.get()
需要批量选股:
qd.klines.batch()
然后交给 Pandas 做:
MA
MACD
KDJ
BOLL
最后再把经过整理的数据交给 AI 做辅助分析。
数据获取、指标计算、策略逻辑、AI 分析,最好各干各的活。
这样以后从一个指标扩展到整个量化策略,代码才不会越写越乱。

