17. 实时监控系统设计:设计一个实时监控波动率曲面套利机会的系统架构
波动率曲面套利,说白了就是跟时间赛跑。你算出来一个机会,等个几秒钟,价格可能就没了。所以我个人习惯,做套利必须有一套实时监控系统,不能靠人工盯盘。
这一章,我就把我在搭建这套系统时踩过的坑、总结的经验,掰开了揉碎了讲给你听。嗯,咱们直接进入正题。
17.1 系统核心目标:快、准、稳
设计这套系统,我给自己定了三个硬指标:
- 快:从行情数据到达,到套利信号发出,延迟控制在 50 毫秒以内。超过这个数,机会基本就没了。
- 准:误报率要低。我曾经被一个错误的信号坑过,直接导致一笔亏损。从那以后,我特别强调数据清洗和校验。
- 稳:系统不能崩。交易时段宕机,那可不是闹着玩的。
核心原则:宁可错过,不要做错。系统设计的第一要务是保证数据准确,其次才是速度。
17.2 整体架构:分层设计,各司其职
我习惯把系统拆成四层。每一层只干自己的事,互不干扰。这样出了问题也好排查。
下面这张图,是我自己画的架构图,你看一眼就明白了。
17.3 各层详解:我是怎么设计的
17.3.1 数据接入层
这一层是系统的「眼睛」。数据进不来,后面全是白搭。
我建议用 WebSocket 直接连交易所的行情推送。别用 REST API 轮询,太慢了。数据进来后,先做三件事:
- 去重:有时候交易所会重复推送同一笔数据,得过滤掉。
- 校验:检查价格、成交量是不是合理。比如某个期权价格突然变成 0,那肯定是脏数据。
- 缓存:用 Redis 做实时缓存。为什么用 Redis?因为它快,而且支持发布/订阅模式,方便后面多个计算节点消费。
小技巧:我在 Redis 里存数据时,会用「期权代码:时间戳」作为 key。这样既能快速读取最新数据,又能回溯历史。
17.3.2 计算引擎层
这是整个系统的大脑。说白了,就是算波动率曲面,然后找套利机会。
我把它拆成三个子模块:
- 曲面构建:用 SVI 模型或者样条插值,把离散的期权报价拟合成连续的曲面。我个人偏爱 SVI,因为它参数少,计算快。
- 曲面平滑:这一步很多人会忽略。其实很重要。原始数据有噪音,直接算出来的曲面坑坑洼洼的,容易产生假信号。我会用核平滑或者局部回归做一下平滑处理。
- 套利信号计算:这里就是核心了。计算日历价差、蝶式价差、盒式价差等。一旦发现某个组合的定价偏离超过阈值,就生成一个信号。
代码示例(伪代码,展示核心逻辑):
def detect_arbitrage(surface_data):
signals = []
for expiry in surface_data.expiries:
for strike in surface_data.strikes:
# 计算蝶式价差
butterfly = calc_butterfly(surface_data, expiry, strike)
if butterfly > threshold:
signals.append({
'type': 'butterfly',
'expiry': expiry,
'strike': strike,
'value': butterfly
})
# 计算日历价差
calendar = calc_calendar(surface_data, expiry, strike)
if abs(calendar) > threshold:
signals.append({
'type': 'calendar',
'expiry': expiry,
'strike': strike,
'value': calendar
})
return signals
注意:阈值不能设得太低。我曾经设了个很低的阈值,结果一天出了几百个信号,大部分都是噪音。后来我把阈值调高到 2 倍标准差,信号质量才上来。
17.3.3 策略决策层
信号来了,要不要下单?这一层就是做决策的。
我加了两个过滤器:
- 流动性过滤器:如果某个期权合约的买卖价差太大,或者成交量太小,直接过滤掉。你想想看,信号再好,你进不去出不来,有什么用?
- 风险过滤器:计算一下这个套利组合的 Greeks,看看会不会暴露太大的风险。比如 Delta 中性吗?Gamma 会不会太大?
只有通过这两层过滤的信号,才会生成订单。
17.3.4 执行与监控层
最后一层,负责把订单发出去,同时盯着系统别出问题。
执行方面,我建议用 FIX 协议 直连交易所。别用券商提供的 API,延迟太高。
监控方面,我做了三件事:
- 心跳检测:每秒钟检查一次各模块是否正常运行。
- 延迟监控:记录每个环节的耗时,一旦超过阈值就告警。
- 日志审计:所有信号、订单、成交记录都存下来,方便事后复盘。
17.4 技术选型:我的推荐
| 层级 | 推荐技术 | 理由 |
|---|---|---|
| 数据接入 | WebSocket + Redis | 低延迟,高吞吐 |
| 计算引擎 | C++ 或 Rust | 计算密集型,需要极致性能 |
| 策略决策 | Python (NumPy/Pandas) | 快速原型,方便调参 |
| 执行与监控 | FIX 协议 + Prometheus | 稳定,监控生态好 |
我的经验:别想着用一套技术打天下。不同层级对性能、开发效率的要求不一样。该用 C++ 的地方别偷懒,该用 Python 的地方也别逞强。
17.5 避坑指南
最后,分享几个我踩过的坑:
- 数据源切换:有一次交易所升级了行情协议,我的解析代码没跟上,导致数据全乱了。后来我加了个版本检测机制,一旦协议变了就自动告警。
- 内存泄漏:计算引擎跑久了,内存占用越来越高。排查了好久,发现是一个全局变量没释放。从那以后,我每次上线前都会跑一遍内存检测工具。
- 时钟同步:多台服务器之间的时间不同步,导致信号的时间戳对不上。后来我统一用 NTP 同步,问题才解决。
嗯,这套系统我用了两年多,整体还算稳定。你如果照着这个思路去搭,应该能少走不少弯路。