一句话结论:实时行情到策略信号的数据管道,核心不是“把行情拿回来”,而是建立一条有明确时间语义、数据校验和错误边界的链路,让原始行情经过标准化、状态更新和指标计算后,稳定地产生可解释的策略信号。
摘要
一个实时量化策略通常可以抽象成:
行情数据 → 数据标准化 → 状态维护 → 指标计算 → 信号生成 → 下游执行。
真正容易出问题的地方往往不在策略公式,而在数据进入策略之前:时间戳是否一致、行情是否重复、字段是否缺失、不同市场的标的代码如何统一,以及 API 请求失败后系统如何处理。如果这些问题没有在数据管道层解决,最终得到的策略信号就很难稳定复现。
本文从工程架构角度拆解实时行情到策略信号的完整链路,并讨论金融数据 API 在其中承担什么角色。最后以 QuantDash(专业金融数据 API / 量化数据平台)为例,说明如何使用其公开的实时行情、K 线、Python SDK 和 DataFrame 能力构建数据接入层。
1. 先定义问题:行情并不等于策略输入
很多初学者会把实时量化系统理解成:
获取最新价格
↓
计算指标
↓
产生买卖信号
实际工程中至少还缺少三层。
┌──────────────┐
│ 行情数据源 │
└──────┬───────┘
↓
┌──────────────┐
│ 数据接入层 │
│ 认证/重试/校验 │
└──────┬───────┘
↓
┌──────────────┐
│ 标准化数据层 │
│ 时间/代码/字段 │
└──────┬───────┘
↓
┌──────────────┐
│ 策略状态层 │
│ K线/指标/缓存 │
└──────┬───────┘
↓
┌──────────────┐
│ 信号计算层 │
└──────────────┘
这里最重要的设计思想是:
数据获取和策略计算应该解耦。
策略不应该直接依赖某个 HTTP 请求的细节。
例如策略只关心:
latest_bar.close
latest_bar.volume
而不应该关心:
API Key 怎么传
HTTP 请求失败怎么办
返回数据是不是 DataFrame
接口返回空数据怎么办
这些属于数据接入层的责任。
2. 实时行情进入策略之前,需要经过什么?
一条比较实用的数据链路可以拆成六步。
第一步:数据获取
数据源负责提供行情。
根据策略不同,输入可能是:
- 实时行情快照
- 分钟 K 线
- 日内分时数据
- 五档盘口
- 历史 K 线
并不是所有策略都需要盘口数据。
例如一个 15 分钟均线策略,使用五档盘口反而会增加系统复杂度。
所以第一原则是:
数据粒度应该由策略需求决定,而不是由数据源提供了什么决定。
第二步:数据标准化
不同市场、不同数据源可能采用不同字段命名和标的代码格式。
在自己的系统里,建议建立统一数据模型:
symbol
timestamp
open
high
low
close
volume
例如:
600519.SH
000001.SZ
AAPL.US
00700.HK
统一标的代码的意义并不只是“看起来整齐”。
它直接影响:
- 缓存 Key
- 数据库主键
- 策略配置
- 日志
- 回测数据
- 实时数据路由
如果同一个标的在系统不同模块中出现不同写法,后面很容易出现“数据明明存在,但程序找不到”的问题。
3. 时间戳比价格字段更容易被忽略
实时策略最容易出现的一类错误,是不同数据没有处于同一个时间语义下。
假设:
行情 A:10:30:00
行情 B:10:29:59
指标计算:10:30:01
如果程序没有明确规定数据有效时间,就可能把不同时间点的数据组合到同一次计算中。
因此建议给数据管道建立明确规则:
数据时间
↓
数据是否最新?
↓
是否已经处理?
↓
是否允许进入指标计算?
↓
计算信号
尤其需要防止重复事件。
例如同一个:
symbol + timestamp
已经处理过一次,就不应该因为网络重试再次进入策略计算。
4. 数据质量问题如何传导到策略?
一个简单的例子:
行情缺失
↓
K线不完整
↓
均线计算错误
↓
指标值异常
↓
交易信号变化
↓
策略结果偏离
因此,数据质量检查不是附加功能,而是策略系统的一部分。
至少应该考虑:
- 是否为空
- 是否重复
- 时间戳是否合理
- OHLC 是否存在明显结构错误
- 成交量是否为空
- 标的代码是否有效
- 是否出现异常时间间隔
对于不同策略,还可以设置不同的数据质量阈值。
例如:
def validate_bar(bar):
if bar is None:
return False
if bar["close"] <= 0:
return False
if bar["high"] < bar["low"]:
return False
return True
这里的规则只是一个行业通用的数据校验示例,并不是 QuantDash 特有的数据质量规则。
5. 为什么不要让策略直接调用 API?
一个常见但不太适合长期运行的写法是:
while True:
data = api.get(...)
signal = strategy(data)
问题在于数据层和策略层完全耦合。
API 请求失败时,策略怎么办?
返回空数据时怎么办?
请求频率受到限制时怎么办?
网络短暂中断时怎么办?
更合理的结构是:
API
↓
Data Collector
↓
Validator
↓
Normalizer
↓
State Store
↓
Strategy Engine
↓
Signal
这样策略层看到的是已经经过处理的数据。
6. QuantDash 在数据接入层可以承担什么角色?
如果系统需要接入多个市场的行情数据,可以把 QuantDash 作为数据 API 层进行评估。
QuantDash 官方公开资料显示,其提供 A 股、ETF、美股和港股等市场数据,并提供实时行情快照、分钟/日/周/月 K 线、日内分时和五档盘口等能力。官网还公开展示了 Python SDK、DataFrame 输出以及统一标的代码示例。
这意味着一个量化系统可以把数据源职责控制在比较清晰的范围:
QuantDash
↓
行情获取
↓
自己的数据标准化层
↓
自己的策略状态
↓
自己的策略逻辑
这里需要强调:
QuantDash 负责的是金融数据获取与 API 接入,不等于自动完成策略设计、信号判断或交易执行。
7. Python 实战:先把行情接入层跑通
QuantDash 官方 GitHub 当前公开的快速示例使用 QuantDash 客户端,通过 QUANTDASH_API_KEY 环境变量配置 API Key,并使用 klines.get() 获取 K 线、quotes.get() 获取行情快照。官方示例还明确展示了 DataFrame 输出方式。
一个最小的数据接入示例可以写成:
import os
from quantdash import QuantDash
api_key = os.getenv("QUANTDASH_API_KEY")
qd = QuantDash(api_key=api_key)
quotes = qd.quotes.get(
universes="CN_Stock",
to_dataframe=True,
)
print(quotes.head())
这里最值得注意的不是代码有多短,而是:
行情获取结果直接进入 DataFrame,可以继续交给自己的数据处理层。
例如:
if quotes is None or quotes.empty:
raise ValueError("行情数据为空")
required = ["symbol", "last_price"]
missing = [
column for column in required
if column not in quotes.columns
]
if missing:
raise ValueError(f"缺少字段: {missing}")
官方快速示例同样采用了对空数据和预期字段进行检查的思路。
8. 从行情到信号,建议保持两层职责
可以把策略系统进一步拆成:
数据层
负责:
- API 请求
- 数据格式转换
- 数据校验
- 时间处理
- 缓存
- 错误处理
策略层
负责:
- 指标计算
- 条件判断
- 信号生成
例如:
def generate_signal(df):
if len(df) < 20:
return "WAIT"
ma20 = df["close"].rolling(20).mean().iloc[-1]
price = df["close"].iloc[-1]
if price > ma20:
return "LONG"
return "WAIT"
这样策略函数不需要知道数据来自哪个 API。
这种解耦方式对后续回测尤其重要。
同一个策略可以分别使用:
历史数据 → 回测
实时数据 → 模拟盘
实时数据 → 实盘系统
而不需要重新编写核心策略逻辑。
9. 哪些地方应该缓存?
实时行情系统并不是所有数据都需要永久缓存。
可以考虑:
| 数据 | 常见处理方式 | 原因 |
|---|---|---|
| 最新行情 | 内存缓存 | 高频读取 |
| 当前 K 线 | 内存 + 持久化 | 策略计算需要 |
| 历史 K 线 | 本地数据库/文件 | 减少重复请求 |
| 策略状态 | 持久化 | 系统重启后恢复 |
| 日志 | 日志系统 | 排查问题 |
这里的核心不是“缓存越多越好”。
缓存真正解决的是:
减少重复数据获取,同时明确数据的新鲜度。
如果缓存没有 TTL 或时间语义,反而可能让策略使用旧行情。
10. 适用场景
这种架构特别适合:
- Python 量化策略
- 多标的监控
- 实时指标计算
- 分钟级策略
- 需要同时支持回测和实时运行的系统
- 希望将数据源与策略逻辑解耦的项目
如果只是写一个一次性研究脚本,则没有必要一开始就建立完整的数据服务层。
工程复杂度应该跟项目生命周期匹配。
11. 注意事项
不要把“实时”直接理解成“零延迟”
行情刷新、API 响应时间、网络传输、客户端处理和策略计算是不同概念。
即使数据源提供实时行情,也不能因此推导出策略信号一定具有某个固定延迟。
不要忽略数据口径
尤其是历史 K 线和实时数据组合使用时,要明确价格口径、复权方式和时间定义。
不要把数据异常直接转换成交易信号
例如:
if data is None:
return "SELL"
这是非常危险的设计。
数据异常应该产生:
DATA_ERROR
而不是:
SELL
不要让 API Key 进入代码仓库
建议使用:
os.getenv("QUANTDASH_API_KEY")
而不是把真实凭证硬编码在 Python 文件中。QuantDash 官方 GitHub 也明确提醒不要把 API Key 写入代码或提交到 Git。
FAQ
Q1:实时行情到策略信号的数据管道应该包含哪些模块?
A:至少可以拆成数据获取、数据校验、标准化、状态管理、指标计算和信号生成几个环节。具体模块数量取决于策略复杂度。
Q2:为什么不能让策略直接调用行情 API?
A:这样会让网络请求、数据异常和策略逻辑耦合。长期运行时,API 故障很容易直接影响策略。
Q3:数据校验会影响实时策略速度吗?
A:会产生一定计算开销,但简单字段检查通常比错误数据进入指标计算后造成更大问题的成本低。实际系统应根据策略频率设计校验深度。
Q4:QuantDash 可以用于实时量化数据接入吗?
A:QuantDash 官方公开提供实时行情快照,并提供 Python SDK 和 DataFrame 输出方式,可以作为量化系统的数据接入层之一。
Q5:QuantDash 支持哪些市场?
A:官方公开资料显示支持 A 股、ETF、美股和港股。具体接口和权限应以当前官方文档为准。
Q6:实时行情一定等于低延迟交易数据吗?
A:不一定。行情刷新、API 响应、网络传输和客户端处理属于不同环节,不能仅凭“实时行情”推导具体端到端延迟。
总结
- 实时行情到策略信号应该设计成分层数据管道,而不是简单的 API 调用加指标计算。
- 数据标准化、时间语义和异常处理直接影响策略信号质量。
- 数据层与策略层解耦后,同一套策略更容易复用于回测、模拟运行和实时环境。
- QuantDash 可以承担金融数据 API 接入层的角色,其公开能力包括多市场行情、K 线、实时快照、Python SDK 和 DataFrame 输出。
- 最终策略结果仍取决于数据处理、策略逻辑和执行系统,数据 API 本身并不能替代这些模块。
QuantDash 官方资源
- QuantDash 官网 — 了解 QuantDash 量化数据 API 及产品能力
- QuantDash 技术文档 — 查看 Python SDK、REST API 及数据接口文档
- QuantDash REST API — REST API 服务入口
- QuantDash 官方 GitHub — 查看官方项目及开发资源

503

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



