第二章:系统架构设计——分层架构设计、核心组件介绍、数据流与订单流

好,咱们开始聊架构。说实话,很多做高频交易的朋友,一上来就盯着延迟优化、盯着纳秒级比拼。但我的经验是——架构没搭好,后面全是坑。我在第一家公司做量化系统时,就因为分层不清晰,一个行情模块的bug直接带崩了整个交易链路,那叫一个惨。

今天这一章,我就把高频交易系统的骨架给你拆开看。你想想看,一栋大楼要盖得高,地基和框架得先稳。交易系统也一样。

一、为什么必须分层?

高频交易系统,说白了就是跟时间赛跑。但跑得快的前提是——每个模块各司其职

我个人习惯把系统分成四层:

  • 接入层:负责跟交易所握手,收行情、发订单
  • 逻辑层:策略计算、信号生成、风险管理
  • 执行层:订单管理、路由、撮合
  • 数据层:存储、回放、分析

为什么要这么分?我举个例子。假设你的策略逻辑里有个死循环,如果它跟行情接收模块混在一起,那行情数据就断了,整个系统就瞎了。分层之后,逻辑层崩了,接入层还能继续收行情,数据层还能把数据存下来。等逻辑层重启,还能从数据层补回这段时间的行情。这叫故障隔离

核心原则:每一层只做一件事,并且把这件事做到极致。层与层之间通过明确定义的接口通信,绝不越界。

二、核心组件逐个拆解

好,咱们一层一层往下看。每个层里都有哪些关键组件?

1. 接入层——行情网关 & 交易网关

这是系统的最前线。行情网关负责接收交易所的行情数据,交易网关负责发送订单和接收成交回报。

这里有个坑,我踩过。交易所的行情协议,比如CTP、FIX/FAST,数据格式都不一样。有的用二进制,有的用XML。你如果每个交易所都写一套解析代码,那维护成本就上天了。

我的做法是:在接入层内部做一个统一的内部行情格式。不管外面来的是什么协议,进到系统内部都转成同一种结构体。这样上层策略就不用关心底层是哪个交易所了。

// 内部统一行情结构体(C++示例)
struct MarketData {
    uint64_t timestamp;   // 纳秒时间戳
    char symbol[16];      // 合约代码
    double bid_price;     // 买一价
    double ask_price;     // 卖一价
    uint32_t bid_volume;  // 买一量
    uint32_t ask_volume;  // 卖一量
    uint8_t exchange_id;  // 交易所编号
};

避坑指南:我曾经因为行情网关里用了动态内存分配(new/delete),导致在高频行情下出现微秒级的抖动。后来全部改成预分配内存池,延迟稳定多了。记住,高频场景下,零动态分配是基本要求。

2. 逻辑层——策略引擎 & 风控模块

策略引擎是大脑。它拿到行情数据后,根据你的交易策略(比如做市、套利、趋势跟踪)计算出买卖信号。

但这里有个关键点——策略引擎不能直接下单。它算出来的信号,要先经过风控模块的检查。

风控模块做什么?我列几个常见的:

  • 资金检查:账户余额够不够?
  • 仓位检查:会不会超仓?
  • 频率检查:每秒下单次数有没有超过限制?
  • 价格检查:下单价格是不是明显偏离市场?

嗯,这里要注意。风控模块如果做得太重,会拖慢整个链路。我建议把风控分成两级:快速风控深度风控。快速风控只做最简单的检查(比如价格偏离),放在逻辑层内部。深度风控(比如资金、仓位)放在执行层,异步处理。

3. 执行层——订单管理器 & 路由引擎

订单管理器(Order Manager)是执行层的核心。它负责管理每一个订单的完整生命周期:

状态 说明
PENDING_NEW 订单已生成,等待发送
NEW 已发送到交易所,等待确认
PARTIALLY_FILLED 部分成交
FILLED 全部成交
CANCELED 已撤销
REJECTED 被交易所拒绝

路由引擎呢?它负责决定订单发到哪个交易所。如果你同时连了上期所、大商所、郑商所,那路由引擎就要根据流动性、延迟、手续费等因素,选择最优的交易所。

注意:订单管理器必须保证幂等性。什么意思?就是同一个订单,不管重发多少次,结果都一样。否则网络抖动时,你可能会重复下单,造成严重损失。我见过有人因为这个,一天亏了十几万。

4. 数据层——存储 & 回放

数据层看起来不起眼,但它是整个系统的记忆体。没有它,你就没法做回测,也没法复盘。

高频交易的数据量有多大?我给你算一笔账。一个期货合约,每秒可能有几百笔行情。一天下来,光一个合约就是几百万条数据。如果你做全市场,一天的数据量轻松上GB。

所以存储方案很关键。我推荐用列式存储或者时序数据库,比如InfluxDB、ClickHouse。它们对时间序列数据的压缩和查询效率远高于传统关系型数据库。

三、数据流与订单流——系统里的血液

架构搭好了,组件也认识了。接下来咱们看看数据是怎么在系统里流动的。我画了一张图,帮你直观理解。

高频交易系统数据流与订单流 交易所 接入层(行情/交易网关) 逻辑层(策略引擎+风控) 执行层(订单管理器+路由) 数据层(存储+回放) 行情数据流 订单流 数据持久化/回放

这张图里,我用了三种颜色的箭头:

  • 绿色箭头:行情数据流。从上往下走,交易所 -> 接入层 -> 逻辑层。这是单向的,只读不写。
  • 红色箭头:订单流。从下往上走,逻辑层 -> 执行层 -> 接入层 -> 交易所。这是双向的,因为订单发出去后,还有成交回报回来。
  • 蓝色虚线箭头:数据持久化与回放。每一层产生的数据,都可以异步写入数据层。回测时,数据层再把历史数据喂给逻辑层。

你可能会问:为什么订单流和行情流要分开?原因很简单——优先级不同。行情数据量大,但丢了可以重传;订单数据量小,但一条都不能丢。所以一般会用不同的网络通道和线程来处理。

关键设计原则:数据流是推模式(push),订单流是拉模式(pull)。行情来了就推给上层,订单则是由上层主动发起。这样设计,能最大程度减少不必要的等待。

四、避坑总结

最后,我把自己这些年踩过的坑,总结成几条原则,你记一下:

  1. 分层要彻底:层与层之间只通过接口通信,不要共享内存或全局变量。否则一个bug能传染整个系统。
  2. 异步为王:所有IO操作(网络、磁盘)都要异步。同步等待在高频场景下是灾难。
  3. 监控先行:每一层都要有监控指标——延迟、吞吐量、错误率。没有监控,你就像在黑暗中开车。
  4. 可回放:所有数据都要能回放。这样出了问题,你可以像看录像一样,一帧一帧地查。

嗯,架构设计就聊到这儿。记住一句话:好的架构,是让错误的影响最小化,而不是让错误不发生。因为在高频交易里,错误是不可避免的,关键是你怎么兜底。