17. 实时监控系统设计:设计一个实时监控波动率曲面套利机会的系统架构

波动率曲面套利,说白了就是跟时间赛跑。你算出来一个机会,等个几秒钟,价格可能就没了。所以我个人习惯,做套利必须有一套实时监控系统,不能靠人工盯盘。

这一章,我就把我在搭建这套系统时踩过的坑、总结的经验,掰开了揉碎了讲给你听。嗯,咱们直接进入正题。

17.1 系统核心目标:快、准、稳

设计这套系统,我给自己定了三个硬指标:

  • :从行情数据到达,到套利信号发出,延迟控制在 50 毫秒以内。超过这个数,机会基本就没了。
  • :误报率要低。我曾经被一个错误的信号坑过,直接导致一笔亏损。从那以后,我特别强调数据清洗和校验。
  • :系统不能崩。交易时段宕机,那可不是闹着玩的。

核心原则:宁可错过,不要做错。系统设计的第一要务是保证数据准确,其次才是速度。

17.2 整体架构:分层设计,各司其职

我习惯把系统拆成四层。每一层只干自己的事,互不干扰。这样出了问题也好排查。

下面这张图,是我自己画的架构图,你看一眼就明白了。

波动率曲面套利实时监控系统架构图 数据接入层 行情源(交易所API) → 数据清洗 → 实时缓存(Redis) 延迟要求:< 10ms 计算引擎层 波动率曲面构建 → 曲面平滑 → 套利信号计算 延迟要求:< 30ms 策略决策层 信号过滤 → 风险评估 → 订单生成 延迟要求:< 10ms 执行与监控层 订单执行 → 风控检查 → 日志与告警 延迟要求:< 5ms

17.3 各层详解:我是怎么设计的

17.3.1 数据接入层

这一层是系统的「眼睛」。数据进不来,后面全是白搭。

我建议用 WebSocket 直接连交易所的行情推送。别用 REST API 轮询,太慢了。数据进来后,先做三件事:

  • 去重:有时候交易所会重复推送同一笔数据,得过滤掉。
  • 校验:检查价格、成交量是不是合理。比如某个期权价格突然变成 0,那肯定是脏数据。
  • 缓存:用 Redis 做实时缓存。为什么用 Redis?因为它快,而且支持发布/订阅模式,方便后面多个计算节点消费。

小技巧:我在 Redis 里存数据时,会用「期权代码:时间戳」作为 key。这样既能快速读取最新数据,又能回溯历史。

17.3.2 计算引擎层

这是整个系统的大脑。说白了,就是算波动率曲面,然后找套利机会。

我把它拆成三个子模块:

  1. 曲面构建:用 SVI 模型或者样条插值,把离散的期权报价拟合成连续的曲面。我个人偏爱 SVI,因为它参数少,计算快。
  2. 曲面平滑:这一步很多人会忽略。其实很重要。原始数据有噪音,直接算出来的曲面坑坑洼洼的,容易产生假信号。我会用核平滑或者局部回归做一下平滑处理。
  3. 套利信号计算:这里就是核心了。计算日历价差、蝶式价差、盒式价差等。一旦发现某个组合的定价偏离超过阈值,就生成一个信号。

代码示例(伪代码,展示核心逻辑):

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 同步,问题才解决。

嗯,这套系统我用了两年多,整体还算稳定。你如果照着这个思路去搭,应该能少走不少弯路。