一、行情系统概述:实时数据流的概念、行情系统的业务价值、主流行情数据源介绍
各位同学,今天咱们聊聊行情系统。说实话,这个主题我讲了不下二十次,但每次讲都有新感悟。为什么?因为行情系统是量化交易的「眼睛」——眼睛要是瞎了,再厉害的策略也白搭。
我刚开始做量化那会儿,踩过一个坑。当时用了一个第三方数据源,延迟大概在500毫秒左右。嗯,你可能觉得500毫秒不算啥,但在高频交易里,这足够让对手盘把你的订单吃干抹净。那次教训让我明白:行情系统不是「有数据就行」,而是「又快又准又稳」。
1.1 实时数据流:到底是个啥?
先别急着看代码,咱们把概念捋清楚。
实时数据流,说白了就是「数据一边产生,一边被处理」。跟传统的数据处理不一样——传统做法是把数据存到数据库里,然后慢慢分析。实时流呢?数据来了,立刻处理,立刻输出结果。
举个例子你就明白了:
- 传统方式:收盘后下载一天的行情数据,然后算均线、算波动率。这叫「离线分析」。
- 实时流方式:每一笔成交数据过来,立刻更新最新价、计算瞬时波动率。这叫「实时处理」。
我个人习惯把实时数据流拆成三个核心要素:
| 要素 | 说明 | 我踩过的坑 |
|---|---|---|
| 低延迟 | 从数据产生到被消费,时间尽可能短 | 曾经用HTTP轮询,延迟飙到2秒,直接被老板骂 |
| 高吞吐 | 单位时间内能处理的数据量要大 | 某次行情爆发,每秒10万笔数据,系统直接挂了 |
| 有序性 | 数据到达的顺序必须跟产生顺序一致 | 乱序导致计算出的均线完全错误,亏了钱才发现的 |
你想想看,这三个要素缺一个,行情系统就废了。延迟高,你看到的永远是「历史」;吞吐不够,行情爆发时直接丢数据;顺序乱了,算出来的指标全是错的。
1.2 行情系统的业务价值:不只是「看价格」
很多人觉得行情系统就是「显示价格」的。太天真了。
我在项目中遇到过一家私募,他们的策略是「做市商策略」。说白了,就是同时挂买单和卖单,赚差价。这个策略对行情的要求极高——你必须在毫秒级别感知到价格变动,然后立刻调整挂单。
行情系统的业务价值,我总结为三点:
- 决策依据:没有实时行情,你的策略就是「盲人摸象」。我记得有个团队用延迟5秒的行情做高频策略,结果每次开仓都开在最高点,平仓平在最低点。
- 风险控制:实时行情能帮你发现异常。比如某只股票突然暴跌,你的风控系统必须立刻响应。我曾经见过一个案例,因为行情延迟,风控没及时触发,一天亏了300万。
- 成本优化:好的行情系统能帮你减少滑点。滑点是什么?就是你下单的价格和实际成交价格的差异。行情越快,滑点越小。
核心观点:行情系统不是「成本中心」,而是「利润中心」。你花在行情系统上的每一分钱,都会在交易中加倍赚回来。
1.3 主流行情数据源介绍
市面上行情数据源很多,但真正靠谱的就那么几个。我按自己的经验给你排个序:
| 数据源 | 特点 | 适用场景 | 我的评价 |
|---|---|---|---|
| 交易所直连 | 延迟最低(微秒级),成本最高 | 高频交易、做市商 | 最靠谱,但门槛高 |
| 券商API | 延迟中等(毫秒级),免费或低价 | 中低频策略、个人交易 | 够用,但别太依赖 |
| 第三方数据商 | 延迟较高(百毫秒级),数据丰富 | 回测、研究、非实时场景 | 适合研究,不适合实盘 |
| 开源数据源 | 延迟最高,免费 | 学习、原型验证 | 玩玩可以,别当真 |
这里我要特别说一下交易所直连。很多人觉得「直连交易所」就是拉根网线就行了。其实不是。你需要申请交易席位、通过交易所的接口认证、还要搞定网络专线。我记得第一次做直连的时候,光申请流程就走了三个月。
我的建议:如果你是个人交易者或者小团队,先用券商API起步。等策略稳定了、资金量上来了,再考虑直连。别一上来就搞直连,成本太高,而且维护起来很麻烦。
1.4 实时数据流的典型架构
说了这么多概念,咱们来看看实际架构长什么样。下面这张图是我自己项目里用的架构,经过多次迭代,算是比较成熟了。
这个架构图看着简单,但每个层都有坑。我重点说两个:
- 数据接入层:不同数据源的协议不一样。有的用FIX协议,有的用二进制协议,还有的用WebSocket。你得统一成内部格式。我曾经因为协议解析写错了一个字节,导致价格差了100倍,还好是测试环境。
- 数据处理层:这里最容易出问题的是「数据对齐」。不同数据源的时间戳可能不一样,你得做时间同步。我建议用NTP服务器统一对时,不然算出来的指标全是错的。
注意:千万不要在数据处理层做「重计算」操作。比如实时计算复杂的机器学习模型,那会拖垮整个系统。把计算量大的任务放到离线层去做,实时层只做轻量级计算。
1.5 一个简单的行情接入示例
光说不练假把式。我给你看一段伪代码,演示行情接入的基本流程:
// 伪代码:行情接入示例
class MarketDataFeed {
constructor(source) {
this.source = source; // 数据源类型
this.buffer = []; // 数据缓冲区
this.callbacks = []; // 回调函数列表
}
// 连接数据源
connect() {
if (this.source === 'exchange') {
// 交易所直连,使用FIX协议
this.socket = new FIXSocket('tcp://exchange:1234');
} else if (this.source === 'broker') {
// 券商API,使用WebSocket
this.socket = new WebSocket('wss://broker:443/market');
}
this.socket.onMessage((data) => {
this.process(data);
});
}
// 处理原始数据
process(rawData) {
// 1. 协议解析
let parsed = this.parseProtocol(rawData);
// 2. 数据清洗
let cleaned = this.cleanData(parsed);
// 3. 格式统一
let unified = this.unifyFormat(cleaned);
// 4. 触发回调
this.callbacks.forEach(cb => cb(unified));
}
}
这段代码看着简单,但实际项目中要考虑的东西多得多。比如:
- 断线重连怎么办?
- 数据乱序怎么处理?
- 缓冲区满了怎么丢弃?
这些问题咱们后面的章节会一个一个解决。今天先把概念搞清楚。
好了,行情系统的概述就讲到这里。记住一句话:行情系统是量化交易的基础设施,基础不牢,地动山摇。
课后思考:如果你现在要设计一个行情系统,你会选择哪种数据源?为什么?