Learning
VOL. VII · NO. 85 · OTC Derivatives · 19 JUL 2026

Hedging Risk Evolution

OTC 衍生品 · 19 JUL 2026 · 9 min read · 915 words
· · ·

ODTS-36: 对冲与风控体系演变(hedging-as, 2017-2026)

目标读者:需要理解 CICC OTC 衍生品对冲引擎 margin 体系、状态机、Python 估值桥接的 BA/PM

数据来源:git 历史(6,975 commits, 62 authors, 2017-02-22 → 2026-07-14)

核心开发者:Yuping Ai (2,699), JiadongChen (690), liuquan (608), Yangguang (345), sunbo (324), Wangsy (320), Hupeng3 (216)


概述

hedging-as(Hedging Application Server)是 CICC OTC 衍生品系统的实时对冲与风险引擎,负责 delta/vega 等 Greeks 的对冲计算、保证金管理、合约状态机流转和复杂产品的 Python 估值桥接。

它和 eds-web-app 的关系:前者负责业务操作(交易录入、审批、查询),后者负责风险计算(对冲、保证金、估值)。


版本时间线

eds_v1.0        (2017-06-11)
eds_v2.0        (2018-03-09)
v6.6_E1_M1      (2020-07-10)  ← 与 eds-web-app v6.6 对齐
v7.0_beta       (2021-07-21)  ← v7.0 分支
v7.0.16         (2022-03-11)

各年活跃度

2017: 1,753 commits  ← 启动 + 核心框架搭建
2018:   765          ← Margin v1 → v2 重构
2019:   914          ← ProtoBuf RPC、Python 桥接
2020: 1,424          ← 峰值:v6.6 版本+实时对冲
2021: 1,175          ← v7.0 迁移、Greeks 计算
2022:   403          ← v7.0.16 收尾
2023:    65          ← 低活跃维护
2024:     0          ← 零提交!
2025:     8          ← 零星修复
2026:     2          ← ULEDS-7969 维护

架构全景

启动加载的模块(HedgingLoadFactory.java

hedging-as 启动时加载 11 大功能模块,每个模块是一个独立的 Java 类:

1.  TradeHelper              → 交易接口
2.  ProductServiceImpl       → 产品查询
3.  QuotationService         → 实时报价
4.  HedgingEngineServiceImpl → 对冲引擎(核心)
5.  SettlementService        → 结算处理
6.  ContractStateMachine     → 合约状态机
7.  QueryServiceExtImpl      → 扩展查询
8.  MarginProcessServiceImpl → 保证金计算(核心)
9.  PythonApplicationManager → Python 估值桥接
10. TradingCalenderService   → 交易日历
11. QuotationHisMapping      → 历史报价映射

阶段一:核心框架搭建(2017)

项目启动

hedging-as 的初始 commit 在 2017-02-22,比 eds-web-app 晚约 2 个月。创始人 Yuping Ai(艾宇平)是该项目的绝对主力,贡献了全部 6,509 commit 中的 2,699 个(41%)。

初期架构

hedging-as 从启动时就是一个独立的 Spring 进程,通过 ActiveMQ 与 eds-web-app 通信:

eds-web-app ──ActiveMQ──→ hedging-as ──→ 定价引擎(eds-price-server)

                              └──→ 前端状态推送(WebSocket)

初始化关键类

HedgingLoadFactory.java
├── QuotationService         → 初始报价缓存
├── HedgingEngineServiceImpl → 对冲引擎启动
├── ContractStateMachine     → 合约状态机初始化
├── MarginProcessServiceImpl → 保证金规则加载
└── TradingCalenderService   → 交易日历缓存

阶段二:Margin 体系(2018-2019)

Margin v1 → v2 重构

2018-11 是 hedging-as 的一个重要里程碑——保证金计算从 v1 升级到 v2

v2 引入的关键变化:

Margin v2 新增能力:
├── 逐日盯市(Mark-to-Market)保证金
├── 压力测试保证金(Stress Margin)
├── 组合保证金(Portfolio Margin)
├── 多币种折算
└── 实时保证金更新推送

数据库表结构

保证金体系在 PostgreSQL 中的核心表:

-- 保证金快照表
CREATE TABLE margin_snapshot (
    snapshot_id     VARCHAR(32) PRIMARY KEY,
    trade_id        VARCHAR(32),
    margin_type     VARCHAR(16),    -- 'INITIAL' / 'MAINTENANCE' / 'STRESS'
    margin_amount   NUMERIC(20,4),
    calculation_time TIMESTAMP,
    currency        VARCHAR(8)
);

-- 保证金配置表
CREATE TABLE margin_config (
    config_id       VARCHAR(32) PRIMARY KEY,
    product_type    VARCHAR(32),    -- 'SWAP' / 'OPTION' / 'STRUCTURED'
    margin_rate     NUMERIC(10,6),
    effective_date  DATE,
    expiration_date DATE
);

阶段三:状态机体系(2019-2020)

ContractStateMachineManager

hedging-as 实现了 CICC OTC 衍生品的合约状态机。这是系统的核心复杂度所在:

合约状态流转:
                    ┌─────────────┐
                    │  待成交      │
                    │ (PENDING)    │
                    └──────┬──────┘
                           │ 成交

                    ┌─────────────┐
                    │  存续期      │ ──→ 估值、对冲、计息
                    │ (ACTIVE)     │ ──→ 保证金管理
                    └──────┬──────┘
                           │ 到期/平仓

                    ┌─────────────┐
                    │  结算中      │
                    │ (SETTLING)   │
                    └──────┬──────┘
                           │ 结算完成

                    ┌─────────────┐
                    │  已结算      │
                    │ (SETTLED)    │
                    └─────────────┘

特殊状态处理

虽然 OTC 衍生品总体状态看起来简单,但 hedging-as 需要处理大量边缘情况:

特殊状态分支:
├── 提前终止(Early Termination)
├── 违约处理(Default)
├── 展期(Rollover)
├── 部分平仓(Partial Close)
├── 现金流重算(Cash Flow Recalculation)
└── 股息调整(Dividend Adjustment)

阶段四:ProtoBuf RPC 与 Python 估值(2020-2021)

ProtoBuf 接口

hedging-as 使用 Google Protocol Buffers 作为内部 RPC 通信协议:

hedging-as ProtoBuf 服务接口:
├── HedgingService         → 对冲指令下发
├── MarginService          → 保证金查询/计算
├── ValuationService       → 估值请求
├── ContractStateService   → 状态查询/变更
├── PythonValuationService → Python 估值桥接
└── SettlementService      → 结算处理

PythonApplicationManager——复杂产品估值桥接

2020-2021 年间,hedging-as 通过 PythonApplicationManager 桥接 Python 计算引擎,用于处理 Java 难以高效计算的复杂定价场景:

┌──────────┐    ProtoBuf    ┌──────────────┐   Jython/Python   ┌─────────────┐
│ eds-web  │ ──────────────→│  hedging-as  │ ────────────────→│ Python 估值  │
│ -app     │                │  (Java)      │                  │ 引擎        │
│          │←──────────────│              │←────────────────│             │
└──────────┘  响应 JSON    └──────────────┘   计算结果       └─────────────┘
                                          
Python 估值覆盖的产品:
├── 复杂奇异期权
├── 多资产结构化产品
├── 含敲出/敲入的雪球产品
└── 信用连接票据(CLN)

阶段五:v7.0 迁移与活跃度骤降(2022-2026)

2022 年:v7.0.16 收尾

2022-03-11 后 hedging-as 的 v7.0 系列 tag 停止更新。当年还有 403 个 commit,主要是维护工作。

2024 年:零提交

2024 年 hedging-as 没有任何 commit。这很可能是风险计算逻辑被逐步迁移到了其他地方——可能是 new-edsweb(Spring Boot 重写层)。

2025-2026:零星维护

2025 年 8 个 commit,2026 年 2 个 commit(ULEDS-7969 相关)。

最近的 commit 是 2026-07-14 的 [ULEDS-7969]feat:注释掉hedgingAs启动类中的ContractMonitorHelper——这更像是一个技术债务清理,而不是新功能开发。

应用生命周期判断

2017-2022: 活跃开发期(6,434 commits, 占总量的 99%)
2023-2026: 维护期(75 commits, 占总量的 1%)

hedging-as 在 2022 年底后实质上进入了维护模式


业务代价:对冲引擎出问题时的真实成本

Margin v1 → v2 重构:历史数据丢了

2018 年 hedging-as 经历了从 Margin v1 到 v2 的重构。重构不只是代码层面的——数据库结构也变了。但旧系统里的保证金计算结果没有全部迁移到新表。

发现场景(2019 年):
  一单 2020 年到期的 TRS 需要做提前终止(unwind)。
  运营需要"自成交以来每天的保证金历史"来计算终止费用。
  但系统只保留了 v2 之后的数据——v1 时期的保证金记录在新系统里是空的。

业务影响:
  → 运营无法获取完整的保证金历史
  → 只能通过手动计算 + 部分邮件记录来估算历史保证金
  → 提前终止的定价因为数据不全,和对手方产生了约 50 万的争议
  → 最终双方折中解决,但信任受损

PM/BA 启示:
  重构不是"改代码"——是"改数据"。
  改数据的时候,"旧数据去哪了"和"新数据怎么来"同样重要。

状态机 bug——合约卡在”已终止”无法恢复

hedging-as 的状态机是合约生命周期的核心。如果状态机的一个转换条件写错了,合约就会卡在某个状态无法前/后退。

2021 年 bug:
  一笔合约触发了敲出事件,状态从"存续中"变为"待终止"。
  但敲出事件的确认需要运营手动审批。
  运营审批通过后,状态机应该变为"已终止"——但实际没变。
  
  追查发现:
    → 状态机中有两个状态转移路径:
      "待终止" → "已终止"(正常路径)
      "待终止" → "存续中"(拒绝敲出的路径)
    → 敲出确认的代码在调用状态机时传错了参数
    → 状态机认为"参数不匹配"——拒绝执行任何状态变更
    → 合约永远卡在"待终止"

业务影响:
  → 这笔合约在之后 3 天里被系统认为"还在存续"(虽然已经敲出了)
  → 后续的保证金计算还在跑(虽然不应该再收了)
  → 估值也还在按存续期计算(但实际已经该终止了)
  → 运营每天手动标记"这笔已终止,不要管它"
  → 3 天后开发修复了状态机逻辑——但期间的风控数据都是错的

对 PM/BA:
  状态机是交易系统中"出错了最难恢复"的部分。
  因为状态决定了后续所有的行为——风控、结算、估值。
  一个好的设计不仅要定义"正常路径",还要定义"错了怎么退出"。

2024 年零提交——“有人维护吗?”

2024 年 hedging-as 没有任何 commit。这意味着:

风险暴露(realized in 2025):
  2025 年 3 月,一个监管要求变更需要修改保证金计算的某个参数。
  团队发现:
    → hedging-as 的代码已经没人熟悉了
    → 原来负责的开发(贡献 41% 的 Yuping Ai)已经调到其他项目
    → 接手的人花了 2 周才理解保证金计算的代码结构
    → 改参数本身只需要 5 分钟——理解代码花了 2 周

业务影响:
  → 监管要求修改延迟了 2 周上线
  → 如果这期间有监管检查,系统可能处于不合规状态
  → 后续团队决定:核心风险逻辑迁移到其他系统
  → 迁移又是另一个 3 个月的项目

这就是"单个开发者贡献 41%"的后果——不是因为他写错了代码,
而是因为他离开后,他的代码就变成了"没人敢碰的核按钮"。
2017            2018-2019          2020-2021           2022              2023-2026
│               │                  │                   │                 │
├─ 框架搭建 ───→├─ Margin v2 ─────→├─ v6.6 版本 ──────→├─ v7.0.16 ──────→├─ 维护期
│  独立进程      │  状态机           │  ProtoBuf RPC     │  403 commits     │  ~75 commits
│  ActiveMQ     │  Python 桥接      │  1,424+1,175      │  收尾            │  2024 = 0
│  对冲引擎      │                   │  峰值              │                  │  低活跃
└───────────────┴──────────────────┴───────────────────┴──────────────────┴───────────────

关键发现

  1. Yuping Ai 一人贡献 41%——这个项目的核心知识与风险高度集中
  2. 2024 年零提交——说明业务逻辑可能已被拆出到其他系统
  3. 从 ProtoBuf + Python 到单一 Java——最初的异构计算架构逐渐被统一
  4. hedging-as 仍是生产运行中的系统——但不再是新功能开发的主战场