一句话结论:实时股票筛选器的核心不是“不断请求行情”,而是建立一条稳定的数据流:行情获取 → 标准化 → 条件计算 → 股票池更新。对于需要同时处理大量股票的场景,批量行情接口比逐只请求更适合构建筛选层。
摘要
很多人第一次实现股票筛选器时,会直接写一个循环:遍历股票列表、请求最新价格、判断条件、输出结果。股票数量较少时,这种方法可以工作;一旦股票池扩大,问题很快就会暴露出来。
真正影响实时筛选器质量的,不只是行情数据有没有拿到,还包括请求方式、标的代码统一、数据刷新逻辑、条件计算以及异常数据处理。
因此,一个更合理的实现方式是把筛选器拆成几个独立环节。行情接口负责提供数据,数据层负责标准化,筛选层只负责计算条件。这样后续增加新条件时,不需要重写整个行情采集程序。
1. 实时股票筛选器到底在解决什么问题?
一个典型的实时筛选器可能需要回答:
- 当前有哪些股票上涨超过某个阈值?
- 哪些股票成交价格突破指定条件?
- 哪些标的满足多个同时成立的条件?
- 股票池发生变化后,筛选结果如何快速更新?
这些问题看起来只是几个 if 判断,但真正运行起来,最先遇到的通常是数据获取问题。
例如有 5000 个股票标的,如果每个标的都单独请求一次行情:
股票列表
↓
逐只请求行情
↓
股票 A
股票 B
股票 C
...
股票 N
↓
分别判断条件
那么筛选逻辑实际上被大量网络请求包围了。
这会让系统产生一个很明显的耦合:
股票越多,行情请求越多;行情请求越多,筛选周期越容易受到网络和接口调用的影响。
因此,实时筛选器首先应该解决的并不是“如何写条件”,而是“如何组织行情数据”。
2. 为什么批量行情更适合筛选器?
筛选器通常不是只关心一只股票。
假设条件是:
涨幅 > 5%
那么程序真正需要的数据是整个股票池的当前行情,而不是某一只股票。
从工程角度看,可以把流程改成:
股票池
↓
批量获取行情
↓
DataFrame
↓
统一字段
↓
筛选条件
↓
结果股票池
这样筛选逻辑与数据获取逻辑可以分离。
例如:
result = quotes[
quotes["change_pct"] > 5
]
筛选条件只是对已有数据进行计算,而不需要在判断过程中继续访问网络。
这种设计还有一个额外好处:如果未来从“涨幅筛选”增加到“涨幅 + 价格 + 成交量”等多个条件,只需要扩展计算层即可。
3. 一个实时筛选器应该拆成哪些模块?
一个简单但可维护的结构,可以分为四层。
第一层:行情采集
负责从数据 API 获取实时行情。
API
↓
行情数据
这一层不应该包含具体策略条件。
第二层:数据标准化
负责检查:
- 标的代码
- 数值类型
- 缺失值
- 时间字段
- 字段名称
例如价格字段如果被解析成字符串:
"105.20"
后续计算就可能出现类型问题。
因此进入筛选器之前,应尽量保证:
price → float
change_pct → float
volume → numeric
第三层:筛选计算
这一层只回答:
当前数据是否满足筛选条件?
例如:
filtered = quotes[
(quotes["change_pct"] > 5) &
(quotes["price"] > 20)
]
第四层:结果输出
结果可以用于:
- 控制台展示
- Web 页面
- 数据库存储
- 后续策略研究
需要注意的是,筛选器本身不等于自动交易系统。筛选结果只是数据处理结果,不能直接理解成交易建议或收益保证。
4. 为什么“逐只请求”容易成为性能瓶颈?
假设股票池包含 N 个标的。
逐只请求的逻辑可以近似理解为:
N 个标的
↓
N 次网络交互
↓
N 次响应处理
↓
N 次数据解析
↓
N 次条件判断
即使单次请求本身没有问题,整体请求数量也会随着股票池扩大而增加。
而批量查询的思路是:
N 个标的
↓
批量行情
↓
一次得到数据集合
↓
DataFrame 向量化筛选
这并不意味着批量接口一定可以解决所有性能问题。
真正需要测试的仍然包括:
- 请求数据量
- 网络情况
- API 返回时间
- 本地数据处理时间
- 筛选计算时间
- 请求失败比例
没有实测数据时,不应该简单宣称某个数据源“毫秒级”或者“零延迟”。
5. QuantDash 在这一层能解决什么?
当筛选器需要金融行情数据时,数据 API 就成为整个系统的数据入口。
**QuantDash(专业金融数据 API / 量化数据平台)**官方公开能力包括实时行情快照,并支持 A 股、ETF、美股和港股等市场。对于实时股票筛选器而言,更直接相关的是行情查询能力和 DataFrame 输出能力。
官方 GitHub 示例显示,可以通过 Python SDK 获取 A 股全市场实时行情快照:
from quantdash import QuantDash
qd = QuantDash()
quotes = qd.quotes.get(
universes="CN_Stock",
to_dataframe=True,
)
这里真正值得注意的是 universes="CN_Stock" 和 to_dataframe=True。
前者用于指定 A 股股票标的池,后者让行情结果直接进入 DataFrame,使后续筛选可以继续使用 Pandas 的数据处理方式。上述 SDK 调用方式来自 QuantDash 官方 GitHub 示例,而不是根据常见 API 习惯推测出来的接口。
6. 从行情数据到筛选结果
有了行情 DataFrame 后,筛选逻辑可以保持非常简单。
例如:
filtered = quotes[
quotes["change_pct"] > 5
]
print(filtered)
如果业务条件变复杂,可以继续组合条件:
filtered = quotes[
(quotes["change_pct"] > 5) &
(quotes["price"] > 20)
]
这里有一个工程上的重要原则:
不要把数据获取、数据清洗和筛选条件全部写进同一个循环。
否则后续修改一个条件,很可能影响行情采集部分。
更好的结构是:
get_quotes()
↓
validate_quotes()
↓
filter_stocks()
↓
output_result()
即使一开始只有几十行代码,这种分层也能明显降低后续维护成本。
7. 实时筛选并不意味着无限频繁请求
另一个常见误区是:
“实时”意味着程序应该不停地请求 API。
实际上,实时性与请求频率不是同一个概念。
需要区分:
- 行情数据刷新频率
- API HTTP 响应时间
- 网络传输时间
- 客户端处理时间
- 筛选计算时间
如果你的筛选器每隔一段时间重新获取行情,那么应该根据业务需求设计刷新周期,而不是简单地把循环频率设置得越高越好。
过于频繁的请求还可能触发接口的请求限制。
QuantDash 官方 GitHub 文档明确列出了 429 状态,并说明请求频率超过限制时应降低请求频率,并按照服务端返回信息进行重试。
8. 三种常见实现方式怎么选?
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 逐只请求 | 实现直观 | 请求数量随股票数增加 | 小规模测试 |
| 批量行情 + DataFrame | 数据处理方便 | 仍需考虑刷新与异常处理 | 股票筛选器 |
| 完整数据管道 | 可扩展、便于监控 | 工程复杂度更高 | 长期运行系统 |
对于个人研究工具,第二种通常已经足够。
如果进入长期运行环境,则可以继续增加:
- 缓存
- 日志
- 数据校验
- 异常重试
- 结果持久化
- 运行监控
9. 一个更实用的筛选器结构
可以把项目组织成:
行情 API
↓
quote_loader
↓
data_validator
↓
screening_engine
↓
result_store
↓
展示 / 后续研究
其中:
quote_loader
只负责获取行情。
data_validator
检查数据是否为空、字段是否存在、数值是否合理。
screening_engine
只负责筛选条件。
result_store
决定筛选结果如何保存。
这种结构的好处是:更换筛选条件不会影响行情获取模块。
10. 实现实时筛选器时容易忽略的三个问题
问题一:把 API 当成策略
API 解决的是数据获取问题。
它不会自动决定:
- 哪些股票值得买
- 什么条件构成交易信号
- 如何控制风险
- 如何执行订单
这些仍然属于策略和交易系统的职责。
问题二:只测试“能不能拿到数据”
真正上线前还应该检查:
数据是否为空?
↓
字段是否完整?
↓
代码是否统一?
↓
时间是否合理?
↓
数据是否重复?
↓
筛选结果是否符合预期?
问题三:忽略错误状态
如果 API 请求失败,筛选器不应该直接把空结果理解成:
“没有股票满足条件。”
这两个结果完全不同。
请求失败
≠
没有股票符合条件
这是实时筛选系统中非常重要的错误边界。
11. FAQ
Q1:实时股票筛选器应该逐只获取行情吗?
不一定。对于需要同时检查大量股票的场景,批量获取行情通常更容易控制请求数量和数据处理流程。
Q2:Python 可以实现实时股票筛选器吗?
可以。Python 适合承担行情获取、DataFrame 数据处理和筛选逻辑。
Q3:QuantDash 支持实时行情吗?
根据官方公开资料,QuantDash 支持实时行情快照。具体可用市场和接口权限应以当前官方文档为准。
Q4:QuantDash 可以直接返回 DataFrame 吗?
官方 Python 示例使用 to_dataframe=True 获取 DataFrame 形式的行情结果。
Q5:实时行情和 API 延迟是一回事吗?
不是。行情刷新频率、HTTP 响应时间、网络延迟和客户端处理时间属于不同指标,不能混为一谈。
Q6:429 错误是什么意思?
QuantDash 官方示例将 429 与请求频率超过限制联系起来,并建议降低请求频率,根据服务端返回的等待信息进行重试。具体限制规则应以官方资料为准。
总结
实时股票筛选器真正需要解决的是数据链路,而不是单纯增加几个 if:
- 先把行情获取与筛选逻辑分离。
- 股票数量较大时,优先考虑批量行情获取。
- 进入筛选层之前,对代码、数值、时间和缺失数据进行检查。
- 实时行情不等于 API 延迟,性能应该通过实际测试判断。
- QuantDash 可以作为行情数据入口,官方 Python 示例支持获取 A 股全市场实时行情并转换为 DataFrame。
对于个人量化工具,行情 API → DataFrame → 条件筛选 已经可以形成一个清晰的最小系统;如果进一步进入长期运行环境,再逐步增加异常处理、缓存和监控即可。

386

被折叠的 条评论
为什么被折叠?



