第九章:监控与告警系统
做市商系统跑起来之后,最怕什么?
怕半夜三点手机突然响了,但更怕的是——手机一直没响,早上到公司一看,系统已经挂了四个小时。
监控与告警,说白了就是给系统装上一套"神经系统"。哪里疼、哪里痒,得第一时间知道。我做了这么多年量化系统,见过太多"裸奔"上线的团队,结果无一例外都被市场教育了。
9.1 实时监控面板:你的系统仪表盘
实时监控面板,就是驾驶舱里的仪表盘。你得一眼能看出:
- 当前持仓风险敞口有多大
- 资金利用率是否合理
- 各交易对报价延迟是否正常
- 网络连接状态是否健康
我个人习惯把监控面板分成三个区域:
- 顶部:全局指标,比如总敞口、总盈亏、系统健康度
- 中部:各交易对详情,包括买卖价差、挂单深度、成交频率
- 底部:系统资源,CPU、内存、网络延迟、数据库连接池
嗯,这里要注意一点:不要把所有数据都堆上去。我曾经见过一个团队,面板上放了80多个指标,结果真正出问题时,根本找不到关键信息。我建议核心指标控制在15个以内,其他的放到二级页面。
核心监控指标清单(我常用的):
- 总敞口(Delta/Gamma/Vega)
- 资金利用率(当前保证金/总资产)
- 报价延迟(中位数、P99)
- 成交率(挂单成交比例)
- 系统错误率(每秒异常数)
- 网络连接状态(交易所API延迟)
9.2 异常交易检测:别让bug变成亏损
做市商系统里,异常交易是最致命的。我遇到过最离谱的一次:一个浮点数精度问题,导致系统在某个价格位上反复报单撤单,一晚上产生了200多万次无效请求,交易所直接把我们IP封了。
异常检测,我一般分三层:
- 第一层:规则引擎——硬性阈值检查。比如单笔成交金额超过总资产的5%,直接报警并暂停该交易对。
- 第二层:统计检测——基于历史数据的异常识别。比如某个交易对的成交频率突然飙升到均值的10倍以上,触发告警。
- 第三层:行为分析——检测策略行为是否异常。比如连续撤单超过50次,或者报价价差突然收窄到正常值的1/10。
我曾经踩过一个坑:只做了第一层规则引擎,结果市场剧烈波动时,所有阈值都被突破,告警刷屏,反而把真正的问题淹没了。后来我加上了"告警抑制"机制——同一类告警5分钟内只发一次。
避坑指南:
我曾经把告警阈值设得太敏感,结果每天收到上千条告警,团队直接麻木了。后来我改成"分级告警":
- P0(致命):系统宕机、资金异常 → 电话+短信
- P1(严重):策略行为异常、网络中断 → 即时消息+邮件
- P2(警告):指标偏离正常范围 → 邮件+日志
- P3(信息):日常统计报告 → 仅日志
9.3 性能监控:别让延迟吃掉利润
做市商的核心竞争力是什么?说白了就是速度。你比别人慢1毫秒,可能就抢不到最优报价。
性能监控,我重点关注三个维度:
- 报价延迟:从行情到达 → 策略计算 → 报单发出,整个链路耗时。我要求P99延迟不超过50ms。
- 成交确认延迟:从报单到收到成交回执的时间。如果超过200ms,说明网络或交易所端有问题。
- 系统吞吐量:每秒能处理多少笔报单和撤单。这个指标决定了你能同时做多少个交易对。
我记得有一次,系统突然出现间歇性延迟,排查了两天才发现是日志库的锁竞争导致的。从那以后,我强制要求所有IO操作都走异步队列,并且日志写入不能阻塞主流程。
// 性能监控的核心代码片段(伪代码)
class PerformanceMonitor {
private:
std::atomic<int64_t> total_orders;
std::atomic<int64_t> total_latency_us;
public:
void record_order(int64_t latency_us) {
total_orders++;
total_latency_us += latency_us;
// 记录P99延迟
if (latency_us > p99_threshold) {
alert("High latency detected: " + latency_us + "us");
}
}
double get_avg_latency_ms() {
return total_latency_us / (total_orders * 1000.0);
}
};
9.4 告警规则引擎:让系统自己"说话"
告警规则引擎,说白了就是一套"如果...就..."的逻辑。但真正好用的引擎,得支持:
- 组合条件:比如"报价延迟 > 100ms 且 成交率 < 50%" 才告警,避免单一指标误报
- 时间窗口:比如"连续5分钟内,错误率超过1%" 才触发,而不是单次抖动就报警
- 动态阈值:根据市场波动自动调整告警阈值。比如波动率低时,价差超过0.1%就告警;波动率高时,价差超过0.5%才告警
我建议用JSON或YAML来配置规则,方便运维人员修改,不用改代码。
{
"rules": [
{
"name": "报价延迟过高",
"condition": "avg_latency_ms > 100 AND duration_minutes > 5",
"severity": "P1",
"actions": ["send_sms", "send_wechat"]
},
{
"name": "资金异常变动",
"condition": "balance_change_percent > 10 AND time_window_minutes < 1",
"severity": "P0",
"actions": ["call_oncall", "pause_trading"]
}
]
}
重要提醒:
告警规则不是越多越好。我见过一个团队配置了200多条规则,结果真正出问题时,告警信息被淹没在"误报"里。我的经验是:先配10条最核心的,跑一个月再逐步优化。另外,一定要有"告警自愈"机制——比如网络抖动导致的短暂延迟,系统自动重试后恢复正常,就不需要通知人。
9.5 监控系统架构图
下面这张图,是我个人比较推荐的监控系统架构。它把数据采集、存储、分析、告警分成了四个独立模块,方便扩展和维护。
这张图里,数据从底层采集上来,经过清洗和计算,存入时序数据库。告警引擎实时扫描数据,一旦匹配规则就触发通知。我个人习惯把"自愈脚本"也放在告警层——比如检测到某个交易对报价延迟过高,自动重启该交易对的报价进程,而不是直接通知人。
9.6 实战经验总结
最后,分享几个我踩过的坑:
- 监控本身也会出问题:我曾经遇到过监控系统自己挂了,但没人知道。后来我加了一个"心跳检测"——监控系统每隔5分钟给自己发一条告警,如果收不到,说明监控挂了。
- 告警疲劳是真实存在的:团队每天收到几百条告警,最后大家都麻木了。我建议每周复盘一次告警规则,把那些"从来没触发过"或者"触发后没人处理"的规则删掉。
- 不要忽视日志:很多问题在告警触发之前,日志里已经有征兆了。我要求所有核心模块都打结构化日志(JSON格式),方便事后回溯。
嗯,监控与告警系统,说白了就是给系统买了一份"保险"。平时觉得没用,真出事的时候,它能救你一命。