第24章 做市商系统架构:实时数据流、计算引擎、订单管理、风险监控
做市商系统,说白了就是一台高速运转的印钞机——前提是你得把它造对。
我入行那会儿,见过太多团队把精力全扑在策略上,觉得系统嘛,能跑就行。结果呢?行情一波动,系统先崩了。嗯,这种事经历过一次就够了。今天我就把做市商系统的四个核心模块拆开聊聊:实时数据流、计算引擎、订单管理、风险监控。
实时数据流:系统的血管
数据流是系统的命脉。你想想看,做市商赚的就是微秒级的价差,数据晚到一毫秒,可能就亏一笔。
我个人习惯把数据流分成三层:
- 行情接入层:对接交易所的行情网关,处理FIX/FAST协议
- 数据分发层:用共享内存或ZeroMQ做低延迟广播
- 数据缓存层:本地维护Order Book的快照和增量
这里有个坑。我曾经遇到过一个情况:行情源同时推送了5档盘口的增量更新,但我的系统是按顺序处理的。结果中间丢了一笔更新,整个Order Book就歪了。后来怎么解决的?我加了一个序列号校验机制,每笔更新都带一个递增ID,发现跳号就立刻请求全量快照。
核心原则:数据流必须支持「增量+快照」双模式。增量保证速度,快照保证一致性。
计算引擎:策略的大脑
计算引擎负责两件事:定价和做市决策。
定价这块,我习惯用三层模型:
- 理论定价层:基于波动率曲面,用BSM或局部波动率模型算理论价
- 市场修正层:根据当前盘口的买卖价差、深度、对手方行为做调整
- 风险调整层:考虑持仓的Delta、Gamma、Vega敞口,加一个惩罚项
代码实现上,我推荐用事件驱动架构。每个新行情进来,触发一次定价计算。别用轮询,太慢了。
// 伪代码:事件驱动的定价引擎
class PricingEngine {
void onMarketData(MarketData md) {
double theoreticalPrice = volSurface.price(md.underlying, option);
double marketAdjustment = calculateSpread(md.bid, md.ask);
double riskPenalty = riskManager.getPenalty(position);
double finalPrice = theoreticalPrice + marketAdjustment - riskPenalty;
orderManager.submitQuote(finalPrice);
}
}
我的经验:计算引擎一定要做性能预算。我一般要求单次定价计算不超过5微秒。超过这个数,你就得考虑用FPGA或者GPU加速了。
订单管理:执行的手脚
订单管理模块,说白了就是负责把策略的报价发出去,同时跟踪订单状态。
我见过最蠢的设计是什么?每个策略自己维护一个订单状态机。结果呢?策略一多,订单状态全乱套了。
正确的做法是:
- 统一订单网关:所有策略的订单都走同一个网关
- 状态机标准化:用有限状态机管理每个订单的生命周期
- 熔断机制:当订单拒绝率超过阈值时,自动暂停该策略的报价
我曾经踩过一个坑:某个策略在行情剧烈波动时,连续发了100笔报价,结果交易所全部拒绝了,因为我们的报价超过了价格带宽限制。从那以后,我就在订单管理模块里加了一个「报价频率控制器」,每个策略每秒最多发N笔报价。
注意:订单管理模块必须支持「撤单再报」和「改价」两种模式。前者适合流动性好的品种,后者适合流动性差的品种。选错了,你的成交率会直线下降。
风险监控:最后的防线
风险监控不是事后诸葛亮,而是事前、事中、事后的全流程控制。
我把它分成三个层次:
| 层次 | 监控内容 | 触发动作 |
|---|---|---|
| 事前 | 报价是否超出风险限额? | 拒绝报价,记录日志 |
| 事中 | 持仓的希腊字母是否超标? | 自动对冲或降低报价规模 |
| 事后 | 日内的盈亏和风险指标 | 生成报告,调整策略参数 |
我个人最看重的是事中监控。为什么?因为行情变化太快,等你事后发现问题,可能已经亏了几百万了。
这里分享一个我自己的做法:我在风险监控模块里加了一个「压力测试引擎」,每5秒跑一次。它会模拟市场瞬间波动5%的场景,看看我的持仓能不能扛得住。扛不住?立刻降低报价规模。
系统架构总览
这四个模块怎么串起来?我画了一张图,你看一眼就明白了。
你看,数据流进来,计算引擎算出报价,订单管理发出去,风险监控全程盯着。一旦发现异常,立刻反馈给计算引擎和订单管理,形成闭环。
总结一句话:做市商系统不是堆功能,而是把数据流、计算、执行、风控这四个模块拧成一股绳。哪个环节慢了,整个系统就废了。
好了,这一章就聊到这儿。下一章我们深入讲讲波动率曲面的实时构建——那才是做市商真正的核心竞争力。