QuantLib · Yield curve bootstrap

QuantLib 收益率曲线 Bootstrap:从市场报价到一条可定价的期限结构

把存款和互换报价交给 DepositRateHelper 与 SwapRateHelper,再交给分段曲线,QuantLib 会逐点反解出零息利率与折现因子。本页给出本机实测的完整输出:四种曲线构造的零息与折现因子、四种插值在非节点上的折现因子极差、用曲线反算输入报价的自洽性误差,以及逐点 +1bp 后的曲线响应。

依据:本机 QuantLib 1.43 实测报价节点:13 个(存款 4 + 互换 9)自洽性误差:0.018bp ~ 1.364bp
报价存款 / 互换
HelperDepositRateHelper / SwapRateHelper
BootstrapPiecewise 曲线
输出零息 / 折现 / 远期

先把市场报价翻译成 helper,再由 helper 逐点反解出一条曲线;曲线建好之后能取零息利率、折现因子与远期利率三种输出,用于定价与风险。示意图非实盘界面。

测试版本QuantLib 1.43(PyPI wheel,本机 pip 安装)Python 版本3.11.9(Windows)最后核验2026-10-09(曲线与风险数值均为本机一次运行输出)估值日2024-01-15(曲线参考日取估值日)报价假设存款 1W 4.32% / 1M 4.35% / 3M 4.40% / 6M 4.50%;互换 1Y 4.55% ~ 30Y 4.95%曲线口径TARGET 日历;折现基准 Actual/360;互换固定端 Annual + 30/360(BondBasis)可直接复现是(helper 参数、曲线构造与输出数值均已写明)本站实测范围仅曲线构造与曲线口径;不含行情数据、不接实盘、不构成投资建议
实验环境QuantLib 1.43 / Python 3.11.9 / Windows
报价节点13 个(存款 4 + 互换 9)
核心结论非节点折现因子极差可达 2.5723bp
证据等级本站实测(脚本与输出均在本页)
Curve types

期限结构类型与曲线构建 helper 对照

QuantLib 的期限结构分成两层:一层是直接给出利率或折现因子的曲线类,另一层是把市场报价翻译成曲线节点的 helper。先用哪一层、用哪个 helper,决定后面能不能反算回市场报价。

依据 QuantLib 1.43 的类清单与本机实测;类名与参数以官方文档为准
类型 / 类作用典型构造方式适用场景注意点
ql.FlatForward单一平价利率的水平曲线ql.FlatForward(refDate, rate, dc, ql.Compounded, ql.Annual)快速试算、风险基准对照、教学示例不含期限结构;用它代表「真实市场曲线」会掩盖斜率效应
ql.ZeroCurve给出零息利率节点的插值曲线ql.ZeroCurve(dates, rates, dc, cal)已有零息利率表(如内部估值曲线)rates 个数必须与 dates 个数相同,否则报 dates/data count mismatch
ql.DiscountCurve直接给出折现因子节点的插值曲线ql.DiscountCurve(dates, dfs, dc, cal)已有折现因子表、或需要与对手方 DF 表对齐与 ZeroCurve 同源但输入口径不同,不要混用两套数值
ql.DepositRateHelper把货币市场存款报价变成短端节点ql.DepositRateHelper(quote, tenor, fixingDays, cal, conv, eom, dc)短端 1D ~ 6MfixingDays 与 eom 会改变节点日期;本页实测取 2 天、eom=True、Actual/360
ql.SwapRateHelper把互换报价变成中长端节点ql.SwapRateHelper(quote, tenor, cal, fixedFreq, fixedConv, fixedDC, ibor)中长端 1Y ~ 30Y固定端频率、计息基准、日历三项要与市场惯例一致,否则反算的 par rate 会有偏差(本页实测 2Y 差 −1.364bp)
ql.FraRateHelper / ql.FuturesRateHelper把远期利率协议或利率期货变成节点对应 helper 构造函数,需给出起算与结束期限远期段(约 3M ~ 2Y)的报价更活跃时期货报价含凸性,直接当远期用会带系统性偏差
ql.OISRateHelper把隔夜指数互换变成节点需要先构造 OvernightIndex,再传入 helper需要无风险(隔夜)折现曲线时与 IBOR 曲线是两条不同的曲线,报价不可互相替代
ql.PiecewiseLogCubicDiscount 等分段曲线由 helper 列表逐点 bootstrap 出整条曲线ctor(0, calendar, helpers, dayCounter)由市场报价直接构造可定价曲线插值方式不同、非节点输出不同(本页实测 4 年折现因子极差 2.5723bp)
本机实测到的三个边界:① ql.ZeroCurve 的节点日期个数与利率个数必须一致,否则报 dates/data count mismatch;② 未开启外推时,取超出曲线末端的期限会报 time (5.075) is past max curve time (1.02222);③ 报价倒挂时 bootstrap 仍能建出曲线,错误会推迟到「取值那一刻」才暴露。
Workflow

从市场报价到可定价曲线:6 步实测流程

下面 6 步是本页实际执行的顺序。每一步都给出调用的接口与预期输出,最后一步是自洽性检验——如果这一步误差很大,说明前面的口径没对齐,而不是曲线算法有问题。

  • 1. 固定估值日与曲线参考日

    先设置 ql.Settings.instance().evaluationDate;构造分段曲线时参考日传 0,表示使用估值日。测出节点日期以估值日 2024-01-15 为起点。

    预期输出:曲线起点节点日期 = 2024-01-15;本页实测共 14 个节点(参考日 + 13 个报价节点)。

  • 2. 构造短端存款 helper(1W / 1M / 3M / 6M)

    ql.DepositRateHelper(quote, tenor, 2, calendar, ql.ModifiedFollowing, True, ql.Actual360()),fixingDays 取 2、月末规则取 True、计息基准取 Actual/360。

    预期输出:4 个短端节点;本页实测首批节点日期为 January 24th, 2024(1W)与 February 19th, 2024(1M),可见节点日期不等于「估值日 + 自然月」。

  • 3. 构造中长端互换 helper(1Y ~ 30Y)

    ql.SwapRateHelper(quote, tenor, calendar, ql.Annual, ql.Unadjusted, ql.Thirty360(ql.Thirty360.BondBasis), ibor);ibor 用 6 个月期指数(本页实测以 USD-6M / TARGET / Actual/360 构造)。

    预期输出:9 个互换节点;固定端频率 Annual、调整约定 Unadjusted、计息 30/360 BondBasis 三项都会影响反算结果。

  • 4. 用 helper 列表 bootstrap 出曲线

    ql.PiecewiseLogCubicDiscount(0, calendar, helpers, ql.Actual360());把 13 个 helper 一次性传入,由曲线类自己逐点反解。

    预期输出:建成后可直接取 zeroRate、discount、forwardRate;本页实测 5 年零息 4.687292%、折现因子 0.7925708982(LogCubic)。

  • 5. 取出三种输出并做口径标注

    零息用 zeroRate(d, ql.Actual360(), ql.Compounded, ql.Annual),折现用 discount(d),远期用 forwardRate(d1, d2, ql.Actual360(), ql.Simple)。

    预期输出:同一期限三种输出的数值口径不同,不能直接互比;本页实测 5 年零息 4.687292% 与同期 6 个月远期利率是两套口径。

  • 6. 用曲线反算输入报价,做自洽性检验

    对每个输入互换,用曲线的折现因子按固定端计息基准加权,反算平价的固定利率,再与输入报价相减。

    预期输出:本页实测差异为 1Y +0.018bp、2Y −1.364bp、3Y −0.533bp、5Y −0.091bp、7Y −0.068bp、10Y −0.061bp;误差集中在 2~3 年,说明固定端口径与曲线基准不一致。

  • term_structure_bootstrap.py(QuantLib 1.43 / Python 3.11.9 实测通过)import QuantLib as ql today = ql.Date(15, 1, 2024) ql.Settings.instance().evaluationDate = today cal, dc = ql.TARGET(), ql.Actual360() ibor = ql.IborIndex("USD-6M", ql.Period(6, ql.Months), 2, ql.USDCurrency(), cal, ql.ModifiedFollowing, False, ql.Actual360()) deposits = [(ql.Period(1, ql.Weeks), 0.0432), (ql.Period(1, ql.Months), 0.0435), (ql.Period(3, ql.Months), 0.0440), (ql.Period(6, ql.Months), 0.0450)] swaps = [(ql.Period(1, ql.Years), 0.0455), (ql.Period(2, ql.Years), 0.0460), (ql.Period(3, ql.Years), 0.0465), (ql.Period(5, ql.Years), 0.0475), (ql.Period(7, ql.Years), 0.0480), (ql.Period(10, ql.Years), 0.0485), (ql.Period(15, ql.Years), 0.0490), (ql.Period(20, ql.Years), 0.0492), (ql.Period(30, ql.Years), 0.0495)] helpers = [ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(q)), t, 2, cal, ql.ModifiedFollowing, True, dc) for t, q in deposits] helpers += [ql.SwapRateHelper(ql.QuoteHandle(ql.SimpleQuote(q)), t, cal, ql.Annual, ql.Unadjusted, ql.Thirty360(ql.Thirty360.BondBasis), ibor) for t, q in swaps] curve = ql.PiecewiseLogCubicDiscount(0, cal, helpers, dc) d5 = cal.advance(today, ql.Period(5, ql.Years)) print(curve.zeroRate(d5, dc, ql.Compounded, ql.Annual).rate()) # 0.04687292... print(curve.discount(d5)) # 0.7925708982
    Bootstrap output

    四种曲线构造的实测输出:零息利率与折现因子

    同一批 helper 交给四种分段曲线构造,逐期限取出零息利率(Annual 复利、Actual/360)与折现因子。下表全部是本机实测值,用于判断「换一种构造会不会改变定价输入」。

    实测:13 个报价节点、估值日 2024-01-15,四种分段曲线构造的零息与折现输出
    期限LogLinear 零息%LogCubic 零息%FlatForward 零息%CubicZero 零息%LogCubic 折现因子
    0.25 年4.4710874.4694404.4710874.4701530.9890082981
    0.5 年4.5476964.5481754.5476964.5484820.9777649372
    1 年4.4738454.4739444.4738454.4734610.9564784998
    2 年4.5172044.5166274.5172044.5168810.9142037644
    3 年4.5787604.5785994.5787604.5786250.8725843529
    5 年4.6870454.6872924.6870454.6873280.7925708982
    7 年4.7416894.7418944.7416894.7419330.7195966054
    10 年4.7963234.7966774.7963234.7966420.6215452476
    15 年4.8545564.8548244.8545564.8548970.4858938322
    20 年4.8767944.8769744.8767944.8770850.3805093517
    30 年4.9187974.9199424.9187974.9200960.2317951390
    读法:在本组报价下,LogLinear 与 FlatForward 的零息输出逐行相同,而 LogCubic 与 CubicZero 略有差异:30 年零息分别是 4.918797%、4.919942%、4.920096%,LogLinear 与 CubicZero 相差 0.001299 个百分点(约 0.13bp)。差异不大,但足以让「用曲线反算报价」的误差跨过 1bp——本页第 6 步实测到 2 年差 −1.364bp。
    Interpolation

    插值方法选择:非节点上的折现因子差多少

    曲线只有在报价节点上是「被报价钉住」的,节点之间全靠插值。交易对手用的插值方式和你不同时,即使报价完全一样,非节点的折现因子也会不同。下面是插值方法对照与本机实测的极差。

    依据 QuantLib 1.43 的曲线类清单(ZeroCurve 为 InterpolatedZeroCurve,DiscountCurve 为 InterpolatedDiscountCurve)与本机实测
    插值方法插值对象优点风险适用场景
    PiecewiseLogLinearDiscount对数线性插值折现因子单调、稳健,一般不会造出负远期曲线有折点,二阶不连续常规市场曲线与折现曲线
    PiecewiseLogCubicDiscount对数三次插值折现因子曲线平滑,远期连续节点附近远期可能出现振荡需要平滑远期、或做曲线风险分析
    PiecewiseFlatForward分段常数平价远期远期在节点之间恒定,口径直观曲线不平滑,远期呈阶梯状教学与教科书式 bootstrap 对照
    PiecewiseCubicZero三次插值零息利率零息曲线平滑零息平滑不等于远期平滑,远期可能更抖以零息利率为报价口径时
    ql.ZeroCurve(线性插值零息)线性插值零息节点构造简单,直接给利率表远期在节点处跳变已有零息利率表、只要近似定价
    ql.DiscountCurve(对数线性插值 DF)对数线性插值折现因子与 DF 表口径一致,便于对账节点外需自行处理外推对手方给的是折现因子表时
    实测:四种插值下的折现因子与极差(极差 = 同期限四种输出之间的跨度,按 bp 计;节点行由第 3 张表的实测值相减得到)
    年限LogLinear 折现因子LogCubic 折现因子FlatForward 折现因子CubicZero 折现因子折现因子极差(bp)是否报价节点
    4 年0.83145964400.83170578550.83145964400.83171686972.5723非节点
    6 年0.75521317600.75520949480.75521317600.75524127730.3178非节点
    8 年0.68538088610.68551663230.68538088610.68547412971.3575非节点
    12 年0.56340611480.56341337960.56340611480.56348098190.7487非节点
    25 年0.29702030740.29723892540.29702030740.29725476712.3446非节点
    5 年0.79258037980.79257089820.79258037980.79256953220.1085报价节点
    10 年0.62156654000.62154524760.62156654000.62154735330.2129报价节点
    30 年0.23187219620.23179513900.23187219620.23178484220.8735报价节点
    判据:非节点的极差明显大于节点:4 年是 2.5723bp、25 年是 2.3446bp,而报价节点上只有 0.1085bp(5 年)到 0.8735bp(30 年)。也就是说:对账差异如果只在非节点上出现,先怀疑插值;如果连节点都对不上,才是报价或口径的问题。
    Self-check

    曲线自洽性与 1bp 风险实测

    曲线建好之后有两件事必须做:用曲线反算输入报价,确认 bootstrap 没走偏;再逐点扰动报价,看关键期限的响应是否符合预期。下面两组都是本机实测输出。

    实测:用曲线折现因子按固定端计息基准反算平价固定利率,与输入报价比较
    期限输入互换报价%曲线反算 par rate%差(bp)判据与可能原因
    1 年4.554.5502+0.018误差很小:短端节点由存款 helper 支撑
    2 年4.604.5864−1.364误差偏大:固定端 Annual + 30/360 与曲线 Actual/360 口径不一致
    3 年4.654.6447−0.533与 2 年同源,随期限变长而收窄
    5 年4.754.7491−0.091插值平滑后残差被摊薄
    7 年4.804.7993−0.068节点较密,残差继续收窄
    10 年4.854.8494−0.061同上;本组误差集中在 2~3 年
    实测:逐点把每个报价抬高 1bp 后重建曲线,观察 5 年与 10 年零息的变化
    被 +1bp 的报价类型报价%5Y 零息变化(bp)10Y 零息变化(bp)读出什么
    1W存款4.320.00.0短端报价对中长端零息无影响(本机实测恒为 0)
    1M存款4.350.00.0同上
    3M存款4.400.00.0同上
    6M存款4.500.00.0同上
    1Y互换4.55−0.0105−0.0055影响很小且带负号:三次插值下远处节点的扰动会反向微调
    2Y互换4.60−0.0131−0.0066同上;负号说明残差在节点之间被重新分配
    3Y互换4.65−0.0515−0.0272负号幅度略大,仍属插值效应
    5Y互换4.75+1.0571−0.0463本节点响应接近 1bp(套利关系决定),跨节点为轻微负号
    7Y互换4.80+0.0044−0.1107对 5 年是微正、对 10 年是负号,跨节点影响方向取决于插值
    10Y互换4.85−0.0009+1.1793本节点响应 1.18bp,超过 1bp:插值叠加计息口径导致
    15Y互换4.90+0.0002+0.0078长端节点对两个关键期限影响都很小
    20Y互换4.92−0.0001−0.0023同上,量级在 0.01bp 以内
    30Y互换4.950.0+0.0003末端节点几乎不影响前面期限
    两条可操作结论:① 自洽性误差不随期限单调变化,2~3 年偏大(−1.364bp、−0.533bp),说明它是固定端口径与曲线基准之间的系统性偏差,不是数值精度问题;② 逐点风险的响应不是「本节点 1bp、其余 0」,本机实测出现 −0.1107bp 这类跨节点反向影响——做关键期限风险时不要把曲线当成互不相干的点列。
    Curve vs yield

    曲线折现与单一收益率:什么时候不能互相替代

    同一只债券(票息 3%、2020-01-15 发行、2030-01-15 到期、年付、TARGET、A/A ISDA、结算 T+2),把折现方式从平曲线换成有斜率的零息曲线,净价与「反解出的单一收益率」会同时变化——但两者描述的不是同一件事。

    实测:同一只债券,只替换折现曲线(估值日 2024-01-15,结算 T+2)
    折现方式净价全价由净价反解出的收益率DV01(每 100 面值)说明
    平曲线 2%105.48014237105.496535812.020134%0.05777747曲线水平移动:所有期限同利率
    平曲线 3%99.7540846799.770478123.0454534%0.05396585与票息同水平,净价接近面值
    平曲线 4%94.3518961194.368289554.08107742%0.05040818利率上行,净价与 DV01 同步下降
    递增零息曲线(2.65% → 7.15%,31 个节点)97.6912447597.707638193.43261594%0.05260284有斜率:每条现金流用各自期限的折现率
    把曲线交付给他人(或与对手方对账)前必须写清的 6 个字段,逐项附本页实测依据
    把曲线交给别人时必须写清的字段为什么关键本页实测依据
    参考日(reference date)所有节点的起算点,差一天整条曲线平移实测:曲线取值早于参考日直接报 negative time (-4.03825) given
    日历(calendar)决定节点日期落在哪天,也决定非营业日如何处理实测:TARGET 与 China.SSE 在假期边界上错开 1~8 天
    计息基准(DayCounter)决定每个区间的年化长度,直接影响折现指数实测:曲线用 Actual/360,互换固定端用 30/360 BondBasis,自洽性在 2 年差 −1.364bp
    复利方式与频率(Compounding / Frequency)零息报 Annual 复利与报 Simple 是两个数实测:zeroRate 用 Compounded + Annual,forwardRate 用 Simple,两者不可互比
    插值方式节点之间怎么走,直接决定非节点折现因子实测:非节点折现因子极差 0.3178bp ~ 2.5723bp
    外推开关末端之外的期限是报错还是外推,必须事先说清实测:未开启外推时取 5 年(1 年曲线)报 time past max curve time
    结论:平曲线下三组实验都能反解出一个「等价收益率」(2.0201% / 3.0455% / 4.0811%),因为所有现金流用了同一个折现率;一旦曲线有斜率,递增曲线给出净价 97.69124475、反解收益率 3.43261594%,而这个单一收益率无法复现同一条曲线下的价格——它只是把 10 年现金流加权后的一个平均数字。报价用收益率、定价用曲线,这两件事必须分开登记。
    China market

    中国市场:能用的是什么,不能直接用的又是什么

    人民币曲线可以照同样的流程构造:把 CNY 报价交给 DepositRateHelper 与 SwapRateHelper,日历换成银行间(China.IB)。但要注意:本页的 CNY 报价是示意值,不是市场数据,QuantLib 也不提供中国的计息口径与估值规则。

    从 Excel 或 CSV 导入报价时建议逐项核对的 7 个字段(字段名为建议命名,按你的数据源调整)
    导入字段含义必须与什么保持一致常见坑本页实测关联
    tenor / 期限报价对应的期限helper 的 Period 与市场惯例一致3M 与 90D 在带假期的日历下不是同一件事实测:1W 节点落在 January 24th, 2024
    instrumenttype / 工具类型存款、互换、债券等决定用哪个 helper用错 helper 会让节点落在错误的日期实测:4 个存款 helper + 9 个互换 helper = 13 节点
    quote / 报价利率数值单位统一(小数与百分比差 100 倍)0.0455 与 4.55 混用会让曲线整体错位实测:本页报价以小数传入(0.0455 = 4.55%)
    daycount / 计息基准报价自身的计息约定与 helper 参数一致Actual/360 与 Actual/365 会让反算 par rate 差几个 bp实测:曲线 Actual/360、互换 30/360,2Y 差 −1.364bp
    settlingdays / 起息规则报价的起息与结算天数与 helper 的 fixingDays 和月末规则一致fixingDays 改了、节点日期就改实测:存款 helper 取 2 天、eom=True
    calendar / 日历该市场采用的日历与 market 一致(银行间或交易所)用 TARGET 构造人民币曲线会错开假期边界实测:China.IB 2024 年非营业日 115 天 / SSE 124 天 / TARGET 110 天
    fixedfrequency / 固定端频率互换固定端付息频率与 SwapRateHelper 参数一致频率与计息基准不匹配会放大自洽性误差实测:本页互换用 Annual + 30/360
    实测:人民币示意曲线(银行存款 1D 1.80% ~ 6M 2.00% + 互换 1Y 2.05% ~ 10Y 2.45%,CNY-3M 指数,China.IB 日历,Actual/365 Fixed 基准)——报价为示意值,非市场数据
    年限节点日期零息利率%折现因子
    1 年January 15th, 20252.0652400.9797106184
    2 年January 15th, 20262.1167870.9589165026
    3 年January 15th, 20272.1683220.9376174702
    5 年January 15th, 20292.2735870.8935709999
    7 年January 15th, 20312.3805950.8480480466
    10 年January 16th, 20342.4893610.7817989884
    cny_curve_illustrative.py(示意报价,非市场数据)import QuantLib as ql today = ql.Date(15, 1, 2024) ql.Settings.instance().evaluationDate = today ib = ql.China(ql.China.IB) cny = ql.IborIndex("CNY-3M", ql.Period(3, ql.Months), 1, ql.CNYCurrency(), ib, ql.ModifiedFollowing, False, ql.Actual360()) deposits = [(ql.Period(1, ql.Days), 0.0180), (ql.Period(1, ql.Weeks), 0.0185), (ql.Period(1, ql.Months), 0.0190), (ql.Period(3, ql.Months), 0.0195), (ql.Period(6, ql.Months), 0.0200)] swaps = [(ql.Period(1, ql.Years), 0.0205), (ql.Period(2, ql.Years), 0.0210), (ql.Period(3, ql.Years), 0.0215), (ql.Period(5, ql.Years), 0.0225), (ql.Period(7, ql.Years), 0.0235), (ql.Period(10, ql.Years), 0.0245)] helpers = [ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(q)), t, 1, ib, ql.ModifiedFollowing, False, ql.Actual360()) for t, q in deposits] helpers += [ql.SwapRateHelper(ql.QuoteHandle(ql.SimpleQuote(q)), t, ib, ql.Quarterly, ql.ModifiedFollowing, ql.Actual365Fixed(), cny) for t, q in swaps] curve = ql.PiecewiseLogCubicDiscount(0, ib, helpers, ql.Actual365Fixed()) d5 = ib.advance(today, ql.Period(5, ql.Years)) print(curve.zeroRate(d5, ql.Actual365Fixed(), ql.Compounded, ql.Annual).rate()) # 0.02273587 print(curve.discount(d5)) # 0.8935709999
    边界(必须写清楚的三件事):① 本机实测 ql.ActualActual 的枚举为 ISDA / Bond / Historical / AFB / Euro / Actual365 / ISMA,没有 China 口径,人民币债券的计息规则要自己按发行文件选定;② 日历可以选 ql.China(ql.China.SSE)(Shanghai stock exchange)或 ql.China(ql.China.IB)(China inter bank market),两者 2024 年非营业日分别是 124 天与 115 天;③ 中债等外部数据源的解析、字段映射与估值口径需要自行实现,本页只给字段清单与方法,具体以中债官方下载口径与你所在机构的估值规则为准。QuantLib 提供的是计算框架,不含中国市场数据。
    Checklist

    曲线建好后的 6 项校验清单

    下面每一项都可以在几分钟内跑完,用来判断一条曲线「能不能用于定价」而不是「看起来像不像曲线」。每项都附本页实测的参照值与不通过时的含义。

    实测导向的曲线验收清单(7 项,每项给出本机参照值)
    校验项怎么做期望结果不通过时的含义本页实测参照
    节点数目与日期打印 curve.dates()节点数 = 参考日 + helper 个数少了说明 helper 未生效或被去重,多了说明日历或周期设置不符实测 14 个节点,首批为 January 15th, 2024 / January 24th, 2024 / February 19th, 2024
    反算输入报价(自洽性)用曲线算每个输入工具的理论定价,再反算报价差异应在 0 ~ 1.5bp 量级误差大说明固定端频率/计息/日历与市场惯例不一致,不是数值问题实测 1Y +0.018bp、2Y −1.364bp、10Y −0.061bp
    零息曲线是否异常跳变逐期限打印 zeroRate相邻期限变化平缓、方向一致局部跳变说明报价本身有问题或插值被节点挤压实测 30 年零息 4.918797% ~ 4.920096%(四种构造)
    折现因子取值区间检查 discount 是否都落在 0 与 1 之间正利率环境下全部小于 1 且随期限递减出现大于 1 说明存在负利率或报价异常实测:负利率报价(−20%)下折现因子会升到 1.2552,属口径而非 bug
    末端与超范围行为取曲线末端之外的期限并确认行为未开外推时应明确报错,而不是返回外推值静默外推会让远端定价没有任何报价支撑实测:报 time (5.075) is past max curve time (1.02222)
    逐点扰动(曲线风险)逐个报价 +1bp 重建曲线,观察关键期限本节点响应约为 1bp,跨节点影响应可解释出现无法解释的大幅反向影响,先检查插值与报价倒挂实测:5Y 报价 +1bp → 5Y 零息 +1.0571bp;10Y 报价 +1bp → 10Y 零息 +1.1793bp
    口径登记把参考日 / 日历 / 计息 / 复利 / 插值 / 外推六项写进文件头六项齐全,且与对手方一致缺项是「同一批报价算出不同价格」的常见起点六项含义与实测依据见本页「曲线折现与单一收益率」一节
    FAQ

    常见问题

    为什么我的曲线反算不出输入的互换报价?

    先看误差量级。本站实测同一批 USD 报价的反算误差是 1Y +0.018bp、2Y −1.364bp、3Y −0.533bp、5Y −0.091bp、10Y −0.061bp——误差集中在 2~3 年,根因是互换固定端用 Annual + 30/360 BondBasis,而曲线折现基准是 Actual/360。如果误差在几百 bp 量级,则要检查报价单位(小数与百分比)与期限是否对应。以官方文档与市场惯例为准;QuantLib 与 EasyClaw 无已证实集成,口径对齐需要你自己完成。

    插值方法到底会影响多少?

    在报价节点上影响很小(本机实测 5 年折现因子极差 0.1085bp、30 年 0.8735bp),但在非节点上会明显放大:4 年 2.5723bp、25 年 2.3446bp。结论是:如果对账差异只出现在非节点,先换成与对手方相同的插值方式;如果连节点都对不上,才是报价或口径问题。以双方约定的曲线口径为准。

    平曲线能不能直接当市场曲线用?

    不能。本站实测同一只债券:平曲线 3% 净价 99.75408467、递增零息曲线(2.65% → 7.15%)净价 97.69124475,而后者反解出的「单一收益率」是 3.43261594%——这个数字在平曲线下无法复现同一条曲线的价格。平曲线适合做基准与试算,不能代表市场期限结构。以真实报价与官方曲线构造接口为准。

    中债数据能不能直接导入?

    不能直接导入,需要自己做字段映射。QuantLib 1.43 的 ql.ActualActual 枚举没有 China 口径,日历有 China.SSE 与 China.IB 可用(本机实测 2024 年非营业日分别是 124 天与 115 天)。本页给出的做法是:把报价整理成「期限 / 工具类型 / 报价 / 计息基准 / 起息规则 / 日历 / 固定端频率」七项,再逐项映射到 helper 参数。具体口径以中债官方下载说明与你所在机构的估值规则为准。

    为什么取超出曲线末端的期限会报错?

    因为默认不做外推。本机实测:用一条只有 1 年期节点的曲线去问 5 年,会报 time (5.075) is past max curve time (1.02222)。这是保护性行为——远端没有报价支撑时返回一个外推值反而更危险。确实需要外推时要显式开启并记录在口径里。以官方文档为准。

    逐点 bump 报价时,为什么别的期限也会变?

    因为插值把节点之间的曲线重新分配了。本机实测:把 7 年互换报价抬高 1bp,5 年零息只变 +0.0044bp,但 10 年零息变了 −0.1107bp;把 10 年报价抬高 1bp,10 年零息变 +1.1793bp(略超过 1bp)。所以做关键期限风险时,不要把曲线当成互不相干的点列。以你自己的曲线口径复算为准。

    曲线参考日用今天还是用固定的历史日期?

    建议显式固定并写进记录。本机实测 ql.Date.todaysDate() 返回运行当天(2026-10-09),如果不设置估值日,同一条曲线在不同天运行会得到不同的节点日期,历史对账复现不了。同时注意边界:取值早于参考日会直接报 negative time。以官方文档为准。

    本页的报价可以直接拿去做定价吗?

    不可以。本页全部是受控实验:美元报价与人民币报价都是示意值,用于演示 bootstrap 流程与口径影响,不是任何时点的市场数据。真实定价必须使用你自己的合规数据源,并记录数据日期与口径;结果仅供研究与流程参考,不构成投资建议。

    本页结论一条可定价曲线 = 报价 + helper 参数 + 插值方式 + 口径登记。本机实测:同批报价下四种曲线构造的30 年零息相差约 0.13bp,非节点折现因子极差可达 2.5723bp,逐点 1bp 扰动在本节点响应约 1bp而跨节点会出现负号;有斜率的曲线无法用单一收益率复现。
    适用边界报价为示意值(存款 1W 4.32% ~ 6M 4.50%、互换 1Y 4.55% ~ 30Y 4.95%;人民币曲线另标示意),环境为 QuantLib 1.43 / Python 3.11.9,估值日固定 2024-01-15。跨版本或换市场惯例,数值会变。
    风险提示曲线是定价输入而非交易建议:报价来源、数据日期、计息与日历口径都会改变结果。本页数值不构成任何标的的估值结论或投资建议。

    曲线建好之后,下一步做什么?

    把曲线接到债券、掉期与互换期权上做定价与风险,去金融工具页;如果结果与预期不符,先按金融约定逐项审计口径,再进错误与排查。