第20章:风控系统架构
做市商的风控系统,说白了就是你的「交易刹车系统」。
我见过太多团队,策略赚钱时觉得风控是累赘,等爆仓了才后悔没装刹车。嗯,今天我们就来聊聊,一套完整的做市商风控系统到底该怎么搭。
一、实时风控引擎:你的第一道防线
实时风控引擎,就是盯着每一笔交易、每一个订单的「哨兵」。它必须在毫秒级做出判断——这个订单能不能发?这个仓位有没有超限?
核心指标:延迟必须控制在 1ms 以内,否则你的策略可能已经亏完了,风控才反应过来。
我个人习惯把实时风控拆成三层:
- 订单级风控:检查单笔订单的金额、数量、价格是否合理。比如,你设置的卖单价格不能偏离市场中间价超过 5%。
- 账户级风控:监控总敞口、总保证金、总盈亏。一旦某个指标触线,立即熔断。
- 策略级风控:每个策略单独设限。我记得有一次,一个策略因为 bug 疯狂下单,幸好策略级风控先拦住了,没让整个账户出事。
代码实现上,我推荐用事件驱动架构:
// 伪代码示例:实时风控引擎核心逻辑
class RealtimeRiskEngine {
async onOrder(order) {
// 1. 订单级检查
if (order.price > this.getMaxPrice()) {
return { pass: false, reason: '价格超限' };
}
// 2. 账户级检查
if (this.account.exposure + order.amount > this.maxExposure) {
return { pass: false, reason: '敞口超限' };
}
// 3. 策略级检查
if (this.strategy.dailyLoss > this.strategy.maxDailyLoss) {
return { pass: false, reason: '策略日亏损超限' };
}
return { pass: true };
}
}
注意:实时风控引擎不能依赖数据库查询。我曾经见过一个团队,每次风控检查都去查 MySQL,结果延迟飙到 50ms,直接导致策略失效。正确的做法是用内存缓存 + 流式计算。
二、离线风控分析:事后复盘才是真功夫
实时风控管的是「当下」,离线风控管的是「过去和未来」。
说白了,离线分析就是把你一天、一周、一个月的交易数据拉出来,看看风控规则有没有漏掉什么,有没有误杀什么。
我一般会做这几件事:
- 回测风控规则:用历史数据跑一遍,看看哪些规则触发了,哪些没触发。有没有该触发却没触发的情况?
- 压力测试:模拟极端行情,比如 2010 年闪电崩盘,看看你的风控系统扛不扛得住。
- 归因分析:每一笔亏损,是策略问题还是风控问题?我曾经发现,某个策略的亏损其实是因为风控规则太严,导致该赚的钱没赚到。
小技巧:离线分析的结果,要能自动生成报告,推送到你的手机或邮箱。我习惯每天早上看一份「昨日风控简报」,心里才有底。
三、风控数据管道:让数据流动起来
风控系统离不开数据。订单数据、成交数据、行情数据、账户数据……这些数据必须实时、准确地流到风控引擎里。
我推荐用 Kafka 作为数据总线:
# 数据管道拓扑示例
# 行情数据 -> Kafka -> 实时风控引擎
# 订单数据 -> Kafka -> 实时风控引擎
# 成交数据 -> Kafka -> 离线分析系统
# 账户数据 -> Kafka -> 实时风控引擎 + 离线分析系统
为什么要用 Kafka?因为它能保证数据不丢、不重复,而且吞吐量极高。我见过用 RabbitMQ 做风控数据管道的,结果行情一爆发,队列直接堵死,风控系统就瞎了。
避坑指南:我曾经犯过一个错误——把风控数据和交易数据混在同一个 Kafka 集群里。结果交易数据量太大,把风控数据的 topic 给挤爆了。后来我强制要求:风控数据必须用独立的 Kafka 集群,物理隔离。
四、风控API设计:对外暴露的「安全门」
风控系统不能只是一个黑盒子,它需要对外提供 API,让其他系统(比如交易系统、监控系统、报表系统)能调用。
我设计风控 API 时,遵循几个原则:
- 简单:每个 API 只做一件事。比如
/risk/check-order只检查订单,/risk/check-account只检查账户。 - 快速:API 响应时间必须小于 1ms。如果做不到,那就用异步方式,先返回一个 token,等结果出来再回调。
- 可观测:每个 API 调用都要有日志、有监控。我习惯给每个 API 加上 trace ID,方便排查问题。
举个例子:
// 风控 API 示例
POST /risk/v1/check-order
{
"order_id": "12345",
"symbol": "BTC/USDT",
"side": "sell",
"price": 50000,
"amount": 1.0
}
// 返回结果
{
"pass": true,
"risk_id": "risk_abc123",
"checks": [
{"name": "price_limit", "pass": true},
{"name": "exposure_limit", "pass": true},
{"name": "strategy_loss_limit", "pass": true}
]
}
个人经验:API 的返回结果一定要包含「检查明细」。这样当风控拒绝了一个订单,交易员能立刻知道是哪个规则触发了,而不是一脸懵逼地来问你。
五、整体架构图
下面这张图,是我做风控系统时最常用的架构。你想想看,数据从行情、订单、账户三个方向流入,经过 Kafka 分发,实时风控引擎和离线分析系统各司其职,最后通过 API 对外提供服务。
这张图看起来简单,但每个模块背后都有大量细节。比如实时风控引擎里,我用了 Redis 做状态缓存,用 Lua 脚本做原子性检查,确保在高并发下不会出现竞态条件。
总结一下:实时风控引擎负责「快」,离线风控分析负责「全」,数据管道负责「稳」,API 负责「通」。四者缺一不可。
嗯,这套架构我用了三年,经历过几次极端行情,也扛过几次系统故障。不能说它完美,但至少让我睡得着觉。