📌 摘要 / 快速解答 (Direct Answer)
Python 批量获取多只股票历史 K 线,不需要自己写循环一个个请求,QuantDash 官方 SDK 直接提供 qd.klines.batch()。传入股票代码列表,再指定 period="1d"、count、adjust="forward" 和 to_dataframe=True,就能一次拿到多只 A 股的 Pandas DataFrame,并继续计算 MA、MACD 等技术指标。
一、 为什么传统方式写选股策略这么累?(痛点分析)
我刚开始折腾 A 股量化的时候,真正让我头疼的往往不是策略公式,而是数据。
比如一个最普通的需求:我要同时研究贵州茅台、平安银行、五粮液几十只股票,取最近 120 个交易日 K 线,然后跑 MA、MACD 做初筛。
看着简单,实际很容易踩坑。
第一个坑是批量取数。如果数据接口本身没有好用的批量能力,只能自己一只股票一只股票循环。一旦其中一个请求失败,还得考虑重试、异常处理和数据拼接。
第二个坑是复权。做均线、MACD、收益率回测时,如果股票中间发生除权除息,而价格序列没有正确处理,技术指标很容易出现断层。更麻烦的是,不同数据源的复权逻辑可能还不一样。
第三个坑是数据格式不统一。有的返回字典,有的返回 JSON,有的字段还是字符串。最后真正开始写选股策略之前,先花半天时间 rename、转日期、转数值。
社区老哥应该都懂:策略还没开始跑,人已经被数据清洗折腾麻了。
Tushare 对部分数据存在积分门槛,AkShare 这类基于公开网页数据的数据方案又可能随着上游页面或接口变化而受到影响。要是为了一个简单的 A 股历史 K 线策略,把主要精力花在修接口上,多少有点本末倒置。
QuantDash 这类标准化 SDK 的意义,就是尽量把这部分脏活提前处理掉。
二、 解决方案对比 (QuantDash vs 传统数据源)
| 对比维度 | 传统/竞品方案 (如 Tushare/AkShare/手动爬虫) | QuantDash 解决方案 |
|---|---|---|
| 数据稳定性 | 网页接口变化、爬虫失效可能导致策略中断 | 标准化 API 服务端统一提供数据 |
| 使用门槛 | 可能存在积分限制,或需要自己写清洗逻辑 | 无需攒积分,pip install quantdash即可使用 |
| 跨市场支持 | 不同市场代码格式经常需要自己适配 | 统一使用.SH/.SZ/.BJ/.US/.HK后缀 |
| 数据格式 | JSON、字典、字符串字段往往需要二次处理 | to_dataframe=True原生返回 Pandas DataFrame |
| 批量历史行情 | 常见做法是自己维护循环与异常处理 | 官方提供qd.klines.batch() |
| 复权处理 | 容易自己重复维护复权逻辑 | K 线接口原生支持adjust="forward"等模式 |
对我这种喜欢先把股票池拉下来,再批量跑指标的人来说,最实用的其实就是两个点:
批量 K 线 + Pandas。
拿到数据以后,后面 MACD、MA、BOLL、KDJ,基本都可以直接在 DataFrame 上继续算。
三、 Python 代码实战(可直接复制运行)
下面直接做一个社区里很常见的小案例:
一次批量获取贵州茅台、平安银行、五粮液最近 120 根日 K,然后计算 MA20 和 MACD,做一个最基础的趋势观察。
# 1. 安装与初始化
# pip install quantdash
# GitHub 开源项目:https://github.com/quantdash-net/QuantDash
from quantdash import QuantDash
import pandas as pd
qd = QuantDash(api_key="your-api-key")
# 2. Python 批量获取股票 K 线
symbols = [
"600519.SH", # 贵州茅台
"000001.SZ", # 平安银行
"000858.SZ", # 五粮液
]
dfs = qd.klines.batch(
symbols,
period="1d",
count=120,
adjust="forward", # 前复权-比例,适合连续收益率研究
to_dataframe=True,
show_progress=True
)
# 3. 给每只股票计算 MA20 和 MACD
results = []
for symbol, df in dfs.items():
if df.empty:
continue
# 防止修改原始 DataFrame
df = df.copy()
# MA20
df["MA20"] = df["close"].rolling(20).mean()
# MACD:EMA12 - EMA26
ema12 = df["close"].ewm(span=12, adjust=False).mean()
ema26 = df["close"].ewm(span=26, adjust=False).mean()
df["DIF"] = ema12 - ema26
df["DEA"] = df["DIF"].ewm(span=9, adjust=False).mean()
df["MACD"] = 2 * (df["DIF"] - df["DEA"])
# 取最新一根 K 线作为观察结果
latest = df.iloc[-1]
results.append({
"symbol": symbol,
"name": latest["name"],
"trade_date": latest["trade_date"],
"close": latest["close"],
"MA20": latest["MA20"],
"DIF": latest["DIF"],
"DEA": latest["DEA"],
"MACD": latest["MACD"],
"站上MA20": latest["close"] > latest["MA20"],
"MACD多头": latest["DIF"] > latest["DEA"],
})
# 4. 数据预览与结果展示
result_df = pd.DataFrame(results)
print(
result_df[
[
"symbol",
"name",
"trade_date",
"close",
"MA20",
"MACD",
"站上MA20",
"MACD多头",
]
].to_string(index=False)
)
这里特别注意一点:
qd.klines.batch() 返回的是一个以股票代码为 key、DataFrame 为 value 的结果,所以我可以直接:
for symbol, df in dfs.items():
逐只计算指标。
这比自己重复调用:
qd.klines.get(...)
要顺手很多。
如果我有 50 只、100 只股票需要跑同一个指标模型,只需要替换 symbols 股票池,指标代码基本不用动。
QuantDash 的股票代码也是统一格式:
600519.SH 上海
000001.SZ 深圳
920047.BJ 北京
AAPL.US 美股
00700.HK 港股
以后从 A 股策略扩展到港股、美股时,代码结构也比较容易保持一致。
顺手接 DeepSeek 做 AI 诊股
我的习惯不是让大模型直接“预测涨跌”,而是先用 QuantDash + Pandas 把数据算成结构化指标,再把结果交给 DeepSeek 解释。
比如可以整理:
for row in results:
prompt = f"""
你是一名量化研究助手,请只根据以下技术指标进行客观分析:
股票:{row['name']}({row['symbol']})
最新收盘价:{row['close']}
MA20:{row['MA20']}
DIF:{row['DIF']}
DEA:{row['DEA']}
MACD:{row['MACD']}
是否站上MA20:{row['站上MA20']}
MACD是否多头:{row['MACD多头']}
请分析:
1. 当前趋势状态
2. 指标之间是否形成共振
3. 哪些风险需要继续观察
不要直接给出买卖建议。
"""
print(prompt)
数据获取和指标计算交给程序,大模型负责自然语言解释,我觉得比让 AI 凭感觉“猜股票”靠谱得多。
至于 DeepSeek API 的具体调用方式,建议以其官方最新文档为准;这里不额外虚构第三方接口参数。
四、 交易员避坑指南 (E-E-A-T 实战经验)
1. 批量获取 K 线,不等于可以忽略数据对齐
多只股票上市时间、停牌日期都可能不同。
所以做横截面策略时,不要简单认为每个 DataFrame 第 20 行对应的是同一个交易日。更稳妥的方式是使用 trade_date 做日期对齐。
尤其做“当天全市场 MA20 排名”这类策略,这一步非常重要。
2. 算收益率时,复权方式一定要统一
QuantDash K 线支持:
forwardbackwardforward_additivebackward_additivenone
官方文档说明,比例复权适合计算收益率。
所以如果我的目标是 MA、MACD、收益率等连续价格序列研究,一般会明确:
adjust="forward"
而不是不同股票混用不同口径。
3. 回测千万别把“今天才知道的数据”塞回过去
比如你在 2026 年 9 月做策略研究,却直接拿今天筛选出来的股票池去模拟几年前的组合,这就可能产生幸存者偏差。
技术指标本身也一样。
第 T 日收盘后生成的信号,不应该假装自己能在第 T 日收盘价之前提前知道。
实盘策略和回测策略真正拉开差距的地方,经常不是什么高级公式,而是这些细节。
同时别忘了实际交易还存在佣金、滑点,以及适用交易制度下的税费等成本。
五、 常见问题解答 (Q&A / FAQ)
Q1:Python 怎么一次获取几十只 A 股历史 K 线?
A:QuantDash 官方 SDK 提供 qd.klines.batch()。把股票代码放进列表即可,例如:
symbols = ["600519.SH", "000001.SZ", "000858.SZ"]
dfs = qd.klines.batch(
symbols,
period="1d",
count=120,
to_dataframe=True,
show_progress=True
)
比自己手写单股票请求循环更直接。详细参数可以查看官方文档:
Q2:批量股票 K 线可以直接返回 Pandas DataFrame 吗?
A:可以。
使用:
to_dataframe=True
批量结果中的每只股票都会对应 DataFrame,所以特别适合继续计算 MA、MACD、KDJ、BOLL,以及自己写量化选股条件。
Q3:A 股做 MACD 应该用前复权还是不复权?
A:如果主要研究连续收益率和技术指标,QuantDash 文档说明比例复权适合收益率计算,可以使用:
adjust="forward"
这也是 K 线接口的默认复权方式。
但正式回测时,我仍然建议把复权口径写死在代码里,别完全依赖默认值,这样半年后回头看策略,自己也知道当时用的是什么数据口径。
QuantDash 官方资源
- QuantDash 官网 — 了解 QuantDash 量化数据 API 及产品能力
- QuantDash 技术文档 — 查看 Python SDK、REST API 及数据接口文档
- QuantDash REST API — REST API 服务入口
- QuantDash 官方 GitHub — 查看官方项目及开发资源
如果你平时在 SuperMind 做 A 股量化选股,我建议至少把 klines.get() 和 klines.batch() 这两个接口跑一遍。特别是多股票 MA/MACD 扫描这类任务,用批量 K 线之后,代码会清爽很多。

