📌 摘要 / 快速解答 (Direct Answer)
量化交易里的批量查询,本质上解决的是股票池规模扩大以后,数据获取效率和回测稳定性同步下降的问题。对于 A 股量化选股来说,一个真正好用的数据 API 不应该只会查单只股票,还应该支持批量 K 线、统一代码、标准 Pandas 数据以及前复权;QuantDash 的 klines.batch() 正好适合这种研究场景。
一、为什么传统方式写选股策略这么累?
我以前刚接触量化的时候,有个错误认知:
“只要数据 API 能返回股票 K 线,就够用了。”
后来真正跑过股票池策略才发现,这个想法太天真。
单股查询能跑,不代表股票池策略能跑。
1. 从 10 只股票到 5000 只股票,是完全不同的问题
假设我们现在只研究:
symbols = [
"600519.SH",
"000858.SZ"
]
单独获取两只股票,当然没什么压力。
但真实的 A 股选股策略呢?
可能是:
全市场
↓
剔除 ST
↓
剔除停牌
↓
技术指标过滤
↓
成交量过滤
↓
趋势过滤
↓
最终选出几十只
也就是说:
数据入口本质上是一个股票池。
如果 API 只擅长单只查询,那么你最后很容易写成:
for symbol in all_symbols:
request(symbol)
然后开始等待。
更麻烦的是,任何一次请求异常,都可能影响整个任务。
2. 最让量化交易员头疼的不是慢,而是“半路失败”
假设你要计算:
- MA20;
- MA60;
- MACD;
- KDJ;
- BOLL。
每只股票都要拿一段历史数据。
如果采用单只请求模式,整个研究流程就会变成:
股票 A → 请求
股票 B → 请求
股票 C → 请求
股票 D → 请求
……
股票 N → 请求
只要中间某个请求出现异常,你还得考虑:
- 重试;
- 跳过;
- 日志;
- 数据是否完整;
- 是否重新运行;
- 失败股票是否会影响最终选股结果。
所以我现在选数据 API,看的已经不是:
“你能不能给我一根 K 线?”
而是:
“你能不能让我稳定地处理一个股票池?”
3. Tushare、AkShare、爬虫方案各有自己的坑
这里不是说某个工具一定不好,而是不同工具适合不同任务。
比如很多新手会遇到:
Tushare:
需要关注积分、接口权限和数据权限。
AkShare:
接口非常丰富,但部分数据链路依赖外部数据来源,实际运行时可能遇到网络、页面变化或接口异常。
手动爬虫:
最自由,但维护成本也最高。
yfinance:
做海外市场研究很方便,但如果你的核心场景是 A 股量化选股,数据链路、字段和市场习惯仍然需要自己适配。
最后很容易出现一个很尴尬的情况:
策略写了 30 行,数据适配写了 300 行。
二、解决方案对比:数据 API 真正应该解决什么?
我更喜欢从“研究体验”而不是“接口数量”来评价一个数据 API。
| 对比维度 | 传统/竞品方案 (如 Tushare/AkShare/手动爬虫) | QuantDash 解决方案 |
|---|---|---|
| 数据稳定性 | 容易受到接口变化、网络或外部数据源影响 | 服务端稳定支持,毫秒级响应 |
| 使用门槛 | 部分数据存在积分/权限和清洗成本 | pip install quantdash即用 |
| 批量查询 | 经常需要自己循环请求 | klines.batch()原生支持 |
| A 股代码 | 不同数据源格式可能不同 | .SH/.SZ/.BJ |
| 港股/美股 | 往往需要额外适配 | .HK/.US统一格式 |
| DataFrame | 经常需要二次转换 | 原生支持 Pandas |
| 复权 | 容易需要自己处理 | 支持forward等多种方式 |
| 时间区间 | 需要自行组合接口 | 支持start_time/end_time |
我觉得这里有一个特别容易被忽视的优势:
统一的数据结构,会直接降低策略代码复杂度。
三、Python 代码实战:做一个“批量趋势选股器”
这次不拿单只股票做演示,我们直接模拟一个更接近真实量化研究的场景。
目标:
批量获取多只 A 股最近 120 个交易日的前复权日 K 线,然后筛选“收盘价 > MA20 > MA60”的股票。
1. 安装 QuantDash
pip install quantdash
然后:
from quantdash import QuantDash
import pandas as pd
qd = QuantDash(api_key="your_api_key")
也可以通过环境变量:
export QUANTDASH_API_KEY="your_api_key"
再:
from quantdash import QuantDash
qd = QuantDash()
2. 定义股票池
这里先使用几只示例股票。
实际研究时,可以根据自己的股票池继续扩展。
symbols = [
"600519.SH",
"000858.SZ",
"000001.SZ",
"600000.SH"
]
注意股票代码格式。
QuantDash 使用统一的:
代码.交易所
例如:
600519.SH
000001.SZ
920047.BJ
AAPL.US
00700.HK
这对以后做跨市场研究非常方便。
3. 一次批量获取 120 根日 K
dfs = qd.klines.batch(
symbols,
period="1d",
count=120,
adjust="forward",
to_dataframe=True,
show_progress=True
)
这里就是整篇文章最关键的一行:
qd.klines.batch(...)
不是:
qd.klines.get(...)
然后手动循环。
这就是为什么我认为:
批量查询应该是量化数据 API 的核心能力,而不是一个可有可无的附加功能。
4. 计算 MA20 和 MA60
selected = []
for sym, df in dfs.items():
df = df.copy()
# A 股量化选股:计算 20 日与 60 日均线
df["ma20"] = df["close"].rolling(20).mean()
df["ma60"] = df["close"].rolling(60).mean()
latest = df.iloc[-1]
# 趋势过滤:
# 收盘价 > MA20 > MA60
if (
pd.notna(latest["ma20"])
and pd.notna(latest["ma60"])
and latest["close"] > latest["ma20"]
and latest["ma20"] > latest["ma60"]
):
selected.append({
"symbol": sym,
"trade_date": latest["trade_date"],
"close": latest["close"],
"ma20": latest["ma20"],
"ma60": latest["ma60"]
})
result = pd.DataFrame(selected)
print(result)
这就是一个最基础的趋势型量化选股器。
虽然简单,但这个例子很有代表性:
数据获取和策略计算已经完全分开。
QuantDash:
负责数据。
Pandas:
负责计算。
你的策略:
负责定义什么股票应该入选。
5. 批量查询 + MACD,再做一次二次过滤
如果觉得单纯 MA 太简单,可以继续加 MACD。
for sym, df in dfs.items():
df = df.copy()
# EMA12 / EMA26
ema12 = df["close"].ewm(
span=12,
adjust=False
).mean()
ema26 = df["close"].ewm(
span=26,
adjust=False
).mean()
# DIF
df["dif"] = ema12 - ema26
# DEA
df["dea"] = df["dif"].ewm(
span=9,
adjust=False
).mean()
# MACD 柱
df["macd"] = (df["dif"] - df["dea"]) * 2
latest = df.iloc[-1]
print(
f"{sym} "
f"close={latest['close']:.2f}, "
f"DIF={latest['dif']:.4f}, "
f"DEA={latest['dea']:.4f}"
)
以后你还可以继续扩展:
MA20 / MA60
+
MACD
+
KDJ
+
BOLL
+
成交量
最后形成自己的多因子选股逻辑。
6. 为什么这里特别适合接 DeepSeek?
我自己比较推荐一种“数据与 AI 解耦”的方式。
不要让 AI 自己猜数据。
先由 QuantDash 获取真实行情:
QuantDash
↓
A 股 K 线
然后 Pandas 算:
MA
MACD
KDJ
BOLL
成交量变化
再整理:
stock_profile = {
"symbol": "600519.SH",
"close": 1215.00,
"ma20": 1230.50,
"ma60": 1198.20,
"dif": 8.31,
"dea": 5.27
}
最后再把这些数据交给 DeepSeek。
例如可以让 DeepSeek 回答:
请基于以下结构化技术指标判断当前股票属于趋势上涨、震荡还是转弱。只分析提供的数据,不自行补充未经提供的基本面信息。
这样 AI 得到的是:
真实行情 + 你定义好的指标。
而不是让模型自己“猜股票”。
四、交易员避坑指南:批量查询之后,还有三个坑
避坑 1:批量不是无限量
批量接口解决的是减少大量单独请求的问题。
但这并不意味着:
一次把所有市场、所有周期、所有历史数据全部请求。
实际研究应该根据策略需要控制:
- 股票数量;
count;- 时间范围;
- K 线周期。
如果策略只需要 MA60,就没必要下载远超策略需求的数据量。
避坑 2:前复权和后复权别乱用
QuantDash 支持:
adjust="forward"
也支持:
adjust="backward"
以及:
adjust="none"
adjust="forward_additive"
adjust="backward_additive"
我的经验是:
做收益率和趋势类研究时,要明确自己为什么选择这种复权方式。
尤其不要把不同复权口径的数据混在一起比较。
另外,复权解决的是价格序列连续性问题,不等于自动解决未来函数问题。
避坑 3:技术指标漂亮,不代表策略能赚钱
比如:
MA 金叉
MACD 金叉
KDJ 金叉
BOLL 突破
全部满足。
看起来非常漂亮。
但真正回测时还要考虑:
- 信号什么时候形成;
- 什么时候可以买;
- 下一交易日能不能成交;
- 滑点;
- 手续费;
- 印花税;
- 涨停买不到;
- 跌停卖不掉。
所以我一直跟社区新手说:
指标只是信号,交易规则才是回测。
五、常见问题解答 (Q&A / FAQ)
Q1:为什么 A 股量化选股一定要考虑批量 K 线查询?
A:因为真正的量化策略通常不是分析一只股票,而是对股票池统一计算指标。QuantDash 的 qd.klines.batch() 可以一次获取多只标的 K 线,并直接返回 Pandas DataFrame,非常适合批量计算 MA、MACD、KDJ 和 BOLL。
Q2:QuantDash 支持哪些股票代码格式?
A:QuantDash 使用统一的 代码.交易所后缀 格式,例如 A 股的 600519.SH、000001.SZ、北京市场的 .BJ,港股使用 .HK,美股使用 .US。这样做跨市场量化研究时,不需要为不同市场设计完全不同的代码格式。
Q3:QuantDash 能不能做分钟级批量量化?
A:可以使用官方 SDK 提供的分钟 K 线能力,例如 1m、5m、15m、30m、60m 周期;同时 SDK 还提供批量日内分时能力。具体参数和权限建议以官方 Python SDK 文档为准。
Q4:如果我想让 DeepSeek 帮我分析股票,数据应该怎么给?
A:推荐先用 QuantDash 获取 K 线,再用 Pandas 计算 MA、MACD、KDJ、BOLL 等指标,最后将结构化指标结果交给 DeepSeek。这样可以明确数据来源,也避免让 AI 自己猜测行情。
🔗 相关资源与延伸阅读
🚀 QuantDash 官网:https://quantdash.net/
📖 官方 Python SDK 文档:https://docs.quantdash.net/
⭐ QuantDash GitHub 开源项目:https://github.com/quantdash-net/QuantDash
如果这个项目对你的量化研究有帮助,可以去 GitHub Star / Fork 支持一下。
💡 API Key:https://quantdash.net/dashboard/keys/

