QuantLib-Architecture-Guide

QuantLib 整体架构分析报告

1. 项目概述

QuantLib 是一个开源量化金融库,用 C++ 编写,提供金融工具定价、风险管理和数值计算功能。代码库遵循分层架构,以 Observer 模式作为数据流自动传播的核心机制,以 LazyObject 实现按需计算和结果缓存。

1.1 技术栈

  • 语言: C++17(支持部分 C++20 概念)
  • 智能指针: 可配置 std::shared_ptrboost::shared_ptr
  • 通知机制: 自实现 Observer/Observable + 可选 Boost.Signals2(线程安全模式)
  • 构建系统: CMake(首选)+ Autotools(遗留)
  • 可选依赖: Boost(多项组件)

1.2 模块全景

ql/
├── patterns/          (7 files)   ← 设计模式核心:Observer, LazyObject, Singleton
├── time/              (70+ files) ← 日期时间:Date, Calendar(49种), DayCounter(13种), Schedule
├── utilities/         (14 files)  ← 工具类:ObservableValue, Clone, Null, DataFormatters
├── math/              (100+ files)← 数值算法:插值(20+), 优化器, 随机数, 分布, 积分, 矩阵
├── currencies/        (86 货币)   ← 货币体系:Flyweight Currency, ExchangeRate, 图搜索转换
├── quotes/            (10 files)  ← 市场报价:SimpleQuote, DerivedQuote, 隐含波动率反解
├── termstructures/    (100+ files)← 期限结构:Yield, Vol, Credit, Inflation 曲线+自举
├── indexes/           (70+ files) ← 指数体系:Ibor, OIS, Swap, Inflation, Equity
├── processes/         (22 files)  ← 随机过程:BS, Heston, OU, CIR, Hull-White, Bates
├── models/            (50+ files) ← 模型参数化:短利率, 权益, 市场模型(LMM/SMM), 波动率
├── methods/           (180+ files)← 数值方法:有限差分(81+59), 格点树(8+2), 蒙特卡洛(14+4)
├── cashflows/         (67 files)  ← 现金流:Coupon, FloatingRateCoupon+Pricer, Leg Builders
├── instruments/       (84+ files) ← 金融工具:Option, Swap, Bond, CDS, Forward, CapFloor
├── pricingengines/    (200+ files)← 定价引擎:15子目录, 数百引擎, 策略模式核心
├── experimental/      (28 子目录) ← 实验特性:信用, 商品, 扩展波动率, CMS价差等
└── legacy/            (30 files)  ← 遗留代码:旧版LMM(2005-2006), 已被marketmodels/替代

2. 整体架构

2.1 分层架构图

graph TD
    subgraph L1["第1层 基础设施"]
        A1["types.hpp 类型别名"]
        A2["errors.hpp 错误处理"]
        A3["qldefines.hpp 编译配置"]
        A4["shared_ptr.hpp 智能指针"]
    end

    subgraph L2["第2层 设计模式核心"]
        B1["patterns/ Observer-Observable"]
        B2["patterns/ LazyObject"]
        B3["patterns/ Singleton"]
        B4["handle.hpp Handle"]
    end

    subgraph L3["第3层 基础模块"]
        C1["time/ 日期与时间"]
        C2["utilities/ 工具类"]
        C3["math/ 数值算法"]
        C4["currencies/ 货币体系"]
    end

    subgraph L4["第4层 市场数据层"]
        D1["quotes/ 市场报价"]
        D2["termstructures/ 期限结构"]
        D3["indexes/ 指数体系"]
    end

    subgraph L5["第5层 过程与模型层"]
        E1["processes/ 随机过程"]
        E2["models/ 模型参数化"]
    end

    subgraph L6["第6层 数值方法层"]
        F1["finitedifferences/ FD"]
        F2["lattices/ 格点树"]
        F3["montecarlo/ MC"]
    end

    subgraph L7["第7层 工具与引擎层"]
        G1["cashflows/ 现金流"]
        G2["instruments/ 金融工具"]
        G3["pricingengines/ 定价引擎"]
    end

    subgraph L8["第8层 实验与遗留"]
        H1["experimental/ 实验模块"]
        H2["legacy/ 遗留LMM"]
    end

    L2 --> L3
    L3 --> L4
    L3 --> L5
    L4 --> L5
    L4 --> L6
    L5 --> L6
    L5 --> L7
    L6 --> L7
    G1 --> G2
    G2 --> G3
    G3 --> G2
    L7 --> L8

2.2 数据流全景:从市场报价到定价结果

graph LR
    subgraph SRC["数据源"]
        Q["SimpleQuote<br/>市场报价原子单元"]
        F["Fixing<br/>历史定息"]
    end

    subgraph BUILD["曲线构建"]
        BH["BootstrapHelper<br/>报价到误差函数"]
        TS["TermStructure<br/>自举和插值"]
    end

    subgraph CHAIN["估值链"]
        IDX["Index<br/>历史与远期决策"]
        PRO["StochasticProcess<br/>SDE漂移和扩散"]
        MDL["CalibratedModel<br/>参数和校准"]
        ENG["PricingEngine<br/>定价算法"]
        CF["CashFlow<br/>现金流计算"]
        INST["Instrument<br/>NPV and Greeks"]
    end

    subgraph NUM["数值方法"]
        FD["有限差分 PDE"]
        LT["格点与树"]
        MC["蒙特卡洛"]
    end

    Q -->|Observer| BH
    F -->|IndexManager| IDX
    BH -->|Brent求根| TS
    TS -->|Handle| IDX
    TS -->|Handle| PRO
    PRO -->|observer| MDL
    MDL -->|calibrate| ENG
    PRO --> FD
    PRO --> LT
    PRO --> MC
    TS -->|Handle| ENG
    IDX -->|fixing| CF
    CF -->|Leg| INST
    ENG -->|calculate| INST
    FD --> ENG
    LT --> ENG
    MC --> ENG

核心数据流: Quote 变化 → BootstrapHelper::update() → TermStructure::update() → Index::update() → FloatingRateCoupon::update() → Instrument::update() → NPV() 被访问时 LazyObject 自动重算。


3. 各层模块详解

3.1 第1层:基础设施

文件 用途 关键内容
ql/qldefines.hpp 配置宏定义 QL_DEPRECATED, QL_ENABLE_SESSIONS, QL_HIGH_RESOLUTION_DATE, QL_NULL_AS_FUNCTIONS
ql/userconfig.hpp 用户可配置编译选项 QL_USE_STD_SHARED_PTR, QL_ENABLE_THREAD_SAFE_OBSERVER_PATTERN, QL_ENABLE_TRACING, QL_USE_INDEXED_COUPON
ql/types.hpp 类型别名 Real=double, Integer=int, Size=std::size_t, Time=Real, Rate=Real, Volatility=Real, DiscountFactor=Real
ql/errors.hpp 错误处理宏 QL_REQUIRE(cond,msg) 前置条件, QL_ENSURE(cond,msg) 后置条件, QL_FAIL(msg) 无条件错误
ql/shared_ptr.hpp 智能指针 ext::shared_ptr<T> = std::shared_ptr<T>boost::shared_ptr<T>, ext::make_shared<T>

3.2 第2层:设计模式核心(ql/patterns/ + ql/handle.hpp)

3.2.1 核心类总览

classDiagram
    class Observable {
        -set~Observer*~ observers_
        +notifyObservers()
        -registerObserver(Observer*)
        -unregisterObserver(Observer*)
    }

    class Observer {
        -set~shared_ptr~Observable~~ observables_
        +registerWith(shared_ptr)
        +unregisterWithAll()
        +update()*
        +deepUpdate()
    }

    class LazyObject {
        -bool calculated_
        -bool frozen_
        -bool failed_
        -bool alwaysForward_
        +calculate()
        +recalculate()
        +freeze() / unfreeze()
        +update()
        #performCalculations()*
    }

    class ObservableSettings {
        -map deferredObservers_
        -bool updatesEnabled_
        -bool updatesDeferred_
        +disableUpdates(bool deferred)
        +enableUpdates()
    }

    class Singleton~T~ {
        +static instance() T&
    }

    class Handle~T~ {
        -shared_ptr~Link~ link_
        +operator->()
        +currentLink()
        +empty()
    }

    class RelinkableHandle~T~ {
        +linkTo(shared_ptr)
    }

    Observable <|-- LazyObject : virtual
    Observer <|-- LazyObject : virtual
    Singleton <|-- ObservableSettings
    Handle <|-- RelinkableHandle
    Singleton <|-- Settings
    Singleton <|-- IndexManager

3.2.2 Observable/Observable — 数据流自动传播

这是 QuantLib 最核心的架构模式。所有依赖链上的对象都参与此模式。

关键设计决策:

  • Observable::observers_ 存储 Observer* 原始指针,避免 shared_ptr 循环引用
  • 复制构造函数不复制观察者集合 — 新对象以无人观察的状态开始
  • 移动操作被显式删除 — 因为观察者持有指向被观察者的原始指针,移动会使已有观察者的指针悬空
  • Observer::~Observer() 自动调用 unregisterWithAll(),确保即使是 Observer 先于 Observable 销毁也不留悬空指针
  • LazyObject 使用虚继承解决菱形继承问题(Instrument 继承 LazyObject,PricingEngine 继承 Observer+Observable)

通知传播链(端到端):

SimpleQuote::setValue(newValue)
  → Observable::notifyObservers()
    → (检查 ObservableSettings: 如果 updatesDisabled → 直接返回)
    → (如果 updatesDeferred → 注册为延迟通知,稍后 enableUpdates() 批量触发)
    → observer->update()
      → LazyObject::update() → calculated_ = false
        → if calculated_ or failed_ was true: notifyObservers() 传播到下游
          → Instrument::update() → calculated_ = false

全局控制: ObservableSettings::instance().disableUpdates(true) 全局推迟通知(批量更新优化),然后 enableUpdates() 一次性触发所有累积通知。

3.2.3 LazyObject — 按需计算与结果缓存

stateDiagram-v2
    [*] --> Dirty : 构造
    Dirty --> Calculating : calculate()
    Calculating --> Clean : performCalculations() 成功
    Calculating --> Failed : performCalculations() 抛异常
    Clean --> Dirty : update() 依赖变化
    Failed --> Dirty : update() 依赖变化
    Dirty --> Frozen : freeze()
    Clean --> Frozen : freeze()
    Frozen --> Dirty : unfreeze() + 补发通知

关键设计: calculate() 在调用 performCalculations() 之前设置 calculated_ = true。这是因为在自举(bootstrapping)过程中,计算债券曲线时可能需要查询同一曲线上的中间点折扣因子。如果 calculated_ 仍然为 false,这些中间点查询会触发另一个 calculate() 调用,导致无限递归。

冻结机制: freeze() 临时阻止重算和通知传播;unfreeze() 恢复并补发通知。用于批量操作场景。

递归防护: update() 使用 RAII UpdateChecker 检测循环依赖。QL_THROW_IN_CYCLES 控制是抛异常还是静默返回。

3.2.4 Handle/RelinkableHandle — 间接引用与自动通知

// Handle 内部包含一个继承自 Observable+Observer 的 Link 对象
// 当 Handle 重新链接到新对象时,Link 通知所有观察者
// 当被链接的对象本身改变时,通知也通过 Link 传播

Handle<YieldTermStructure> curveHandle(someCurve);
// 注册为 curveHandle 的观察者
engine->registerWith(curveHandle);

// 方式1:重新链接 → Link 通知所有观察者
curveHandle.linkTo(newCurve);

// 方式2:曲线本身变化 → 通过 Link 传播到观察者
someCurve->notifyObservers();

Handleql/termstructures/, ql/indexes/, ql/models/, ql/processes/, ql/quotes/ 等模块的标准引用方式,支持运行时重连和自动脏标记。


3.3 第3层:基础模块

3.3.1 time/ — 日期与时间(70+ 文件)

classDiagram
    class Date {
        -int_fast32_t serialNumber_  (距1899-12-31天数)
        +weekday() Weekday
        +dayOfMonth() Integer
        +month() Month
        +year() Year
        +operator+(Period) Date
        +operator-(Date) BigNatural
        +todaysDate()$ Date
        +minDate()$ Date (1901-01-01)
        +maxDate()$ Date (2199-12-31)
        +endOfMonth(Date)$ Date
        +nthWeekday(n,w,m,y)$ Date
    }

    class Period {
        -Integer length_
        -TimeUnit units_
        +length() Integer
        +units() TimeUnit
        +frequency() Frequency
        +normalize() Period (24Months to 2Years)
    }

    class Calendar {
        -shared_ptr~Impl~ impl_
        +isBusinessDay(Date) bool
        +isHoliday(Date) bool
        +adjust(Date, BDC) Date
        +advance(Date,n,unit,BDC) Date
        +businessDaysBetween(d1,d2) Integer
        +addHoliday(Date) / +removeHoliday(Date)
    }

    class DayCounter {
        -shared_ptr~Impl~ impl_
        +yearFraction(d1,d2,refStart,refEnd) Time
        +dayCount(d1,d2) Integer
    }

    class Schedule {
        -vector~Date~ dates_
        -vector~bool~ isRegular_
        +size() Size
        +at(i) Date
        +isRegular(i) bool
        +startDate() / endDate() Date
    }

    Date --> Period : arithmetic
    Calendar --> Date : adjusts
    DayCounter --> Date : computes
    Calendar *-- CalendarImpl : Bridge, 49+ 日历实现
    DayCounter *-- DayCounterImpl : Bridge, 13+ 计数约定

设计模式:

组件 模式 说明
Date 不可变值类型 算术返回新对象,线程安全。序数=距1899-12-31天数,weekday() = serial % 7
Calendar Bridge 句柄 + shared_ptr<Impl>,49个日历通过 WesternImpl/OrthodoxImpl/独立Impl 实现
DayCounter Bridge 句柄 + shared_ptr<Impl>,13种约定:Actual360, Actual365Fixed, ActualActual(ISDA/ISMA), Thirty360(USA/BondBasis), Business252 等
Schedule Builder MakeSchedule().from(d1).to(d2).withTenor(tenor)... 流式构建,支持12+参数

Calendar 假日判断优先级:

  1. addedHolidays(用户显式添加的假日)→ 非业务日
  2. removedHolidays(用户显式移除的假日)→ 业务日
  3. Impl::isBusinessDay() 虚拟函数 → 由具体实现判断

Calendar 实现层次:

  • WesternImpl → US(Settlement,NYSE,GovBond,SOFR,NERC,FedWire), UK, DE, FR, IT, CA, AU, JP, CN, HK, SG, IN, BR, MX…
  • OrthodoxImpl → RU, UA, MK(东正教复活节)
  • 独立Impl → SA(Tadawul:Thu+Fri), TW(Tsec)
  • JointCalendar::Impl → 组合2-4个日历(JoinHolidays并集/JoinBusinessDays交集)
  • BespokeCalendar::Impl → 用户自定义

Schedule 日期生成时序:

  1. 用 NullCalendar 生成种子日期(不受假日影响)
  2. 对每个种子日期应用 BDC adjust(ModifiedFollowing, Preceding 等)
  3. 标记 isRegular(比较实际周期 vs 名义 tenor)
  4. 处理 endOfMonth, firstDate, nextToLastDate 等特例

3.3.2 utilities/ — 工具类(14 文件)

组件 用途 关键特性
ObservableValue<T> 可观察值包装 赋值即通知(operator= → notifyObservers),Settings 中 evaluationDate 基于此类
Clone<T> 深度克隆代理 拷贝即克隆(需 T::clone()→unique_ptr),市场模型状态演化中大量使用
Null<T> 类型安全空值哨兵 替代 NaN(NaN != NaN 破坏等价关系),float→float::max, int→int::max
DataFormatters I/O 格式化 io::rate(0.05)→"5.00%", io::percent(0.25)→"25.00%", io::ordinal(1)→"1st"
DataParsers 字符串解析 PeriodParser::parse("1Y3M"), DateParser::parseISO("2024-06-15")
step_iterator 步进迭代器 网格/时间序列上以固定步长迭代
Tracing 调试追踪 QL_TRACE 仅在 QL_ENABLE_TRACING 定义时生效,零运行时开销

3.3.3 math/ — 数值算法(100+ 文件)

classDiagram
    class Interpolation {
        +operator()(x) Real
        +primitive(x) Real
        +derivative(x) Real
        +secondDerivative(x) Real
        +xMin() / xMax() Real
    }

    class OptimizationMethod {
        <<abstract>>
        +minimize(problem, criteria)* EndCriteria::Type
    }

    class Solver1D {
        +solve(f, accuracy, guess, xMin, xMax) Real
    }

    class Statistics {
        +add(value, weight)
        +mean() / variance() / skewness() / kurtosis()
        +errorEstimate() (= stdDev/sqrt(N))
    }

    OptimizationMethod <|-- LevenbergMarquardt : 阻尼最小二乘
    OptimizationMethod <|-- Simplex : Nelder-Mead 无需梯度
    OptimizationMethod <|-- ConjugateGradient
    Solver1D <|-- Brent : 自举中最常用
    Solver1D <|-- FiniteDifferenceNewtonSafe : 牛顿+边界保护

核心子模块:

子模块 规模 关键内容
interpolations/ 20+ 插值器 Linear, LogLinear, BackwardFlat, Cubic, MonotonicCubic, ConvexMonotone, SABR, Kruger
optimization/ 5+ 优化器 LevenbergMarquardt (阻尼LS), Simplex (NelderMead), ConjugateGradient
randomnumbers/ 多种生成器 MersenneTwister, PseudoRandom, BoxMuller, Ziggurat, Sobol(低差异)
distributions/ 分布函数 Normal, BivariateNormal, ChiSq, NonCentralChiSq, Student, Gamma
integrals/ 数值积分 GaussKronrodAdaptive, GaussLobatto
solvers1d/ 1D 求根 Brent (二分+割线+逆二次), Bisection, Newton, FiniteDifferenceNewtonSafe
statistics/ 统计累加器 Statistics, IncrementalStatistics (单遍在线), RiskStatistics (VaR, ES)
matrixutilities/ 矩阵分解 QR, SVD, Cholesky, LU
ode/ ODE 求解器 用于 FD 方法中的时间离散
copulas/ Copula 分布 用于信用衍生品

插值器选型指南:

插值器 适用场景
Linear 通用,C0 连续
LogLinear DiscountCurve(分段常数瞬时远期)
BackwardFlat ForwardCurve, HazardRate 曲线(右连续)
Cubic 需要 C2 平滑时
MonotonicCubic 单调保持(Hyman 1983),避免振荡
ConvexMonotone 正值保持(Hagan-West 2006),远期利率曲线首选
SABR SABR 波动率微笑插值
Kruger 无套利波动率插值

Interpolation/Interpolator 分离设计:

// Interpolator 在构造时选择算法(工厂)
// Interpolation 在运行时只做评估(轻量级对象,O(log N) 搜索 + O(1) 计算)
auto interp = Linear().interpolate(x.begin(), x.end(), y.begin());
Real y = interp(x);  // 运行时高效

3.3.4 currencies/ — 货币体系(86 货币 + 汇率转换)

classDiagram
    class Currency {
        -shared_ptr~Data~ data_
        +name() / code() / numericCode()
        +triangulationCurrency() Currency
        +empty() bool
        +rounding() Rounding
    }

    class CurrencyData {
        +string name, code, symbol
        +Integer numeric, fractionsPerUnit
        +Rounding rounding
        +Currency triangulated
    }

    class ExchangeRate {
        +Type Direct / Derived
        +Currency source() / target()
        +Decimal rate()
        +Money exchange(Money) (双向)
        +chain(r1,r2)$ ExchangeRate (二叉树组合)
    }

    class ExchangeRateManager {
        +add(rate, startDate, endDate)
        +lookup(src,tgt,date) ExchangeRate
        +clear()
        -addKnownRates() (欧元遗留, TRY/TRL, RON/ROL)
    }

    Currency *-- CurrencyData : Flyweight, 所有同币种实例共享不可变Data
    ExchangeRate --> Currency : source/target
    ExchangeRateManager --> ExchangeRate : data_ entries

关键设计模式:

  1. Flyweight 享元模式: 所有 USDCurrency 实例共享同一个 static shared_ptr<Data>,内存高效
  2. Thin Concrete Class: 每个货币子类仅3行代码,所有参数在构造时传入基类
  3. 汇率查找算法(图搜索+三角转换):
    lookup(src,tgt,date):
    1. src==tgt? → 返回 1.0
    2. 直接查找: data_ 中存在 src→tgt? → 返回
    3. 三角转换: src 有 triangulationCurrency? → src→link + link→tgt
    4. 逆向三角: tgt 有 triangulationCurrency? → src→link + link→tgt
    5. BFS 图搜索: 在所有已知汇率中搜索转换路径
    6. 返回链式汇率或抛异常

货币分布: Africa(14), America(17), Asia(27), Europe(40 含16种欧元遗留), Oceania(2), Crypto(8)

非 ISO 货币: MXV (墨西哥通胀单位), COU (哥伦比亚实际价值单位), CLF (智利通胀单位)


3.4 第4层:市场数据层

3.4.1 quotes/ — 市场报价(Observer 树叶节点层)

Quote 是所有市场数据的原子单元。任何市场数据变化从 Quote 开始,逐级向上传播。

classDiagram
    class Quote {
        <<abstract>>
        +value()* Real
        +isValid()* bool
    }

    class SimpleQuote {
        -Real value_
        +setValue(Real) (赋值 to notifyObservers)
        +reset() (value_=Null)
    }

    class DerivedQuote~F~ {
        -Handle~Quote~ element_
        -F f_ (函数对象)
        +value() = f(element_->value()) (缓存)
        +update() cache=Null + notify
    }

    class CompositeQuote~F~ {
        -Handle~Quote~ e1_, e2_
        -F f_ (二元函数对象)
        +value() = f(e1_->value(), e2_->value())
    }

    class ImpliedStdDevQuote {
        -Handle~Quote~ forward_, price_
        -Real strike_, guess_
        +value() blackFormulaImpliedStdDev (反解BS)
    }

    class ForwardSwapQuote {
        -SwapIndex swapIndex_
        -Handle~Quote~ spread_
        +value() createSwap + fairRate
    }

    Quote <|-- SimpleQuote
    Quote <|-- DerivedQuote
    Quote <|-- CompositeQuote
    Quote <|-- ImpliedStdDevQuote : LazyObject
    Quote <|-- ForwardSwapQuote : LazyObject
    Quote <|-- ForwardValueQuote : Observer
    Quote <|-- LastFixingQuote : Observer

三种通知策略:

策略 Quote 类型 update() 行为
直接转发 DeltaVolQuote, ForwardValueQuote notifyObservers() 直接传播
缓存失效 DerivedQuote, CompositeQuote value_=Null + notifyObservers()
LazyObject ImpliedStdDevQuote, ForwardSwapQuote calculated_=false + 条件通知

函数组合示例:

// S → f(S) = S*exp(rT) → 远期价格
auto fwdQuote = DerivedQuote(spotHandle, [](Real S){ return S * exp(0.05*1.0); });

// (F, vol) → BS(F, K, vol, T) → 期权价格
auto optPrice = CompositeQuote(fwdHandle, volHandle,
    [](Real F, Real vol){ return blackFormula(Call, K, F, vol*sqrt(T)); });

// spot 变化 → fwd 自动重算 → option price 自动重算
spotQuote->setValue(110.0);

3.4.2 termstructures/ — 期限结构(100+ 文件,最大模块)

核心架构理念:三策略分离 — Traits(自举什么数据:Discount/ZeroYield/ForwardRate)× Interpolator(如何插值:Linear/LogLinear/Cubic)× Bootstrap(什么算法:IterativeBootstrap/GlobalBootstrap)。

3.4.2.1 收益率曲线 — 四层适配器链
classDiagram
    class TermStructure {
        +referenceDate() / maxDate()
        +dayCounter() / calendar()
        +update()
    }

    class YieldTermStructure {
        +discount(Date) DiscountFactor
        +zeroRate(Date) InterestRate
        #discountImpl(Time)* DiscountFactor
    }

    class ZeroYieldStructure {
        #zeroYieldImpl(Time)* Rate
        #discountImpl(Time) = exp(-zeroYield*T)
    }

    class InterpolatedZeroCurve {
        -vector times_ / data_
        -Interpolation interpolation_
        #zeroYieldImpl(Time) = interpolation_(t)
    }

    class PiecewiseYieldCurve~Traits,Interp,Bootstrap~ {
        -vector helpers_
        +performCalculations() bootstrap.run()
    }

    TermStructure <|-- YieldTermStructure
    YieldTermStructure <|-- ZeroYieldStructure
    ZeroYieldStructure <|-- InterpolatedZeroCurve
    InterpolatedZeroCurve <|-- PiecewiseYieldCurve

四层职责:

  1. YieldTermStructure — 纯虚 discountImpl(Time) + 公共 discount/zeroRate 接口
  2. ZeroYieldStructure — 改编:discountImpl(t) = exp(-zeroYieldImpl(t) * t),新增纯虚 zeroYieldImpl
  3. InterpolatedZeroCurve<Interpolator> — 添加插值,zeroYieldImpl(t) = 插值器(t)
  4. PiecewiseYieldCurve<Traits, Interp, Bootstrap> — 添加自举 (LazyObject),performCalculations() 运行 bootstrap
3.4.2.2 BootstrapHelper — 自举辅助工具
classDiagram
    class BootstrapHelper~TS~ {
        -Handle~Quote~ quote_
        +quoteError()* Real (modelValue - marketValue)
        +setTermStructure(TS*) (自举迭代过程中动态设置)
    }

    BootstrapHelper <|-- RateHelper : TS=YieldTermStructure
    BootstrapHelper <|-- DefaultProbabilityHelper : TS=DefaultProbabilityTS
    RateHelper <|-- DepositRateHelper : 1+rate*yf = 1/disc
    RateHelper <|-- FraRateHelper : 远期利率一致性
    RateHelper <|-- SwapRateHelper : swap fairRate = quote
    RateHelper <|-- BondHelper : bond cleanPrice = quote
    DefaultProbabilityHelper <|-- SpreadCdsHelper : cds fairSpread = quote

自举核心流程:

PiecewiseYieldCurve::performCalculations():
  1. sort helpers by pillar date
  2. init dates[] and times[] from helpers
  3. set initial guess data[] based on Traits::initialValue()
  4. for each pillar i (从短端到长端):
       a. setTermStructure(curve*) on helper i
       b. Brent::solve(f(x) = helper.quoteError() = 0, xMin, xMax)
       c. Traits::updateGuess(data_, root, i)
       d. interpolation_.update()
  5. calculated_ = true

每次 Brent f(x) 评估触发后面 pillars 的自举 → O(n²) 复杂度
3.4.2.3 Curve Traits — 自举策略
Traits 自举内容 初始值 典型用途
Discount 折扣因子 initialValue=1.0 收益曲线: PiecewiseYieldCurve<Discount, LogLinear>
ZeroYield 零利率 initialValue=0.05 零利率曲线: PiecewiseYieldCurve<ZeroYield, Cubic>
ForwardRate 瞬时远期 initialValue=0.05 远期曲线: PiecewiseYieldCurve<ForwardRate, BackwardFlat>
SurvivalProbability 生存概率 initialValue=1.0 信用曲线
HazardRate 风险率 initialValue=0.01 风险率曲线

三种参考日期策略(TermStructure 基类):

  • 固定日期: 构造时指定 refDate,永不变化
  • 滚动日期: referenceDate() 跟随 Settings.evaluationDate() + settlementDays
  • 纯虚: 子类实现自己的 referenceDate()
3.4.2.4 波动率曲面体系
classDiagram
    class VolatilityTermStructure {
        +minStrike() / maxStrike()
        +volatilityType()
    }

    class BlackVolTermStructure {
        +blackVol(Date, Strike) Volatility
        #blackVolImpl(Time, Strike)* Volatility
    }

    class BlackVarianceCurve {
        -mutable Interpolation varianceCurve_
        #blackVolImpl(t, strike) = sqrt(interp(t))
    }

    class BlackVarianceSurface {
        -mutable Interpolation2D varianceSurface_
        #blackVolImpl(t, strike) = sqrt(interp(t, k))
    }

    class SmileSection {
        <<abstract>>
        +volatility(strike)* Volatility
        +atmLevel() Real
        +exerciseDate() / dayCounter()
    }

    VolatilityTermStructure <|-- BlackVolTermStructure
    BlackVolTermStructure <|-- BlackVarianceCurve : 1D 时间维度
    BlackVolTermStructure <|-- BlackVarianceSurface : 2D 时间x行权价
    SmileSection <|-- SabrSmileSection
    SmileSection <|-- InterpolatedSmileSection
    SmileSection <|-- FlatSmileSection

波动率曲面体系包含:

  • BlackVolTermStructure — 权益/FX 类 Black 波动率
  • SwaptionVolatilityStructure — 互换期权波动率矩阵
  • OptionletVolatilityStructure — Cap/Floor 用 Optionlet 波动率
  • CapFloorTermVolatilityStructure — Cap/Floor 整体波动率
  • LocalVolTermStructure — 局部波动率(Dupire)

常用曲线快捷 typedef:

Typedef 完整类型
DiscountCurve InterpolatedDiscountCurve<LogLinear>
ZeroCurve InterpolatedZeroCurve<Linear>
ForwardCurve InterpolatedForwardCurve<BackwardFlat>
RateHelper BootstrapHelper<YieldTermStructure>

3.4.3 indexes/ — 指数体系(70+ 文件)

Index 是市场数据和金融工具之间的关键中间层。它同时是 Observer(观察 TermStructure 变化)和 Observable(向 Coupon/Engine 广播变化)

classDiagram
    class Index {
        <<abstract, Observable+Observer>>
        +name()* string
        +fixingCalendar()* Calendar
        +fixing(Date,bool)* Real
        +addFixing(Date,Real)
        +pastFixing(Date) Real
        +update() = notifyObservers()
    }

    class InterestRateIndex {
        <<abstract>>
        +familyName() / tenor() / fixingDays() / currency()
        +forecastFixing(Date)* Rate
        +maturityDate(Date)* Date
        +fixing(Date,bool) Real (★ Template Method)
    }

    class IborIndex {
        -Handle~YieldTermStructure~ termStructure_
        +forecastFixing(Date) = (disc/disc-1)/t
        +clone(Handle)* shared_ptr (★ Clone模式)
    }

    class SwapIndex {
        -shared_ptr~IborIndex~ iborIndex_
        -Handle~YieldTermStructure~ discount_
        +forecastFixing(Date) createSwap to setEngine to fairRate()
        +underlyingSwap(Date) shared_ptr
    }

    class IndexManager {
        -map name to TimeSeries~Real~ data_
        -map name to shared_ptr~Observable~ notifiers_
        +getHistory(name) / setHistory(name, ts)
        +addFixings(dates, values)
        +notifier(name) shared_ptr (延迟创建)
    }

    Index <|-- InterestRateIndex
    Index <|-- InflationIndex
    InterestRateIndex <|-- IborIndex
    InterestRateIndex <|-- SwapIndex
    IborIndex <|-- OvernightIndex
    Index --> IndexManager : 定息存储代理

fixing() Template Method 决策流程:

sequenceDiagram
    participant Caller
    participant Idx as InterestRateIndex
    participant IM as IndexManager
    participant TS as TermStructure

    Caller->>Idx: fixing(fixDate, forecastTodaysFix)

    alt fixDate < today
        Idx->>IM: pastFixing(fixDate) = 历史值
    else fixDate == today
        Idx->>IM: pastFixing(fixDate)
        alt 历史值存在
            IM-->>Idx: 历史值
        else forecastTodaysFix==true
            Idx->>TS: discount(valDate), discount(matDate)
            Idx->>Idx: forecastFixing() = 远期预测
        end
    else fixDate > today
        Idx->>TS: discount(valDate), discount(matDate)
        Idx->>Idx: forecastFixing() = 远期预测
    end

    Idx-->>Caller: fixing 结果

关键设计模式:

  1. Thin Concrete Class 模式: 每个具体指数仅3行代码。例如 Euribor6M 构造时传 Period(6,Months),所有其他参数(货币=EUR, 日历=TARGET, DC=Act360)在 Euribor 基类中硬编码
  2. Clone 模式: iborIndex->clone(differentCurve) 创建共享相同约定但链接到不同远期曲线的新实例(定价引擎中频繁使用)
  3. IndexManager 作为定息中枢: 全局 Singleton,存储所有指数的历史定息。addFixing → notifier().notifyObservers() → 所有依赖该指数的对象自动 dirty
  4. 大小写不敏感键: IndexManager 使用 CaseInsensitiveCompare,"USDLibor" = "usdlibor"

SwapIndex 缓存机制: forecastFixing() 内部缓存 lastSwap_lastFixingDate_,重复查询相同 fixingDate 不重新创建 swap。


3.5 第5层:过程与模型层

3.5.1 processes/ — 随机过程(22 文件)

StochasticProcess 定义 SDE 的漂移和扩散,是模型和数值方法之间的桥梁。

classDiagram
    class StochasticProcess {
        <<abstract N-D, Observer+Observable>>
        +size()* Size
        +factors() Size
        +initialValues()* Array
        +drift(t,x)* Array
        +diffusion(t,x)* Matrix
        +evolve(t0,x0,dt,dw) Array
        +expectation(t0,x0,dt) Array
    }

    class StochasticProcess1D {
        <<abstract 1-D>>
        +x0()* Real
        +drift(t,x)* Real
        +diffusion(t,x)* Real
        +evolve(t0,x0,dt,dw) Real
        ★ 私有: N-D to 1-D 包装 (size=1 etc.)
    }

    class GeneralizedBlackScholesProcess {
        -Handle x0_, dividendTS_, riskFreeTS_, blackVolTS_
        +drift = (r-q)*S, diffusion = vol*S
        ★ 条件解析矩 (vol不依赖strike时)
        +forceDiscretization_ (强制使用离散化)
    }

    class HestonProcess {
        -Handle s0_, v0_
        -kappa, theta, sigma, rho
        Size=2, factors=2 (或3, 独立方差)
        ★ 8种离散化方案
    }

    class OrnsteinUhlenbeckProcess {
        -x0, speed, level, sigma
        ★ 解析矩 (绕过离散化)
    }

    class HullWhiteProcess {
        -shared_ptr~OUProcess~ ouProcess_
        ★ 组合模式而非继承: r(t)=OU(t)+alpha(t)
    }

    class G2Process {
        -shared_ptr~OUProcess~ xProcess_, yProcess_
        -Real rho_ (两因子相关)
    }

    StochasticProcess <|-- StochasticProcess1D
    StochasticProcess <|-- HestonProcess
    StochasticProcess <|-- G2Process
    StochasticProcess1D <|-- GeneralizedBlackScholesProcess
    StochasticProcess1D <|-- OrnsteinUhlenbeckProcess
    StochasticProcess1D <|-- CoxIngersollRossProcess
    HestonProcess <|-- BatesProcess : 加跳跃
    StochasticProcess1D <|-- HullWhiteProcess : 组合

过程特性总览:

过程 维度 因子 解析矩 自定义 evolve 典型用途
GBS (BS,BSM,Black,GK) 1 1 条件 Yes 标准欧式期权
Ornstein-Uhlenbeck 1 1 Yes No Hull-White 组件
CIR 1 1 Yes QE Scheme 利率/波动率建模
Hull-White 1 1 OU-based No 利率衍生品
Heston 2 2-3 No 8 Schemes 随机波动率期权
Bates 2 2-3 No Yes 带跳跃的Heston
G2 2 2 Yes No 双因子利率
Hybrid Heston-HW 3 3 No Yes 混合利率+权益
StochasticProcessArray N N 代理 No 多资产

Heston 8 种离散化方案(Discretization 枚举):
PartialTruncation, FullTruncation, Reflection, NonCentralChiSquareVariance, QuadraticExponential (推荐), QuadraticExponentialMartingale (QE+鞅修正), BroadieKayaExactSchemeLobatto, BroadieKayaExactSchemeLaguerre

离散化注入(策略模式):

// 所有 1D 过程的构造函数接受可选 discretization shared_ptr
auto process = BlackScholesProcess(spot, qTS, rTS, volTS,
    make_shared<EndEulerDiscretization>());  // 注入终点欧拉
// forceDiscretization_=true 强制使用离散化(忽略解析公式)

1D ↔ N-D 适配: StochasticProcess1D 私有地重写所有 N-D 方法(size()=1, drift()→Array(1) 等),使所有使用 N-D 接口的代码(FD算子、MC)可以透明地处理 1D 过程。

3.5.2 models/ — 模型参数化(50+ 文件)

QuantLib 有两套独立的模型世界

classDiagram
    class CalibratedModel {
        -vector~Parameter~ arguments_
        +calibrate(helpers, method, criteria)
        +params() / setParams(Array)
        +constraint() Constraint
        +update() generateArguments+notifyObservers
        #generateArguments()*
    }

    class OneFactorAffineModel {
        <<abstract>>
        +A(t,T)* / B(t,T)*
        discountBond = exp(A - B*x)
    }

    class Vasicek {
        -r0, a, b, sigma, lambda
        +解析 A(t,T), B(t,T)
        +内嵌 Dynamics = OUProcess
    }

    class HullWhite {
        -Parameter phi_ (时变均值回复)
        +generateArguments() fit国债曲线
    }

    class HestonModel {
        -HestonProcess process_
        +FellerConstraint (2*kappa*theta >= sigma²)
    }

    class MarketModel {
        <<interface>>
        +pseudoRoot(i)* Matrix
        +numberOfSteps()* Size
        +numberOfRates()* Size
    }

    class MarketModelEvolver {
        +startNewPath()*
        +advanceStep()*
        +currentState()* CurveState
    }

    class MarketModelMultiProduct {
        <<interface>>
        +possibleCashFlows()*
        +exerciseTimes()*
    }

    CalibratedModel <|-- OneFactorAffineModel
    OneFactorAffineModel <|-- Vasicek
    Vasicek <|-- HullWhite
    OneFactorAffineModel <|-- CIR
    CalibratedModel <|-- HestonModel
    CalibratedModel <|-- G2
    CalibratedModel <|-- Gaussian1dModel
    Gaussian1dModel <|-- Gsr : 分段 sigma + reversion

世界一:CalibratedModel(短期利率 + 权益)

  • 参数向量 + 优化器校准
  • update() = generateArguments() 重建内部状态 + notifyObservers() 广播
  • 每个模型内嵌 Dynamics 类(如 Vasicek::Dynamics 包含 OUProcess)
  • 校准流程:calibrate(helpers, method)CalibrationFunction(cost = Σ w_i * error_i²)OptimizationMethod::minimize()

世界二:MarketModel(LMM/SMM)+ MarketModelEvolver + MarketModelMultiProduct

  • pseudoRoot() 协方差矩阵分解 + Evolver (Euler/PC/IPC/Balland/SVD…) + CurveState (LMMCurveState/CoterminalSwapCurveState)
  • 支持 MultiProduct (复合产品: TARN, ratchet…), PathwiseGreeks, UpperBoundEngine (百慕大/可赎回)
  • 10+ 种 evolver, 多种状态表示,低差异序列支持

模型校准流程(LM 优化器):

sequenceDiagram
    participant CM as CalibratedModel
    participant LM as LevenbergMarquardt
    participant H as CalibrationHelper

    CM->>LM: minimize(costFunc, endCriteria)

    loop 每次 LM 迭代
        LM->>CM: setParams(x_new)
        CM->>CM: generateArguments() 重建状态
        CM->>CM: notifyObservers() 通知Helpers

        loop 每个 helper
            LM->>H: calibrationError()
            H->>H: modelValue() - marketValue()
        end

        LM->>LM: 数值差分计算 Jacobian
        LM->>LM: 解 (J^T J + λI) dx = -J^T f
        LM->>LM: x_{k+1} = x_k + dx
    end

    CM-->>CM: 校准完成

短期利率模型层次:

OneFactorModel
  ├─ Vasicek (r0, a, b, sigma, lambda) — 解析 A(t,T), B(t,T)
  │   └─ HullWhite (时变 phi) — TermStructureConsistentModel
  ├─ CIR (r0, theta, k, sigma) — 不同 B(t,T)
  └─ BlackKarasinski (log-normal short rate, 无 A/B)

TwoFactorModel
  └─ G2 (a, sigma, b, eta, rho + phi) — TermStructureConsistentModel

Gaussian1dModel (MarkovFunctional基类)
  └─ Gsr (分段常数 sigma + reversion)

3.6 第6层:数值方法层(ql/methods/)

3.6.1 有限差分(81 头文件 + 59 源文件)

架构层次:

Mesher (网格) → Operator (算子) → Scheme (离散方案) → BoundaryCondition + StepCondition → Solver (求解)

关键类:

classDiagram
    class Fdm1dMesher {
        +location(i) Real
        +dplus(i) / dminus(i) Real
    }

    class FdmLinearOpComposite {
        <<abstract>>
        +size()* Size (维度数)
        +apply_direction(d,r)* Array
        +solve_splitting(d,r,s)* Array
        +apply_mixed(r)* Array (混合导数项)
    }

    class FdmHestonOp {
        -EquityPart + VariancePart + MixedDerivative
    }

    class FdmBatesOp {
        -FdmHestonOp hestonOp_
        +apply_mixed() 添加 Gauss-Hermite 跳跃积分
    }

    class FdmBackwardSolver {
        +rollback(from, to, steps) (ADI 回滚)
    }

    class Fdm1DimSolver {
        -LazyObject
        +interpolateAt(x) Real
        +thetaAt(x) Real
    }

    Fdm1dMesher <|-- Uniform1dMesher
    Fdm1dMesher <|-- FdmBlackScholesMesher
    Fdm1dMesher <|-- FdmHestonVarianceMesher : 集中网格
    FdmLinearOpComposite <|-- FdmHestonOp
    FdmLinearOpComposite <|-- FdmBatesOp : 装饰器
    FdmBatesOp --> FdmHestonOp : composition

ADI 回滚流程(Heston 2D PDE):

每个 dt 步:
  1. BoundaryCondition::applyBeforeApplying(op, a)
  2. Operator::apply_mixed(a)  (混合导数项, 显式)
  3. 对每个方向 d:
     a. BoundaryCondition::applyBeforeSolving(op, a, d)
     b. Operator::solve_splitting(d, a, alpha*dt)  (三对角求解, 隐式)
     c. BoundaryCondition::applyAfterSolving(a, d)
  4. BoundaryCondition::applyAfterApplying(a)
  5. StepCondition::applyTo(a, t)  (如早期行权、障碍)

ADI 方案选择指南:

方案 维度 说明
Douglas 1D-3D 等价于 Crank-Nicolson (1D时)
CraigSneyd 2D 标准 ADI,Heston 常用
Hundsdorfer 2D-3D 更高精度 ADI
CrankNicolson 1D 标准二阶方案
TrBDF2 1D-3D 更强稳定性(L-stable)
MethodOfLines(eps, relInitStep) 1D-3D 自适应时步

3.6.2 格点/树(8 头文件 + 2 源文件)

CRTP 架构:

template <class Derived>
class BinomialTree : public Tree<Derived> { branches=2; };

// 具体树(通过 CRTP 编译时特化):
class JarrowRudd;          // 等概率, log-normal
class CoxRossRubinstein;   // 等跳跃, vol matching
class Tian;                // 三阶矩匹配
class LeisenReimer;        // 概率精炼 (收敛更快)

template <class Impl>
class TreeLattice : public Lattice, public CuriouslyRecurringTemplate<Impl> {
    void rollback(DiscretizedAsset&, Time to) const;
    Real presentValue(DiscretizedAsset&) const;
protected:
    vector<vector<Real>> statePrices_; // Arrow-Debreu 状态价格
};

Arrow-Debreu 状态价格 — 核心创新:

正向传播:statePrices[i+1][child(i,j,b)] += statePrices[i][j] * discount(i,j) * prob(i,j,b)
PV = dot(statePrices[t], assetValues[t])

优势:只需一次正向传递 + 一次 dot product,无需对每个节点反向折现

3.6.3 蒙特卡洛(14 头文件 + 4 源文件)

// 核心 MC 循环模板
template <class MC, class RNG, class S>
class MonteCarloModel {
    void addSamples(Real accuracy, Size maxSamples) const;
    const S& sampleAccumulator() const;  // Statistics 累加器
};

// Longstaff-Schwartz 最小二乘 Monte Carlo (LSM)
template <class PathType>
class LongstaffSchwartzPathPricer : public EarlyExercisePathPricer<PathType> {
    void calibrate();                     // 阶段1: 回归 (calibrationSamples)
    Real operator()(const PathType&) const; // 阶段2: 定价 (pricingSamples)
};

// 基函数系统 — LsmBasisSystem
// Monomial, Laguerre, Hermite, Hyperbolic, Legendre, Chebyshev, Chebyshev2nd

MC 收敛准则: errorEstimate = stdDev / sqrt(samples),2x精度需要4x样本。对偶变量和控制变量可减少方差。


3.7 第7层:工具与引擎层

3.7.1 cashflows/ — 现金流(67 文件,最大核心模块之一)

classDiagram
    class CashFlow {
        <<abstract, Event+LazyObject>>
        +date()* Date
        +amount()* Real
    }

    class Coupon {
        <<abstract>>
        +nominal()* Real
        +rate()* Rate
        +accrualStartDate()* / accrualEndDate()*
        +accruedAmount(Date)* Real
    }

    class FloatingRateCoupon {
        <<abstract>>
        -shared_ptr~InterestRateIndex~ index_
        -shared_ptr~FloatingRateCouponPricer~ pricer_
        -Real gearing_ / Spread spread_
        +setPricer(p) (可插拔定价器)
        +indexFixing() / adjustedFixing()
        #performCalculations() pricer_->swapletRate()
    }

    class CappedFlooredCoupon {
        -shared_ptr~FloatingRateCoupon~ underlying_
        -Rate cap_ / floor_
        +rate() = min(max(underlying->rate(), floor), cap)
    }

    class FloatingRateCouponPricer {
        <<abstract>>
        +swapletPrice()* / swapletRate()*
        +capletPrice(cap)* / capletRate(cap)*
        +floorletPrice(floor)* / floorletRate(floor)*
        +initialize(FloatingRateCoupon)*
    }

    CashFlow <|-- Coupon
    CashFlow <|-- SimpleCashFlow
    Coupon <|-- FixedRateCoupon
    Coupon <|-- FloatingRateCoupon
    FloatingRateCoupon <|-- IborCoupon
    FloatingRateCoupon <|-- CmsCoupon
    FloatingRateCoupon <|-- OvernightIndexedCoupon
    FloatingRateCoupon <|-- CappedFlooredCoupon : 装饰器
    FloatingRateCoupon <|-- DigitalCoupon : 装饰器
    FloatingRateCoupon --> FloatingRateCouponPricer : 策略模式

核心设计模式:

  1. 策略模式(Pricer): 同一息票可切换不同定价器

    • BlackIborCouponPricer → Black76 定价
    • LinearTsrPricer → 线性终端互换利率模型
    • HaganPricer → 静态复制 (CMS)
    • LognormalCmsRatePricer → 对数正态近似
  2. 装饰器模式: CappedFlooredCoupon 装饰 FloatingRateCoupon,在不修改底层息票的情况下添加期权特征

  3. Builder 模式: 流式构建完整的支付腿

    Leg iborLeg = IborLeg(schedule, euribor6m)
       .withNotionals(10000000)
       .withSpreads(0.001)
       .withCaps(0.05)
       .withFloors(0.0);
  4. CashFlows 静态分析函数: CashFlows::npv(leg, curve), CashFlows::bps(leg, curve), CashFlows::duration(leg, ...), CashFlows::yield(leg, price, ...)

3.7.2 instruments/ — 金融工具(84+ 文件)

classDiagram
    class Instrument {
        <<LazyObject>>
        -shared_ptr~PricingEngine~ engine_
        +NPV() / errorEstimate() / valuationDate()
        +setPricingEngine(engine) (策略模式)
        #setupArguments(args)*
        #fetchResults(results)*
        #performCalculations() reset to validate to calculate to fetch
    }

    class Option {
        +payoff() Payoff
        +exercise() Exercise
    }

    class OneAssetOption {
        +delta() / gamma() / theta() / vega() / rho()
    }

    class Swap {
        +legNPV(j) / legBPS(j)
        +deepUpdate() (优化通知图)
    }

    class Bond {
        +cleanPrice() / dirtyPrice() / yield()
        +accruedAmount() Real
    }

    class CreditDefaultSwap {
        +fairSpread() / fairUpfront()
        +impliedHazardRate() Real
    }

    Instrument <|-- Option
    Instrument <|-- Swap
    Instrument <|-- Bond
    Instrument <|-- CreditDefaultSwap
    Instrument <|-- Forward
    Instrument <|-- Stock
    Option <|-- OneAssetOption
    OneAssetOption <|-- VanillaOption
    OneAssetOption <|-- BarrierOption
    Option <|-- Swaption

Instrument-Engine 交互时序:

sequenceDiagram
    participant User
    participant Inst as Instrument
    participant LO as LazyObject
    participant Eng as PricingEngine
    participant MD as MarketData

    User->>Inst: NPV()
    Inst->>LO: calculate()

    alt isExpired()
        Inst->>Inst: setupExpired() NPV=0
    else not expired
        Inst->>Inst: performCalculations()
        Inst->>Eng: reset()
        Inst->>Eng: setupArguments(args) (填充 strike, dates...)
        Eng->>Eng: arguments.validate()
        Eng->>Eng: calculate()
        Note over Eng: 1. query Handles for market data
        Note over Eng: 2. run numerical method
        Note over Eng: 3. write results_.value, delta, gamma...
        Inst->>Eng: fetchResults(results) (读回计算结果)
    end
    Inst-->>User: NPV_

    Note over MD,Inst: 市场数据变化后:
    MD->>Eng: update() via Observer chain
    Eng->>Inst: notifyObservers()
    Inst->>LO: calculated_ = false

arguments/results 嵌套类(Bridge 模式):
每个 Instrument 子类定义专用的 argumentsresults 嵌套类:

class VanillaOption::arguments : public virtual PricingEngine::arguments {
    shared_ptr<Payoff> payoff;
    shared_ptr<Exercise> exercise;
};
class VanillaOption::results : public Instrument::results {
    Real delta, gamma, theta, vega, rho, dividendRho;
};
class VanillaOption::engine : public GenericEngine<VanillaOption::arguments,
                                                    VanillaOption::results> {};

跨模型工具的参数组合: Swaption::arguments 需要多重继承(钻石继承)来组合 FixedVsFloatingSwap::arguments 和 Option::arguments。使用虚继承解决菱形问题。

additionalResults 机制: results_.additionalResults["impliedVol"] = 0.234; 允许引擎返回任意命名数据,工具端通过 option.result<Real>("impliedVol") 查询。

simplifyNotificationGraph: 对于 Swap/Bond(很多现金流),通知链可能过长,此优化从每个现金流单独通知 → 统一通过 Index 和 Curve Handle 传播。

3.7.3 pricingengines/ — 定价引擎(200+ 文件,15 子目录)

classDiagram
    class PricingEngine {
        <<abstract, Observable>>
        +getArguments()* / getResults()*
        +reset()* / calculate()*
    }
    note for PricingEngine "嵌套类: arguments { validate() } / results { reset() }"

    class GenericEngine~Args,Results~ {
        -mutable Args arguments_
        -mutable Results results_
        ★ calculate() writes to mutable results_
    }

    class GenericModelEngine~Model,Args,Results~ {
        -Handle~Model~ model_
        +registerWith(model_) (Observer)
    }

    class McSimulation~MC,RNG,S~ {
        +calculate(accuracy, maxSamples)
        +pathPricer()* / pathGenerator()* / timeGrid()*
    }

    class BlackStyleSwaptionEngine~Spec~ {
        ★ Policy-Based: Black76Spec / BachelierSpec
    }

    PricingEngine <|-- GenericEngine
    GenericEngine <|-- GenericModelEngine
    GenericEngine <|-- AnalyticEuropeanEngine
    GenericEngine <|-- FdBlackScholesVanillaEngine
    GenericEngine <|-- BlackSwaptionEngine
    MCEuropeanEngine --|> GenericEngine
    MCEuropeanEngine --|> McSimulation : Mixin

核心设计模式:

  1. calculate() 是 const: 通过 mutable 结果成员实现。允许 Instrument 多次调用 NPV() 命中同一个缓存结果
  2. Policy-Based(编译时策略):
    template <class Spec>
    class BlackStyleSwaptionEngine : public Swaption::engine { ... };
    struct Black76Spec { Real value(...) { return blackFormula(...); } };
    struct BachelierSpec { Real value(...) { return bachelierBlackFormula(...); } };
    typedef BlackStyleSwaptionEngine<Black76Spec>  BlackSwaptionEngine;
    typedef BlackStyleSwaptionEngine<BachelierSpec> BachelierSwaptionEngine;
  3. Mixin(多重继承): MCEuropeanEngine 同时继承 GenericEngine + McSimulation
  4. GenericModelEngine: 泛型模板,持有 Handle<ModelType> 并注册为 Observer

引擎目录与类别:

目录 引擎数 类别
vanilla/ 44 Analytic, Binomial, FD(BS/Heston/Bates/CEV/SABR), MC, COS, BAW
barrier/ 19 Analytic, Binomial, FD, MC
asian/ 17 MC Discrete/Continuous, TurnbullWakeman, FD, Choi
swaption/ 16 Black, Bachelier, Jamshidian, G1d, G2, Tree, FD
swap/ 9 Discounting, CrossCurrency, CounterpartyAdj (CVA/DVA)
credit/ 4 MidPointCds, IntegralCds, IsdaCds
basket/ 17 Kirk, BjerksundStensland, DengLiZhou, FD 2D/ND, MC
bond/ 5 Discounting, Credit, MonteCarlo
capfloor/ 8 Analytic, FD, MC, Mixed
forward/ 4 Analytic, MC
inflation/ 5 CrossAsset, YearOnYear
quanto/ 4 Analytic, MC
cliquet/ 3 Analytic, MC
lookback/ 2 Analytic, FD
mclongstaffschwartz/ 2 LS PathPricer + Regression

3.8 第8层:实验与遗留

3.8.1 experimental/ — 实验特性(28 子目录)

关键实验模块:

子模块 内容 状态
credit/ CDO分层, 篮子模型, Gaussian/StudentCopula, 损失模型 最大实验模块
commodities/ Commodity, EnergySwap, EnergyFuture, CommodityCurve 完整商品交易框架
volatility/ No-Arb SABR (Doust 2012), SVI (Gatheral), SABR vol surface 新波动率模型
finitedifferences/ 电力/商品衍生品 VPP 求解器 扩展FD
coupons/ CMS 价差息票 扩展息票
shortrate/ 广义 Hull-White 扩展短期利率
processes/ 扩展随机过程 新过程
math/ Copula RNG, PSO 优化器 新数值算法

废弃模块(保留空头文件引导到主库):

averageois/  → 使用 ql/cashflows/overnightindexedcoupon.hpp
fx/          → 使用 ql/termstructures/ 和 ql/instruments/
risk/        → 已废弃,无替代
barrieroption/ → ql/instruments/doublebarrieroption.hpp (部分迁移)

3.8.2 legacy/ — 遗留 LMM(30 文件)

2005-2006 年 Klaus Spanderen 实现的旧版 Libor 市场模型,已被 ql/models/marketmodels/ (2006-2012+) 完全取代。

方面 遗留 (2005-2006) 现代替代 (2006-2012+)
设计 一体化模型为中心 分层: Model / Evolver / CurveState / Product
状态演化 单一预测-校正方案 10+ evolver (Euler, PC, IPC, Balland, SVD 等)
产品 无产品抽象 多步产品、复合产品、路径希腊字母
可赎回 完整百慕大/可赎回 (UpperBoundEngine, LSStrategy)
希腊字母 PathwiseGreeks, BumpInstrumentJacobian
生成器 MT + Sobol 低差异
模型范围 仅 Libor 远期 LMM, SMM, CMS 市场模型

保留原因: 向后兼容、测试对比、历史文档、简单场景下更易理解。


4. 跨切面架构模式

4.1 Observer 数据流端到端

SimpleQuote::setValue(0.055)
  → notifyObservers()
    → BootstrapHelper::update() → pillar dirty
      → PiecewiseYieldCurve::update()
        → LazyObject::calculated_ = false → notifyObservers()
          → InterestRateIndex::update() → notifyObservers()
            → FloatingRateCoupon::update() → calculated_ = false → notifyObservers()
              → Swap::update() → calculated_ = false → notifyObservers()
                → [客户端代码响应]

三种通知策略的统一视图:

策略 实现者 update() 行为
直接转发 Quote→Observer, Handle→Observer, Process→Observer notifyObservers()
缓存失效 + LazyObject LazyObject 子类 (TermStructure, Instrument, Coupon) calculated_=false + notifyObservers()
仅标记脏 Index, SimpleQuote, Handle::Link 各自内部处理

4.2 策略模式家族

策略 参数化内容 实现方式 示例
Instrument::engine 定价算法 运行时可插拔 VanillaOption::engine
Traits 自举数据类型 编译时模板参数 Discount, ZeroYield, ForwardRate
Interpolator 插值方法 工厂模式 Linear, LogLinear, Cubic, ConvexMonotone
Bootstrap 自举算法 编译时模板参数 IterativeBootstrap, GlobalBootstrap
discretization SDE 离散化 运行时注入 EulerDiscretization, EndEulerDiscretization
FdmSchemeDesc FD 时间离散 值对象选择器 Douglas, Hundsdorfer, CraigSneyd
FloatingRateCouponPricer 息票定价器 运行时可插拔 BlackIborCouponPricer, HaganPricer
Policy (Spec) 定价公式 编译时模板策略 Black76Spec, BachelierSpec
RNG 随机数生成器 编译时模板参数 PseudoRandom, SobolRsg

4.3 设计模式分布总图

模式 出现位置
Observer/Observable 全局: patterns/, quotes/, termstructures/, indexes/, instruments/, pricingengines/, processes/, cashflows/
LazyObject patterns/, instruments/, termstructures/, quotes/, methods/finitedifferences/
Singleton patterns/ → Settings, IndexManager, ExchangeRateManager, ObservableSettings, Tracing
Strategy instruments/→PricingEngine, cashflows/→Pricer, termstructures/→Traits/Interpolator/Bootstrap, processes/→discretization
Bridge (Pimpl) time/→Calendar/DayCounter, termstructures/→TermStructure
Flyweight currencies/→Currency
Decorator cashflows/→CappedFlooredCoupon/DigitalCoupon, methods/→FdmBatesOp装饰FdmHestonOp
Builder time/→MakeSchedule, cashflows/→IborLeg/FixedRateLeg/CmsLeg/OvernightLeg/InflationLeg, instruments/→MakeVanillaSwap, pricingengines/→MakeMCEuropeanEngine
Template Method LazyObject::calculate→performCalculations, InterestRateIndex::fixing(历史vs远期决策)
CRTP methods/lattices/→BinomialTree, patterns/→CuriouslyRecurringTemplate
Mixin pricingengines/→McSimulation
Policy-Based pricingengines/→BlackStyleSwaptionEngine<Spec>
Clone (Prototype) utilities/→Clone<T>, indexes/→IborIndex::clone(Handle)
Adapter processes/→StochasticProcess1D私有适配N-D接口, HullWhiteProcess组合OU+分离
Composite processes/→StochasticProcessArray, time/→JointCalendar, quotes/→CompositeQuote

5. 模块依赖矩阵

graph TD
    subgraph CORE["核心基础设施"]
        types["types.hpp"]
        errors["errors.hpp"]
        qldefines["qldefines.hpp"]
        userconfig["userconfig.hpp"]
        sp_inc["shared_ptr.hpp"]
    end

    subgraph PATTERNS["模式层"]
        singleton["singleton.hpp"]
        observable["observable.hpp"]
        lazyobject["lazyobject.hpp"]
        handle["handle.hpp"]
    end

    subgraph UTILITY["基础工具层"]
        time["time/"]
        utilities["utilities/"]
        math["math/"]
        currencies["currencies/"]
    end

    subgraph DATA["市场数据层"]
        quotes["quotes/"]
        termstructures["termstructures/"]
        indexes["indexes/"]
    end

    subgraph MODELING["模型层"]
        processes["processes/"]
        models["models/"]
    end

    subgraph METHODS["方法层"]
        finitediff["finitedifferences/"]
        lattices["lattices/"]
        montecarlo["montecarlo/"]
    end

    subgraph APP["应用层"]
        cashflows["cashflows/"]
        instruments["instruments/"]
        pricingengines["pricingengines/"]
    end

    subgraph EXTRAS["实验与遗留"]
        experimental["experimental/"]
        legacy["legacy/"]
    end

    types --> observable
    types --> time
    types --> utilities
    types --> termstructures
    errors --> observable
    errors --> time
    errors --> utilities
    errors --> termstructures

    singleton --> observable
    observable --> lazyobject
    observable --> handle
    handle --> quotes
    handle --> termstructures
    handle --> indexes
    handle --> models
    handle --> processes

    time --> termstructures
    time --> cashflows
    time --> indexes
    time --> instruments

    utilities --> termstructures

    math --> termstructures
    math --> models
    math --> finitediff
    math --> montecarlo
    math --> lattices

    currencies --> indexes
    currencies --> cashflows
    currencies --> instruments

    quotes --> termstructures
    quotes --> indexes

    termstructures --> indexes
    termstructures --> processes
    termstructures --> models
    termstructures --> pricingengines

    processes --> models
    processes --> finitediff
    processes --> montecarlo
    processes --> lattices

    models --> pricingengines

    indexes --> cashflows
    indexes --> pricingengines
    indexes --> instruments

    finitediff --> pricingengines
    lattices --> pricingengines
    montecarlo --> pricingengines

    cashflows --> instruments
    instruments --> pricingengines
    pricingengines --> instruments

    instruments --> experimental
    pricingengines --> experimental
    processes --> experimental
    models --> experimental
    finitediff --> experimental

    models --> legacy

依赖强度:

  • 核心依赖: patterns 被所有模块依赖;time 被所有需要日期运算的模块依赖;math 被所有需要数值计算的模块依赖
  • 循环依赖(有意的): instruments ↔ pricingengines(Instrument 持有 engine shared_ptr,engine 访问 instrument 的 arguments/results)
  • 最大扇出: termstructures(被 indexes, processes, models, pricingengines 依赖)和 math(被 termstructures, models, methods 依赖)

6. 设计决策指南

6.1 如何选择定价数值方法

场景 推荐方法 原因
欧式期权(BS/Merton) Analytic(解析公式) 精确、瞬时
欧式期权(复杂 payoff) MC 或 COS 解析公式不可用
美式/百慕大期权 FD 或 Tree 需要处理早期行权
强路径依赖(亚式、回望) MC 或 FD Tree 状态爆炸
障碍期权 Analytic(当可用) 或 FD 或 MC 取决于 Barrier 类型
多资产 (Basket) MC 或 FD-ND Tree 维度诅咒
利率衍生品 (HW/CIR) Tree 或 FD 或 G1d 解析 取决于模型和产品
互换/CDS Discounting(折现现金流) 确定型现金流
互换期权 (Black) Black 解析公式 市场标准
互换期权 (模型校准) Jamshidian (Vasicek) 或 G1d (GSR) 单因子仿射模型
可赎回/百慕大互换 Tree 或 FD 或 LS-MC 早期行权

6.2 如何选择插值方法

场景 推荐插值器 原因
折扣曲线 LogLinear 分段常数瞬时远期,无负利率风险
零利率曲线 Linear 或 Cubic 保证连续,行业惯例
远期利率曲线 BackwardFlat 或 ConvexMonotone Flat=右连续, CM=正值单调保持
波动率微笑 SABR 或 Kruger 无套利保证
一般科学数据 Cubic 或 MonotonicCubic 平滑+单调保持

6.3 如何选择 Heston 离散化方案

方案 适用场景
QuadraticExponential 推荐默认 — Andersen 2008, 大规模 MC 中使用
QuadraticExponentialMartingale QE + 鞅修正,高精度场景
BroadieKayaExactSchemeLobatto 精确方案 (Lobatto 积分),精度要求最高
FullTruncation 简单场景,方差过程接近零时可用
Reflection 对称反射,方差过程穿越零的对策

6.4 模型世界选择

需求 使用
利率 cap/swaption 校准 + 定价 CalibratedModel 世界 (HullWhite, GSR, G2)
Heston/Bates 股票期权 CalibratedModel 世界 (HestonModel, BatesModel)
复杂利率结构 (TARN, ratchet, callable CMS) MarketModel 世界 (LMM/SMM + MultiProduct + Evolver)
需要路径希腊字母 MarketModel (PathwiseGreeks)
简单 LMM 原型/教学 legacy/ 模块(不推荐用于生产)

7. 编译时配置选项汇总

默认值 功能
QL_USE_STD_SHARED_PTR ON 使用 std::shared_ptr 代替 boost::shared_ptr
QL_USE_STD_ANY ON 使用 std::any 代替 boost::any
QL_USE_STD_FUNCTION ON 使用 std::function 代替 boost::function
QL_ENABLE_SESSIONS OFF 启用 session(每线程独立的 Singleton 全局状态)
QL_ENABLE_THREAD_SAFE_OBSERVER_PATTERN OFF 线程安全 Observer(Boost.Signals2 + mutex + Proxy 模式)
QL_ENABLE_TRACING OFF 启用调试追踪输出
QL_FASTER_LAZY_OBJECTS ON LazyObject 默认只转发首次通知(缩减通知图)
QL_THROW_IN_CYCLES OFF 递归通知循环时抛异常(否则静默返回)
QL_HIGH_RESOLUTION_DATE OFF 高精度日期(微秒级,影响 sizeof(Date)=8 vs 4)
QL_USE_INDEXED_COUPON ON 使用票息索引(提升某些操作的运行时性能)
QL_NULL_AS_FUNCTIONS OFF Null<T> 作为函数对象而非隐式转换
QL_ENABLE_PARALLEL_UNIT_TEST_RUNNER OFF 启用并行测试执行

8. 设计原则总结

  1. 关注点分离: 工具(Instrument)、引擎(PricingEngine)、过程(StochasticProcess)、模型(CalibratedModel)、方法(FD/Lattice/MC)各自独立变化。三层策略分离(Traits × Interpolator × Bootstrap)使收益率曲线可在编译时组合数十种变体
  2. 延迟计算: 通过 LazyObject 模式,依赖变化时仅标记 dirty(O(1)),真正的计算延迟到结果被访问时。calculate() 先设置 calculated_=true 再调用 performCalculations() 防止自举中的无限递归
  3. 自动重计算: 通过 Observer 链,市场数据变化从 SimpleQuote 叶子节点开始,逐级向上通过 TermStructure → Index → Coupon → Instrument 自动传播脏标记。ObservableSettings 支持全局批量更新优化
  4. 间接引用: Handle/RelinkableHandle 是市场数据引用的标准方式。Handle 内部 Link 对象同时是 Observer+Observable,接收被链接对象的变化通知并向 Handle 的观察者转发
  5. 策略可插拔: 定价模型(PricingEngine)、自举算法(Bootstrap)、插值方法(Interpolator)、离散化方案(discretization)、息票定价器(Pricer)均可通过策略模式在编译时或运行时替换
  6. 编译时多态: 大量使用模板(CRTP, Policy-Based Design, Traits, Mixin)实现零开销抽象,减少运行时虚函数调用。BinomialTree 用 CRTP、BlackStyleSwaptionEngine 用 Policy 模板、McSimulation 用 Mixin 多重继承
  7. 值语义与不可变性: Date、Period、Calendar、DayCounter、Money 等是值类型(Handle/Copy 支持),支持复制和比较。Calendar/DayCounter 内部使用共享 Impl 避免深拷贝开销
  8. Bridge (Pimpl) 模式: Calendar、DayCounter 使用句柄体模式,句柄是可复制的轻量级对象,Impl 是共享的笨重实现。新日历/计息约定可独立扩展
  9. 命名约定: 公开 API 清晰(discount(), NPV(), fixing()),内部细节使用 detail 命名空间或 Impl 嵌套类。*Impl(Time) 纯虚函数使用后缀标识 Template Method 中的"钩子"
  10. 内存安全: Observer 存储 Observer* 原始指针(避免 shared_ptr 循环引用),Observer 析构自动 unregisterWithAll。Handle 是 shared_ptr 包装,自动引用计数管理 TermStructure 等大对象生命周期
  11. 渐进式采纳: experimental/ 作为功能孵化区,新模型和方法在不影响主库稳定性的前提下测试和演化。成熟后迁移到 ql/ 主库。legacy/ 保留过时实现用于向后兼容和测试验证
  12. 编译时配置: 通过 userconfig.hpp + CMake 选项控制线程安全、sessions、tracing、高精度日期等特性,零开销条件编译

附录:文件数量与规模统计

模块 头文件 源文件 关键组件
patterns/ 7 2 Observer, LazyObject, Singleton
time/ 70+ 70+ Date, Calendar(49), DayCounter(13), Schedule
utilities/ 14 5 ObservableValue, Clone, Null, DataFormatters
math/ 100+ 50+ Interpolation(20+), Optimization, RNG, Distributions
currencies/ 86 0 86 货币子类 (Flyweight), ExchangeRate
quotes/ 10 0 SimpleQuote, DerivedQuote, ForwardSwapQuote
termstructures/ 100+ 60+ Yield/Vol/Credit/Inflation, BootstrapHelper, InterpolatedCurve
indexes/ 70+ 2 Ibor/OIS/Swap/Inflation/Equity 指数, IndexManager
processes/ 22 22 BS, Heston(8离散化), OU, CIR, HW, Bates, G2
models/ 50+ 40+ 短利率(Vasicek,HW,CIR,GSR,G2), 权益(Heston,Bates), MarketModel
methods/ 100+ 65+ FD(81+59), Lattice(8+2), MC(14+4)
cashflows/ 67 50+ Coupon, FloatingRateCoupon+Pricer, Leg Builders
instruments/ 84+ 10+ Option, Swap, Bond, CDS, Forward, CapFloor
pricingengines/ 200+ 150+ 15 子目录, 数百引擎
experimental/ 28 子目录 信用, 商品, 波动率, CMS价差
legacy/ 15 15 旧版 LMM (已废弃)
总计 ~1000 ~550

发表评论