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
CalendarBridge句柄 + shared_ptr<Impl>,49个日历通过 WesternImpl/OrthodoxImpl/独立Impl 实现
DayCounterBridge句柄 + shared_ptr<Impl>,13种约定:Actual360, Actual365Fixed, ActualActual(ISDA/ISMA), Thirty360(USA/BondBasis), Business252 等
ScheduleBuilderMakeSchedule().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
DataFormattersI/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 连续
LogLinearDiscountCurve(分段常数瞬时远期)
BackwardFlatForwardCurve, HazardRate 曲线(右连续)
Cubic需要 C2 平滑时
MonotonicCubic单调保持(Hyman 1983),避免振荡
ConvexMonotone正值保持(Hagan-West 2006),远期利率曲线首选
SABRSABR 波动率微笑插值
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, ForwardValueQuotenotifyObservers() 直接传播
缓存失效DerivedQuote, CompositeQuotevalue_=Null + notifyObservers()
LazyObjectImpliedStdDevQuote, ForwardSwapQuotecalculated_=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 {
        
        +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完整类型
DiscountCurveInterpolatedDiscountCurve<LogLinear>
ZeroCurveInterpolatedZeroCurve<Linear>
ForwardCurveInterpolatedForwardCurve<BackwardFlat>
RateHelperBootstrapHelper<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)11条件Yes标准欧式期权
Ornstein-Uhlenbeck11YesNoHull-White 组件
CIR11YesQE Scheme利率/波动率建模
Hull-White11OU-basedNo利率衍生品
Heston22-3No8 Schemes随机波动率期权
Bates22-3NoYes带跳跃的Heston
G222YesNo双因子利率
Hybrid Heston-HW33NoYes混合利率+权益
StochasticProcessArrayNN代理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 方案选择指南:

方案维度说明
Douglas1D-3D等价于 Crank-Nicolson (1D时)
CraigSneyd2D标准 ADI,Heston 常用
Hundsdorfer2D-3D更高精度 ADI
CrankNicolson1D标准二阶方案
TrBDF21D-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 {
        
        -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/44Analytic, Binomial, FD(BS/Heston/Bates/CEV/SABR), MC, COS, BAW
barrier/19Analytic, Binomial, FD, MC
asian/17MC Discrete/Continuous, TurnbullWakeman, FD, Choi
swaption/16Black, Bachelier, Jamshidian, G1d, G2, Tree, FD
swap/9Discounting, CrossCurrency, CounterpartyAdj (CVA/DVA)
credit/4MidPointCds, IntegralCds, IsdaCds
basket/17Kirk, BjerksundStensland, DengLiZhou, FD 2D/ND, MC
bond/5Discounting, Credit, MonteCarlo
capfloor/8Analytic, FD, MC, Mixed
forward/4Analytic, MC
inflation/5CrossAsset, YearOnYear
quanto/4Analytic, MC
cliquet/3Analytic, MC
lookback/2Analytic, FD
mclongstaffschwartz/2LS 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→ObservernotifyObservers()
缓存失效 + LazyObjectLazyObject 子类 (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
discretizationSDE 离散化运行时注入EulerDiscretization, EndEulerDiscretization
FdmSchemeDescFD 时间离散值对象选择器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/
LazyObjectpatterns/, instruments/, termstructures/, quotes/, methods/finitedifferences/
Singletonpatterns/ → Settings, IndexManager, ExchangeRateManager, ObservableSettings, Tracing
Strategyinstruments/→PricingEngine, cashflows/→Pricer, termstructures/→Traits/Interpolator/Bootstrap, processes/→discretization
Bridge (Pimpl)time/→Calendar/DayCounter, termstructures/→TermStructure
Flyweightcurrencies/→Currency
Decoratorcashflows/→CappedFlooredCoupon/DigitalCoupon, methods/→FdmBatesOp装饰FdmHestonOp
Buildertime/→MakeSchedule, cashflows/→IborLeg/FixedRateLeg/CmsLeg/OvernightLeg/InflationLeg, instruments/→MakeVanillaSwap, pricingengines/→MakeMCEuropeanEngine
Template MethodLazyObject::calculate→performCalculations, InterestRateIndex::fixing(历史vs远期决策)
CRTPmethods/lattices/→BinomialTree, patterns/→CuriouslyRecurringTemplate
Mixinpricingengines/→McSimulation
Policy-Basedpricingengines/→BlackStyleSwaptionEngine<Spec>
Clone (Prototype)utilities/→Clone<T>, indexes/→IborIndex::clone(Handle)
Adapterprocesses/→StochasticProcess1D私有适配N-D接口, HullWhiteProcess组合OU+分离
Compositeprocesses/→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 或 FDTree 状态爆炸
障碍期权Analytic(当可用) 或 FD 或 MC取决于 Barrier 类型
多资产 (Basket)MC 或 FD-NDTree 维度诅咒
利率衍生品 (HW/CIR)Tree 或 FD 或 G1d 解析取决于模型和产品
互换/CDSDiscounting(折现现金流)确定型现金流
互换期权 (Black)Black 解析公式市场标准
互换期权 (模型校准)Jamshidian (Vasicek) 或 G1d (GSR)单因子仿射模型
可赎回/百慕大互换Tree 或 FD 或 LS-MC早期行权

6.2 如何选择插值方法

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

6.3 如何选择 Heston 离散化方案

方案适用场景
QuadraticExponential推荐默认 — Andersen 2008, 大规模 MC 中使用
QuadraticExponentialMartingaleQE + 鞅修正,高精度场景
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_PTRON使用 std::shared_ptr 代替 boost::shared_ptr
QL_USE_STD_ANYON使用 std::any 代替 boost::any
QL_USE_STD_FUNCTIONON使用 std::function 代替 boost::function
QL_ENABLE_SESSIONSOFF启用 session(每线程独立的 Singleton 全局状态)
QL_ENABLE_THREAD_SAFE_OBSERVER_PATTERNOFF线程安全 Observer(Boost.Signals2 + mutex + Proxy 模式)
QL_ENABLE_TRACINGOFF启用调试追踪输出
QL_FASTER_LAZY_OBJECTSONLazyObject 默认只转发首次通知(缩减通知图)
QL_THROW_IN_CYCLESOFF递归通知循环时抛异常(否则静默返回)
QL_HIGH_RESOLUTION_DATEOFF高精度日期(微秒级,影响 sizeof(Date)=8 vs 4)
QL_USE_INDEXED_COUPONON使用票息索引(提升某些操作的运行时性能)
QL_NULL_AS_FUNCTIONSOFFNull<T> 作为函数对象而非隐式转换
QL_ENABLE_PARALLEL_UNIT_TEST_RUNNEROFF启用并行测试执行

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/72Observer, LazyObject, Singleton
time/70+70+Date, Calendar(49), DayCounter(13), Schedule
utilities/145ObservableValue, Clone, Null, DataFormatters
math/100+50+Interpolation(20+), Optimization, RNG, Distributions
currencies/86086 货币子类 (Flyweight), ExchangeRate
quotes/100SimpleQuote, DerivedQuote, ForwardSwapQuote
termstructures/100+60+Yield/Vol/Credit/Inflation, BootstrapHelper, InterpolatedCurve
indexes/70+2Ibor/OIS/Swap/Inflation/Equity 指数, IndexManager
processes/2222BS, 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/6750+Coupon, FloatingRateCoupon+Pricer, Leg Builders
instruments/84+10+Option, Swap, Bond, CDS, Forward, CapFloor
pricingengines/200+150+15 子目录, 数百引擎
experimental/28 子目录信用, 商品, 波动率, CMS价差
legacy/1515旧版 LMM (已废弃)
总计~1000~550

发表评论