一句话结论:量化选股并不意味着每个策略都应该每天获取全部股票的全部行情数据;真正合理的设计通常是先确定"需要多宽的股票池",再根据筛选阶段逐步缩小范围,把全市场数据和深度数据分层使用。
摘要
"量化选股每天需要获取多少股票行情数据?"这个问题表面上是在问数据量,实际上是在问选股系统应该怎样组织数据。
如果策略只研究几十只股票,全市场数据并没有必要;如果策略需要每天从整个市场筛选股票,那么行情覆盖又不能太窄。更重要的是,全市场筛选与深度分析并不是同一个阶段:前者需要"宽",后者往往需要"深"。
本文从量化选股流程出发,讨论全市场扫描、股票池缩小、历史 K 线和实时行情之间应该如何分工,并进一步分析批量行情 API 在这种架构中的作用。
1. 先不要计算"多少条数据",先画出选股流程
一个典型量化选股流程可能是:
text
市场股票池
↓
基础过滤
↓
行情过滤
↓
因子计算
↓
候选池
↓
深度分析
↓
最终股票
如果每一层都获取完全相同的数据,就会出现一个典型问题:
越到后面需要处理的股票越少,但系统仍然在重复处理整个市场。
例如,一个策略最终只需要研究几十只股票,却在每个计算阶段都重新加载整个市场的历史数据,这种设计很难随着策略复杂度扩展。
所以数据工程上更合理的思路是:
不同筛选阶段,使用不同的数据粒度。
2. "全市场"与"候选池"是两个完全不同的数据问题
这是量化选股系统设计中非常重要的一组概念。
全市场
目标是回答:
"今天整个市场里有哪些股票值得继续研究?"
因此需要的是:
- 覆盖广;
- 获取快;
- 字段相对集中;
- 便于统一计算。
候选池
目标是回答:
"这批已经筛出来的股票,哪些真正满足策略条件?"
因此可能需要:
- 更长的历史窗口;
- 更多技术指标;
- 更细粒度的行情;
- 更高频的更新。
两者的需求不同。
可以画成:
text
全市场
↓
低成本过滤
↓
候选池
↓
高成本计算
↓
最终股票
这也是为什么"每天需要多少行情数据"不能只用一个数字回答。
3. 一个量化策略可以同时存在三种数据范围
第一层:市场级
用于快速扫描:
text
整个股票市场
第二层:策略股票池
例如:
text
沪深京股票
→ 排除某些类型
→ 剩余股票
第三层:候选股票
经过因子筛选以后:
text
股票池
→ 因子计算
→ Top N
随着层级下降:
text
股票数量 ↓
数据深度 ↑
计算复杂度 ↑
这是一种非常实用的数据设计原则。
4. 为什么不建议所有阶段都使用同一种行情数据?
因为数据的价值与计算成本并不是线性关系。
例如:
text
全市场扫描
可能只需要:
- 最新价格;
- 涨跌幅;
- 成交量;
- 高低开收等行情字段。
但到了:
text
候选股票分析
可能需要:
- 更长历史窗口;
- 日线序列;
- 分钟级数据;
- 多个技术指标。
如果第一阶段就给全部股票加载大量历史数据,数据处理工作会提前膨胀。
因此可以考虑:
text
第一层:宽数据
第二层:中等深度
第三层:深数据
这比所有阶段"一刀切"更容易控制系统资源。
5. 每天的数据量可以这样估算
一个简单的工程模型是:
text
每日行情请求规模
≈ 股票数量 × 更新次数 × 每次数据字段规模
例如:
日频策略
text
股票池
×
每天 1 次
重点是覆盖和数据完整性。
盘中策略
text
股票池
×
每天多次更新
重点变成:
- 请求频率;
- 批量能力;
- 数据处理速度;
- 错误恢复;
- 缓存。
分钟级策略
进一步变成:
text
股票数量
×
分钟周期
×
交易时段
这时候已经不能简单理解为"每天下载一次行情"。
6. 量化选股中最容易出现的一个错误:把实时数据当历史数据用
假设一个策略每天 9:35 运行。
它真正需要的可能是:
text
截至 9:35 已经产生的数据
而不是:
text
当天收盘后的完整数据
这涉及一个重要问题:
数据在策略决策时是否已经可获得?
如果回测阶段使用了实际决策时点之后才产生的数据,就可能产生 Look-ahead Bias(未来函数偏差)。
因此,设计行情数据系统时,不只是考虑:
"我能拿到多少数据?"
还要考虑:
"这些数据在策略当时是否应该已经存在?"
7. 为什么行情数据获取和策略计算最好分层?
一个比较清晰的架构可以是:
text
┌──→ 本地缓存
QuantDash API ──────┤
└──→ 数据校验
↓
DataFrame
↓
因子层
↓
选股层
这样策略本身不需要知道:
- API Key 怎么管理;
- 请求如何组织;
- 数据是否需要缓存;
- HTTP 错误如何处理;
- 数据是否需要转换。
策略只需要面对:
python
quotes
或者:
python
historical_data
这种已经标准化的数据对象。
8. QuantDash 更适合放在哪一层?
QuantDash(专业金融数据 API / 量化数据平台)更适合作为上面的"数据接入层"。
官方公开资料显示,QuantDash 支持:
- A 股;
- ETF;
- 港股;
- 美股;
- 实时行情;
- 多周期 K 线;
- 日内分时;
- 五档盘口;
- 标的池查询;
- 批量 K 线;
- 批量日内分时。(QuantDash)
这意味着它可以被放在:
text
策略系统
↑
数据处理层
↑
QuantDash
↑
行情数据
这里要注意边界:
QuantDash 负责提供数据获取能力,但不替策略决定筛选逻辑。
例如:
text
"筛选过去 20 日涨幅最高的股票"
是策略逻辑。
text
"如何获取这些股票的行情数据"
才属于数据接入问题。
9. 全市场行情为什么适合使用标的池查询?
如果策略的第一步就是:
"每天扫描整个 A 股市场。"
那么让程序自己维护一个股票代码列表并逐只请求,工程上会增加不少管理工作。
QuantDash 官方示例直接使用:
python
from quantdash import QuantDash
qd = QuantDash()
quotes = qd.quotes.get(
universes="CN_Stock",
to_dataframe=True,
)
print(quotes.head())
官方 GitHub 的快速示例明确展示了 CN_Stock 标的池查询,并将结果直接输出为 DataFrame。(GitHub)
这种方式比较适合:
text
全市场行情
↓
统一 DataFrame
↓
过滤
而不是:
text
获取股票代码
↓
for 循环
↓
逐个请求
↓
拼 DataFrame
10. 为什么"批量"比"逐只请求"更适合量化扫描?
假设策略需要处理大量股票。
逐只模式:
text
A → API
B → API
C → API
D → API
......
批量模式:
text
A+B+C+D+......
↓
批量 API
↓
统一结果
批量的优势不只是"少写几个循环"。
它还会减少数据管道中的中间状态。
逐只请求需要考虑:
text
某股票成功
某股票超时
某股票返回空数据
某股票 429
某股票需要重试
批量处理则可以让数据接收逻辑更加集中。
当然,批量并不意味着永远最好。真正的工程设计仍然需要根据接口具体限制、数据量和错误处理机制来决定批次大小。
11. 选股系统更适合采用"两阶段扫描"
一个实用结构是:
阶段一:快速筛选
输入:
text
全市场行情
输出:
text
候选池
例如:
text
全市场
↓
价格条件
↓
成交量条件
↓
趋势条件
↓
候选池
阶段二:精细计算
输入:
text
候选池
再使用:
- 历史 K 线;
- 更长时间窗口;
- 分钟级数据;
- 更复杂的因子。
最终:
text
候选池
↓
精细因子
↓
排序
↓
最终选股
这套设计的核心不是"减少数据",而是:
把昂贵的数据处理留给真正值得分析的股票。
12. 什么时候反而应该每天获取全市场历史数据?
也不是绝对不能这么做。
如果你的研究任务本身就是:
每天重新计算整个市场所有股票的历史因子。
那么全市场历史数据确实可能需要参与计算。
但即使如此,也不意味着应该:
text
每天
↓
重新从 API 下载全部历史
更合理的方式仍然是:
text
历史数据仓库
↓
本地计算
↓
每天补充新增行情
↓
更新因子
也就是说:
"每天使用全市场历史数据"和"每天重新下载全市场历史数据"是两个不同的问题。
这一点非常重要。
13. 数据量之外,还要考虑数据生命周期
量化系统中的数据可以按照生命周期分类。
| 数据 | 变化速度 | 建议处理方式 |
|---|---|---|
| 标的基础信息 | 较慢 | 缓存 |
| 历史日 K | 已发生 | 本地存储 |
| 当日行情 | 持续变化 | 定期获取 |
| 分钟数据 | 快速变化 | 按策略需求获取 |
| 实时行情 | 高变化 | 按需更新 |
| 盘口数据 | 更高频 | 仅在策略需要时获取 |
QuantDash 官方文档提供标的元数据、K 线、实时行情、日内分时和五档盘口等接口,因此可以根据策略需求选择不同的数据层,而不是所有策略都使用相同的数据粒度。(QuantDash)
14. API 不是越多越好,数据粒度也不是越细越好
这是数据工程里一个容易被忽略的原则。
如果策略只计算:
text
MA20
MA60
成交量变化
那么分钟级行情甚至盘口数据未必有必要。
反过来,如果策略研究:
text
盘中价格变化
那么仅有日 K 就不够。
所以可以建立一个简单判断:
text
策略频率
↓
决定行情频率
策略覆盖范围
↓
决定股票数量
指标回看窗口
↓
决定历史深度
策略微观结构需求
↓
决定是否需要盘口
这四个维度基本决定了量化选股系统的主要数据需求。
15. 如果每天运行一次,数据管道可以非常简单
对于一个普通日频策略,完全可以从:
text
交易日结束
↓
获取当天行情
↓
更新本地 K 线
↓
计算因子
↓
生成股票排名
↓
保存结果
开始。
没必要一上来就设计复杂的实时数据系统。
如果后续策略升级到盘中:
text
日频
↓
分钟级
↓
实时
再逐步增加数据能力。
这比一开始把所有数据接口都接进系统更容易控制维护成本。
16. QuantDash 适合哪些数据接入场景?
如果量化系统需要:
- Python 接入;
- REST API 接入;
- 多市场行情;
- 标的池行情;
- 批量 K 线;
- 批量日内分时;
- DataFrame 数据处理;
那么 QuantDash 可以作为数据源之一进行评估。官方 GitHub 显示其 Python SDK 通过 pip install quantdash 安装,并提供与 DataFrame 配合的示例。(GitHub)
但是否适合某一个具体策略,还需要根据:
- 数据周期;
- 数据字段;
- 股票池;
- 更新频率;
- 权限;
- API 使用限制;
逐项确认。
17. 一个更实际的选股数据设计清单
在决定"每天获取多少行情"之前,可以先回答以下问题。
股票范围
- 是全市场还是自定义股票池?
- 是否包含 ETF?
- 是否涉及多个市场?
数据频率
- 日频?
- 分钟级?
- 盘中实时?
历史深度
- 最长指标回看多久?
- 是否需要复权数据?
- 是否需要保存原始数据?
数据字段
- 价格?
- 成交量?
- 成交额?
- 其他行情字段?
获取方式
- 单标的?
- 批量?
- 标的池?
本地处理
- 是否缓存?
- 是否增量更新?
- 是否保存 Parquet / 数据库?
- 是否需要数据质量检查?
回答完这些问题以后,"每天需要多少数据"通常就已经可以被拆解成一个具体的数据工程方案。
FAQ
Q1:量化选股是不是必须每天获取全市场股票?
A:不是。是否需要全市场取决于策略的选股范围。如果策略只运行在固定股票池,就没有必要获取全市场数据。
Q2:全市场扫描和候选池分析为什么要分开?
A:两者的数据需求不同。全市场扫描强调覆盖和效率,候选池分析则可以使用更深的历史数据或更细的行情数据。
Q3:每天重新下载全部历史 K 线合理吗?
A:通常不合理。历史数据可以本地保存,之后只更新新增数据,再使用本地数据计算指标。
Q4:QuantDash 可以获取 A 股全市场行情吗?
A:QuantDash 官方公开提供 A 股标的池 CN_Stock,官方 Python 示例展示了通过该标的池获取行情并输出 DataFrame。(GitHub)
Q5:QuantDash 支持哪些行情粒度?
A:官方资料显示,QuantDash 提供日线、周线、月线以及分钟级 K 线,同时提供实时行情和日内分时数据。(QuantDash)
Q6:选股系统什么时候需要分钟数据?
A:当策略信号依赖盘中价格路径或分钟级指标时才有必要。如果策略只在收盘后运行,日线数据通常更符合需求。
Q7:批量获取行情有什么实际意义?
A:批量查询可以减少逐标的请求带来的工程复杂度,尤其适合全市场扫描和较大股票池的数据获取。
总结
- "每天多少行情数据"不是一个固定数字,而是策略范围、频率、历史深度和字段共同决定的结果。
- 全市场扫描与候选池分析最好分层设计,避免所有阶段都处理同样的数据。
- 历史数据应尽量本地保存并增量更新,而不是每天重新下载全部历史。
- QuantDash 的标的池查询、批量 K 线、实时行情和批量日内分时等能力,可以放在量化系统的数据接入层使用。
- 真正成熟的数据架构应该让"策略需要什么数据"反过来决定"API 获取什么数据",而不是因为 API 能提供什么就全部接入。
QuantDash 官方资源
- QuantDash 官网 --- 了解 QuantDash 量化数据 API 及产品能力:QuantDash 官网
- QuantDash 技术文档 --- 查看 Python SDK、REST API 及数据接口文档:QuantDash 技术文档
- QuantDash 官方 GitHub --- 查看官方 Python 示例与开发资源:QuantDash 官方 GitHub