第2章:做市商系统架构:系统整体架构设计、核心模块划分、技术栈选型与数据流
做市商系统,说白了就是一台精密的「赚钱机器」。但机器要跑得稳,架构得先搭对。我见过不少团队,一上来就写代码,结果做到一半发现数据流不通,或者风控模块成了摆设——嗯,这种坑我踩过不少。
今天咱们就聊聊,一个靠谱的做市商系统,到底该怎么搭。
2.1 整体架构设计:分层与解耦
我个人习惯把做市商系统分成四层。为什么是四层?因为每一层都有它自己的「脾气」,混在一起容易出乱子。
| 层级 | 职责 | 关键点 |
|---|---|---|
| 接入层 | 对接交易所API,处理行情与订单 | 低延迟、高可用、协议适配 |
| 策略层 | 定价、做市逻辑、订单生成 | 可插拔、参数化、回测友好 |
| 风控层 | 实时监控、限额、熔断 | 独立进程、不可绕过 |
| 数据层 | 存储、分析、复盘 | 时序数据库、高吞吐写入 |
你想想看,如果风控和策略写在一个进程里,策略崩了风控也跟着挂——那还控个啥?所以分层不只是为了好看,是为了保命。
2.2 核心模块划分
模块划分这事儿,我踩过最大的坑就是「过度设计」。一开始恨不得把每个功能都拆成微服务,结果光服务间通信就占了30%的CPU。后来我学乖了——该合的就合,该拆的才拆。
2.2.1 行情模块
行情是系统的「眼睛」。它负责从交易所拉取深度、成交、Ticker等数据。这里要注意的是:行情数据是有时效性的。延迟超过100ms,你的报价可能就已经过时了。
- 支持多交易所同时接入
- 数据去重与对齐(不同交易所的时间戳格式不同)
- 本地缓存最新快照,供策略快速读取
2.2.2 策略引擎
策略引擎是系统的「大脑」。它接收行情,计算报价,生成订单。我个人建议把策略做成「插件化」的——这样换策略不用重启整个系统。
// 伪代码示例:策略接口
type Strategy interface {
OnTick(tick *Tick) []*Order
OnOrderFilled(order *Order)
OnOrderCancelled(order *Order)
}
你看,接口就这么简单。但实际实现时,要考虑的东西就多了——比如订单状态管理、重试逻辑、滑点控制。
2.2.3 风控模块
风控是系统的「刹车」。没有刹车的车,你敢开吗?我曾经见过一个团队,风控模块只是个「日志记录器」——出了事才回头看日志,那还有什么用?
- 实时风控:检查单笔订单金额、持仓上限、亏损阈值
- 熔断机制:当市场波动超过预设范围,自动暂停做市
- 事后风控:盘后分析,检查是否有异常交易
2.2.4 订单管理模块
订单管理是系统的「手」。它负责把策略生成的订单发到交易所,并跟踪订单状态。这里有个坑:交易所的订单状态回调可能延迟或丢失。所以一定要有「主动查询」机制。
2.3 技术栈选型
技术栈选型这事儿,没有银弹。我根据自己的经验,给出一套经过实战检验的组合:
| 模块 | 推荐技术 | 理由 |
|---|---|---|
| 行情接入 | Go / Rust | 低延迟、高并发、内存安全 |
| 策略引擎 | Python / C++ | Python快速迭代,C++极致性能 |
| 风控模块 | Go | 独立进程,部署简单 |
| 数据存储 | InfluxDB + PostgreSQL | 时序数据用InfluxDB,元数据用PG |
| 消息队列 | Redis Stream / NATS | 低延迟、轻量级 |
2.4 数据流设计
数据流是系统的「血管」。血流通畅,系统才能健康。我画了一张图,帮你理解数据是怎么流动的:
数据流的核心逻辑其实很简单:
- 行情模块从交易所拿到数据,推给策略引擎
- 策略引擎算出报价,生成订单请求,发给风控模块
- 风控模块检查通过后,交给订单管理模块
- 订单管理模块发单到交易所,并跟踪状态
- 所有模块的数据,都会异步写入数据存储,用于复盘和分析
2.5 避坑指南
最后,分享几个我亲身踩过的坑:
- 不要把所有模块放在一个进程里。我曾经这么干过,结果行情模块崩了,整个系统都挂了。后来改成独立进程,一个挂了其他还能跑。
- 风控模块一定要有「手动熔断」开关。自动熔断再智能,也比不上人眼判断。我遇到过市场异常波动,自动熔断没触发,手动按了按钮才保住仓位。
- 数据存储要预留足够的写入带宽。做市商系统每秒可能产生几千条记录,普通数据库扛不住。用时序数据库,或者干脆用文件日志+离线导入。
- 测试环境要和生产环境一致。别问我为什么知道——我在测试环境用Redis,生产环境用Kafka,结果上线第一天就出了兼容性问题。
嗯,架构设计这块,今天就聊到这儿。记住一句话:好的架构不是设计出来的,是改出来的。先跑起来,再优化,别一开始就想搞个完美的。