系统架构总览:分层架构设计、核心模块划分、数据流与订单流
做市引擎这东西,说白了就是一台高速运转的印钞机——前提是你得把它造对。我见过太多团队一上来就写代码,结果做到一半发现数据流卡住了,订单发不出去,或者行情延迟高得离谱。嗯,今天我们就从架构层面,把这件事彻底聊透。
一、为什么必须分层?
你可能觉得分层是「学院派」的做法。但我在实战中吃过亏——早期我做过一个单体的做市程序,所有逻辑揉在一起。行情处理、策略计算、订单管理全在一个线程里。结果呢?行情一波动,订单就堵住了,直接爆仓。
从那以后,我坚定了一个原则:做市引擎必须分层。每一层只干一件事,层与层之间通过明确定义的接口通信。这样做的三个好处:
- 隔离故障:行情层崩了,订单层还能撑一会儿
- 独立优化:你可以单独给订单层上FPGA加速,不影响其他层
- 便于扩展:加一个新品种?加一层适配器就行,核心逻辑不用动
核心原则:每一层都是「黑盒」。上层不需要知道下层怎么实现的,只需要知道接口长什么样。
二、四层架构设计
我个人习惯把做市引擎分成四层。你想想看,这其实跟TCP/IP协议栈的思路很像——每一层解决一个特定问题。
| 层级 | 名称 | 核心职责 | 典型组件 |
|---|---|---|---|
| L4 | 策略层 | 做市逻辑、定价、风控 | 策略引擎、风险控制器 |
| L3 | 订单管理层 | 订单生命周期、路由、状态机 | OrderManager、路由表 |
| L2 | 行情与数据层 | 行情订阅、数据清洗、缓存 | MarketDataFeed、TickCache |
| L1 | 接入层 | 交易所协议适配、网络通信 | Gateway、协议转换器 |
这里我要特别强调一下:L1和L2是IO密集的,L3和L4是计算密集的。所以我在项目中,通常把L1和L2放在独立的线程甚至独立的进程里跑,避免IO阻塞影响策略计算。
三、核心模块划分
每一层内部,又需要拆成更细的模块。我直接拿一个实际项目中的模块图来说明:
你看,每个模块的职责非常清晰。比如订单状态机,它只负责一件事:跟踪订单从「新建」到「成交」或「撤销」的完整生命周期。我在项目中遇到过一个问题——订单状态机没处理好「部分成交」的情况,导致仓位计算错了。后来我加了一个部分成交缓存,才彻底解决。
四、数据流:从行情到策略
数据流是架构的命脉。我习惯用「管道-过滤器」模式来描述它:
- 原始行情:交易所推送的Tick数据,经过L1的协议转换,变成内部统一格式
- 数据清洗:L2层做去重、排序、时间戳校准。这里要注意——不同交易所的时间戳精度不一样,我曾经踩过坑,Binance是毫秒级,而某些小交易所是秒级,直接导致策略误判
- 缓存与聚合:Tick数据进入环形缓冲区,同时K线生成器实时计算1秒、1分钟的聚合数据
- 策略消费:L4的策略引擎从缓存中拉取数据,计算做市报价
我的经验:数据流一定要设计成「推拉结合」。行情推送时,策略层被动接收;但策略层也可以主动拉取历史数据做回测。这样既保证了实时性,又保留了灵活性。
五、订单流:从策略到交易所
订单流是反方向的,但比数据流更复杂。因为它涉及状态确认和错误处理。
一个典型的订单生命周期是这样的:
- 策略层生成报价 → 传给L3订单管理层
- 订单管理层做预检:检查账户余额、检查是否超过风控阈值、检查是否重复下单
- 通过预检后,订单进入发送队列,由L1的Gateway发送到交易所
- 交易所返回确认 → 订单状态机更新状态
- 如果超时未确认,进入重试队列,最多重试3次
这里有个关键点:订单的幂等性。我曾经因为网络抖动,同一个订单被发送了两次,结果交易所成交了两笔。后来我在订单ID里加入了客户端序列号,交易所根据序列号去重,才彻底解决。
避坑指南:订单流一定要设计「死信队列」。那些重试3次仍然失败的订单,不能丢弃,要进入死信队列人工处理。我见过有人直接把失败订单扔了,结果亏了几十万。
六、多品种并行的挑战
做多品种并行,最头疼的是资源隔离。你不能让BTC的策略把CPU吃光了,导致ETH的策略饿死。
我的做法是:
- 每个品种一个独立的策略实例,运行在独立的线程或协程中
- 共享数据层:行情数据是全局共享的,但每个策略有自己的缓存副本
- 订单层统一管理:所有品种的订单都经过同一个OrderManager,方便做全局风控
你想想看,这样做的好处是什么?如果BTC的策略崩了,ETH的策略完全不受影响。而且全局风控可以防止某个品种过度交易。
七、性能关键点
最后聊几个性能相关的细节:
| 环节 | 常见瓶颈 | 我的优化方案 |
|---|---|---|
| 行情接收 | TCP粘包、序列化开销 | 使用零拷贝技术,直接操作内存缓冲区 |
| 策略计算 | Python GIL限制 | 核心计算用C++扩展,Python只做调度 |
| 订单发送 | 网络延迟 | 使用UDP + 应用层ACK,减少握手开销 |
| 日志记录 | 磁盘IO | 异步日志,先写内存环形缓冲区,再批量刷盘 |
嗯,架构总览就聊到这里。记住一句话:好的架构不是设计出来的,是改出来的。你不可能一开始就设计出完美的架构,但你可以留好扩展点,让架构随着业务一起成长。
一句话总结:分层解耦、模块化拆分、数据流与订单流分离、多品种资源隔离——这就是做市引擎架构的四大支柱。