QuantLib 整体架构分析报告
1. 项目概述
QuantLib 是一个开源量化金融库,用 C++ 编写,提供金融工具定价、风险管理和数值计算功能。代码库遵循分层架构,以 Observer 模式作为数据流自动传播的核心机制,以 LazyObject 实现按需计算和结果缓存。
1.1 技术栈
- 语言: C++17(支持部分 C++20 概念)
- 智能指针: 可配置
std::shared_ptr或boost::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();
Handle 是 ql/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 假日判断优先级:
addedHolidays(用户显式添加的假日)→ 非业务日removedHolidays(用户显式移除的假日)→ 业务日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 日期生成时序:
- 用 NullCalendar 生成种子日期(不受假日影响)
- 对每个种子日期应用 BDC adjust(ModifiedFollowing, Preceding 等)
- 标记 isRegular(比较实际周期 vs 名义 tenor)
- 处理 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
关键设计模式:
- Flyweight 享元模式: 所有 USDCurrency 实例共享同一个
static shared_ptr<Data>,内存高效 - Thin Concrete Class: 每个货币子类仅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
四层职责:
- YieldTermStructure — 纯虚
discountImpl(Time)+ 公共 discount/zeroRate 接口 - ZeroYieldStructure — 改编:
discountImpl(t) = exp(-zeroYieldImpl(t) * t),新增纯虚zeroYieldImpl - InterpolatedZeroCurve<Interpolator> — 添加插值,
zeroYieldImpl(t)= 插值器(t) - 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 结果
关键设计模式:
- Thin Concrete Class 模式: 每个具体指数仅3行代码。例如
Euribor6M构造时传Period(6,Months),所有其他参数(货币=EUR, 日历=TARGET, DC=Act360)在Euribor基类中硬编码 - Clone 模式:
iborIndex->clone(differentCurve)创建共享相同约定但链接到不同远期曲线的新实例(定价引擎中频繁使用) - IndexManager 作为定息中枢: 全局 Singleton,存储所有指数的历史定息。
addFixing→ notifier().notifyObservers() → 所有依赖该指数的对象自动 dirty - 大小写不敏感键: 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 : 策略模式
核心设计模式:
-
策略模式(Pricer): 同一息票可切换不同定价器
BlackIborCouponPricer→ Black76 定价LinearTsrPricer→ 线性终端互换利率模型HaganPricer→ 静态复制 (CMS)LognormalCmsRatePricer→ 对数正态近似
-
装饰器模式:
CappedFlooredCoupon装饰FloatingRateCoupon,在不修改底层息票的情况下添加期权特征 -
Builder 模式: 流式构建完整的支付腿
Leg iborLeg = IborLeg(schedule, euribor6m) .withNotionals(10000000) .withSpreads(0.001) .withCaps(0.05) .withFloors(0.0); -
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 子类定义专用的 arguments 和 results 嵌套类:
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
核心设计模式:
- calculate() 是 const: 通过
mutable结果成员实现。允许 Instrument 多次调用 NPV() 命中同一个缓存结果 - 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; - Mixin(多重继承):
MCEuropeanEngine同时继承GenericEngine+McSimulation - 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. 设计原则总结
- 关注点分离: 工具(Instrument)、引擎(PricingEngine)、过程(StochasticProcess)、模型(CalibratedModel)、方法(FD/Lattice/MC)各自独立变化。三层策略分离(Traits × Interpolator × Bootstrap)使收益率曲线可在编译时组合数十种变体
- 延迟计算: 通过 LazyObject 模式,依赖变化时仅标记 dirty(O(1)),真正的计算延迟到结果被访问时。
calculate()先设置calculated_=true再调用performCalculations()防止自举中的无限递归 - 自动重计算: 通过 Observer 链,市场数据变化从 SimpleQuote 叶子节点开始,逐级向上通过 TermStructure → Index → Coupon → Instrument 自动传播脏标记。
ObservableSettings支持全局批量更新优化 - 间接引用: Handle/RelinkableHandle 是市场数据引用的标准方式。Handle 内部 Link 对象同时是 Observer+Observable,接收被链接对象的变化通知并向 Handle 的观察者转发
- 策略可插拔: 定价模型(PricingEngine)、自举算法(Bootstrap)、插值方法(Interpolator)、离散化方案(discretization)、息票定价器(Pricer)均可通过策略模式在编译时或运行时替换
- 编译时多态: 大量使用模板(CRTP, Policy-Based Design, Traits, Mixin)实现零开销抽象,减少运行时虚函数调用。BinomialTree 用 CRTP、BlackStyleSwaptionEngine 用 Policy 模板、McSimulation 用 Mixin 多重继承
- 值语义与不可变性: Date、Period、Calendar、DayCounter、Money 等是值类型(Handle/Copy 支持),支持复制和比较。Calendar/DayCounter 内部使用共享 Impl 避免深拷贝开销
- Bridge (Pimpl) 模式: Calendar、DayCounter 使用句柄体模式,句柄是可复制的轻量级对象,Impl 是共享的笨重实现。新日历/计息约定可独立扩展
- 命名约定: 公开 API 清晰(
discount(),NPV(),fixing()),内部细节使用detail命名空间或Impl嵌套类。*Impl(Time)纯虚函数使用后缀标识 Template Method 中的"钩子" - 内存安全: Observer 存储 Observer* 原始指针(避免 shared_ptr 循环引用),Observer 析构自动 unregisterWithAll。Handle 是 shared_ptr 包装,自动引用计数管理 TermStructure 等大对象生命周期
- 渐进式采纳: experimental/ 作为功能孵化区,新模型和方法在不影响主库稳定性的前提下测试和演化。成熟后迁移到 ql/ 主库。legacy/ 保留过时实现用于向后兼容和测试验证
- 编译时配置: 通过
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 |