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

Pricing Engine Evolution

OTC 衍生品 · 19 JUL 2026 · 10 min read · 1,000 words
· · ·

ODTS-35: 定价引擎演变(eds-price-server, 2016-2021)

目标读者:需要理解 CICC 从简单期权定价到 Monte Carlo + 30 种结构定价演进路径的 BA/PM

数据来源:git 历史(9,325 commits, 50 authors, 2016-12-21 → 2021-12-30)

核心开发者:chenkun (2524), Shaonan Cheng (1221), Ou Zhao (1153), wangyh3 (544), Shijun (503)


概述

eds-price-server 是一个独立于 eds-web-app 运行的定价服务。注意它的 commit 分布和 eds-web-app 一样从 2016 年开始,说明定价引擎从一开始就被设计为独立服务——这是一个早期的架构决策。

产品结构(product type)从最初的简单香草期权(Vanilla),逐步扩展到 30+ 种结构化产品。


版本时间线

v1.0                        ─── 初始版本
v1.2.1                      ───
v1.5                        ───
v1.7.2                      ───
V2.0_2020-01-16             ─── 2020 年重大升级
V2.1_2020-03-21             ───
v2.2_6.6.3-20200522         ─── 与 eds-web-app v6.6 系列对齐
version6.6.6-2020-11-8      ───
v6.6.7-2020-12-15           ─── 最后一个标签

关键观察:标签中的 6.6.x 版本号与 eds-web-app 的 v6.6.x 系列保持一致——说明两个项目在 2020 年有一个版本对齐的发布节奏。2021 年之后没有新标签,但开发持续到 2021 年底(最后 commit 在 2021-12-30)。


阶段一:初始定价引擎(2016-2018)

起步(2016-12)

eds-price-server 的第一个 commit 和 eds-web-app 几乎同时(相差 7 天),说明定价是 EDS 系统的从一开始就有的核心能力

初始架构:

PricingEngine.java(主入口)→ StructuredProduct/(各产品子类)
                                            ├── VanillaOption
                                            ├── TRSValue
                                            ├── SPPValue(雪球)
                                            └── ...

早期产品覆盖

从代码中 StructuredProduct 的子类名可以推断,2016-2018 年只覆盖了:

  • VAN(Vanilla, 香草期权)——最基本
  • TRS(Total Return Swap)——收益互换
  • SPP / DSF——简单的结构化产品

技术特点

  • 纯 Java 计算引擎,无外部依赖
  • 每日历/交易日规则硬编码
  • 使用 JDBC 直连 Oracle 获取市场数据(行情、波动率曲面)

阶段二:Greeks 和 Monte Carlo(2018-2020)

GPricingEngine 的引入

gpricingengine/pricing/GPricingEngine.java 的加入是定价能力的一个关键里程碑。它提供了完整的 Greeks 计算:

定价输出:
├── OptionNPV    → 期权净现值
├── DeltaNPV     → Delta 敞口
├── GammaNPV     → Gamma 敞口
├── ThetaNPV     → Theta(时间衰减)
├── VegaNPV      → Vega(波动率敏感度)
├── RhoNPV       → Rho(利率敏感度)
├── PremiumNPV   → 权利金
└── TotalNPV     → 总净值

产品线扩展

2018-2020 年之间,产品类型从 ~10 种扩展到 20+ 种:

// PricingEngine.java 中的 switch-case:
VAN      → 普通香草
ACPS     → Auto-Callable Premium Snowball(自动赎回)
CPS      → Callable Premium Snowball
ZCC      → 雪球(中证雪球)
BR       → Bull Ratio(保本)
SF       → Snowball Fix(雪球固息)
DSF      → Discount Snowball Fix(折价雪球固息)
STEP     → Step-down(阶梯)
STEP2    → Step-down 变种
IPP      → IPP
SPP      → Snowball Premium Participation
SPPF     → SPP Fix
RISKY    → 雪球(最核心产品)
PPDSF    → Principal Protected Discount Snowball Fix
NPP      → Net Premium Protection
BR3      → Bull Ratio 3
FCPS     → Fixed Coupon Premium Snowball
CLQ      → Classic(经典)
RA       → Range Accrual
REP      → REP
OT       → OT
ASIAN    → Asian Option(亚式期权)
ESF      → European Snowball Fix
CCSF     → CCS Fix
DCCS     → DCC Structure
STP      → Step
IDP      → IDP
DCCSP    → DCCS Premium

Monte Carlo 模拟引擎

对于路径依赖型产品(雪球、亚式期权等),引入 Monte Carlo 模拟

输入:
├── Spot Price(标的价格)
├── Vol Surface(波动率曲面)
├── Dividend Yield(股息率)
├── Interest Rate Curve(利率曲线)
├── Barrier Levels(敲入/敲出界限)
└── Coupon Schedule(票息计划)

MC 模拟过程:
1. 生成 10,000+ 个价格路径
2. 每条路径判断敲入/敲出
3. 统计平均收益 → NPV

阶段三:系统架构成熟(2020-2021)

SOAP Web Service 接口

eds-price-server 对外暴露 SOAP Web Service:

Endpoint: http://10.110.224.205:9091/PricingEngine?wsdl

服务范围:
├── Option Pricing(期权定价)
├── IRS Curve Pricing(利率互换曲线定价)
└── Amortizing IRS Pricing(摊销 IRS 定价)

这个 SOAP 接口被 hedging-as(对冲服务器)和 eds-web-app 共同调用。

与 eds-web-app 的集成

eds-web-app(业务层)

    ├──→ 实时定价请求 → eds-price-server (SOAP)

    ├──→ 盘中估值请求 → eds-price-server (SOAP)

    └──→ EOD 批量估值 → eds-price-server (批量调用)

hedging-as(对冲引擎)

    └──→ 对冲计算 → eds-price-server (SOAP)
         ├── Greeks → 计算需要对冲的量
         └── NPV → 计算盈亏

SOAP WSDL 缓存

~/odts1/eds-price-server/wsdl/
├── PricingEngine.wsdl
└── GPricingEngine.wsdl

注意到 hedging-as 中也有相同的 WSDL 缓存:

~/odts1/hedging-as/wsdl/
├── PricingEngine.wsdl
└── typemapping.properties

缓存层

cache/
├── MarketDataCache        → 行情数据缓存
├── VolSurfaceCache         → 波动率曲面缓存
└── CurveCache             → 利率曲线缓存

阶段四:停更与转移(2021-2026)

2021 年后的情况

price-server 的最后一个 commit 在 2021-12-30。此后定价引擎本身没有大的修改,但定价逻辑的调整通过两种方式继续:

  1. 通过 eds-web-app 中的定价参数调整:费率、BPS、保证金率等
  2. 通过 hedging-as 中的 Python 估值集成PythonApplicationManager 调用 Python 模型

Python 估值的角色

hedging-as/PythonApplicationManager

    ├──→ 调用 Python Monte Carlo 模型
    │       ├── 复杂结构估值
    │       └── 路径依赖产品估值

    └──→ 与 Java PricingEngine 对比验证

这暗示 Java 定价引擎在复杂产品上逐渐被 Python 模型补充或替代。


演变总结

2016                   2018                   2020                   2021
│                      │                      │                      │
├─ v1.x 基础定价 ──────┤                      │                      │
│   Vanilla + TRS       │                      │                      │
│                       ├─ Greeks 扩展 ────────┤                      │
│                       │   Delta/Gamma/Theta  │                      │
│                       │                      ├─ 30+ 结构产品 ───────┤
│                       │                      │   雪球家族全线覆盖    │
│                       │                      │                      │
│                       │                      ├─ SOAP WebService ────┤
│                       │                      │   与 hedging-as 集成  │
│                       │                      │                      │
│                       │                      └─ Python 估值补充 ────┤
│                       │                        Monte Carlo 模型    │
└───────────────────────┴──────────────────────┴──────────────────────┘
                                      ↑ price-server 停更
                                        但定价逻辑仍在 eds-web-app
                                        和 hedging-as 中持续演进

关键数字

维度初始 (2016)成熟 (2021)
产品结构类型~330+
定价方法解析解Monte Carlo + 解析解
GreeksDelta/Gamma/Vega/Theta/Rho
对外接口SOAP WebService
缓存MarketData + VolSurface + Curve
Python 集成通过 hedging-as

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

Java 定价 vs Python 定价——谁是对的?

2021 年后,价格引擎有两条路径:Java PricingEngine(原生的解析解/数值解)和 hedging-as 中调用的 Python Monte Carlo 模型。当两条路径对同一产品的估值不一致时,交易员应该信谁?

真实场景:
  某雪球产品(Autocallable),敲出边界 103%,期限 24 个月。
  市场条件:标的下跌约 15%。
  
  Java PricingEngine 估值:面值约 85%(已亏损)
  Python Monte Carlo 估值:面值约 78%

  差异原因:
    → Java 引擎使用简化的波动率模型(局部波动率),
      在深度虚值状态下的路径模拟不够精确
    → Python Monte Carlo 使用随机波动率模型,
      更准确地反映了"标的一直不反弹"的概率

  业务影响:
    → 交易员用哪个估值来做对冲决策?
    → 不同估值 → 不同 Greeks → 不同对冲策略
    → 运营估值报告给客户时用哪个?
    → 如果报高了,客户觉得被坑了;报低了,客户提前止损
  
  最终处理(据推测):
    → 日间交易用 Java 引擎(快,够用)
    → EOD 估值用 Python Monte Carlo(精确)
    → 但有时候两者的差异 > 5%,风控需要出说明

缓存未刷新——交易员看到了 1 小时前的价格

定价引擎使用 MarketDataCacheManagerVolSurfaceCacheManager 缓存市场数据和波动率曲面。如果缓存刷新机制出问题,交易员看到的就是过时的价格。

2020 年场景:
  开市后标的 A 大跌 5%。
  交易员看到价格引擎显示的估值变化很小——"不对啊,标的跌这么多,雪球怎么没怎么变?"
  等了 30 分钟,估值突然跳水。
  
  → 原因是波动率曲面缓存每 30 分钟刷新一次
  → 标的已经大跌,但波动率曲面用的是昨天的数据
  → 30 分钟后波动率曲面刷新(波动率飙升),估值才反映真实变化

业务影响:
  → 这 30 分钟里有交易员基于过时的估值做了对冲决策
  → 如果按照"正确的估值",他应该减仓——但实际上没做
  → 30 分钟的延迟 = 约 20 万的额外亏损(取决于规模)

对 PM/BA 的启示:
  系统说"实时估值"的时候,要问清楚:
  "哪些市场数据是实时(<1s)、哪些是分钟级、哪些是小时级?"
  "估值页面是真的重新算了,还是显示了上次的缓存?"

定价引擎停更带来的风险

price-server 从 2021 年底停止更新,但 eds-web-app 还在持续新增产品。新产品的定价依赖 hedging-as 的 Python 模型——但如果 Python 模型也来不及更新呢?

2023 年场景:
  业务新增了一种"双观察日雪球"——不是每天观察敲出,而是只在每月的第 1 天和第 15 天观察。
  Python Monte Carlo 模型来不及支持这种定制结构。
  临时方案:
    → 在 eds-web-app 中硬编码了一条定价规则(基于已有产品的估值加一个 spread)
    → 没有经过完整的定价引擎验证
    → 这个 spread 值是一个人工估算,没有回测

业务风险:
  → 这个产品的定价是否正确?无法验证
  → 因为没有独立的定价引擎可以做交叉验证
  → 如果 spread 估错了,每笔交易都带着这个错误
  → 直到产品到期才能真正知道"定价是不是对的"

定价引擎停更不是"旧技术不用了"——它是"失去了独立验价能力"。
对于衍生品业务来说,失去独立验价能力意味着:
  你无法回答"这个价格对吗?"
  只能回答"Python 模型说这个价"。

从代码结构推断可能的原因:

  1. 产品复杂度超过 Java 引擎能力边界——复杂结构(变种雪球等)需要更灵活的 Python 模型
  2. 市场数据源切换——从 Oracle 直连改为 DAS(数据服务)的 REST API
  3. hedging-as 承担了更多定价职责——状态机 + 对冲 + Python 估值的组合使供需迁移