Quantlib零息通胀互换未读取CPI值问题排查求助
美元CPI零息通胀互换定价问题(QuantLib Python)
问题描述
用QuantLib Python定价USD CPI零息通胀互换时,折现曲线与固定端NPV结果正常,但通胀端NPV与BBG SWPM存在数个百分点偏差。修改CPI数值对互换定价无影响,怀疑是CPI设置错误导致互换基准指数异常,求问题定位,同时希望获取完整Python示例。
代码片段
import QuantLib as quantlib import pandas as pd start_date = quantlib.Date.from_date(pd.Timestamp(2022, 9, 6)) calc_date = quantlib.Date.from_date(pd.Timestamp(2022, 9, 6)) end_date = quantlib.Date.from_date(pd.Timestamp(2024, 9, 6)) swap_type = quantlib.ZeroCouponInflationSwap.Receiver calendar = quantlib.TARGET() day_count_convention = quantlib.ActualActual() contract_observation_lag = quantlib.Period(3, quantlib.Months) business_day_convention = quantlib.ModifiedFollowing nominal = 10e6 fixed_rate = 0.05 cpi_json = '{"columns":[1],"index":[1640908800000,1643587200000,1646006400000,1648684800000,1651276800000,1653955200000,1656547200000,1659225600000],"data":[[277.948],[278.802],[283.716],[287.504],[289.109],[292.296],[296.311],[296.276]]}' cpi_prints = pd.read_json(cpi_json, orient='split') # Pretty-printed CPI: # 1 # 2021-12-31 277.948 # 2022-01-31 278.802 # 2022-02-28 283.716 # 2022-03-31 287.504 # 2022-04-30 289.109 # 2022-05-31 292.296 # 2022-06-30 296.311 # 2022-07-31 296.276 zero_coupon_observations = pd.DataFrame(index=[0], data={'1Y': 2.73620, '2Y': 2.975, '3Y': 2.967, '4Y': 2.917, '5Y': 2.8484}) inflation_yield_term_structure = quantlib.RelinkableZeroInflationTermStructureHandle() inflation_index = quantlib.USCPI(True, inflation_yield_term_structure) for date, value in cpi_prints.itertuples(): # Setting the CPI as fixings, but no matter what I put here the NPV comes out the same # Looks like the base index for the swap is not being set by me/set through the CPI prints # I put here. inflation_index.addFixing(quantlib.Date.from_date(date), value) inflation_rate_helpers = [] nominal_term_structure = quantlib.YieldTermStructureHandle(quantlib.FlatForward(calc_date, 0.00, # Changing this seems to have no effect quantlib.ActualActual())) for tenor in zero_coupon_observations.columns: maturity = calendar.advance(calc_date, quantlib.Period(tenor)) quote = quantlib.QuoteHandle(quantlib.SimpleQuote(zero_coupon_observations.at[0, tenor] / 100.0)) helper = quantlib.ZeroCouponInflationSwapHelper(quote, contract_observation_lag, maturity, calendar, business_day_convention, day_count_convention, inflation_index, nominal_term_structure) inflation_rate_helpers.append(helper) # Not sure how to choose this number, just taking the 1Y tenor on the calc date? # I'm pricing a 2Y swap, and will want to price it off it's start date as well base_zero_rate = zero_coupon_observations.at[0, '1Y']/100 inflation_curve = quantlib.PiecewiseZeroInflation(calc_date, calendar, day_count_convention, contract_observation_lag, quantlib.Monthly, inflation_index.interpolated(), base_zero_rate, inflation_rate_helpers, 1.0e-12, quantlib.Linear()) inflation_yield_term_structure.linkTo(inflation_curve) swap = quantlib.ZeroCouponInflationSwap(swap_type, nominal, start_date, end_date, calendar, business_day_convention, day_count_convention, fixed_rate, inflation_index, contract_observation_lag) # Leaving off the construction of the discount curve for brevity. # NPV of the fixed legs checks out discount_curve = ... swap_engine = quantlib.DiscountingSwapEngine(discount_curve) swap.setPricingEngine(swap_engine) print(swap.NPV())
问题定位与修正建议
核心问题点
- CPI指数初始化顺序错误:先关联通胀曲线再加载fixing,导致历史CPI数据未被正确纳入指数计算。QuantLib中通胀指数的fixing需要在绑定曲线前加载,否则曲线预测值会覆盖历史数据。
- 通胀曲线基准值误用:
base_zero_rate直接取1Y零息通胀报价是错误的,应该用最新的已发布CPI值锚定曲线基准,而非互换报价。 - 名义折现曲线无效:构建通胀曲线时传入的
nominal_term_structure是0利率曲线,会导致helper拟合通胀曲线时折现逻辑错误,进而影响通胀端现金流计算。 - 观察期逻辑未验证:起息日2022-09-06搭配3个月观察期,对应的参考CPI应为2022-06-30的数值,需确认该fixing是否被指数正确识别。
修正步骤
- 调整CPI加载顺序:先创建无曲线的USCPI实例,加载所有fixing后再绑定通胀曲线:
# 先创建独立的通胀指数 inflation_index = quantlib.USCPI(True) # 加载所有历史CPI fixings for date, value in cpi_prints.itertuples(): ql_date = quantlib.Date.from_date(date) inflation_index.addFixing(ql_date, value) # 再关联通胀曲线句柄 inflation_yield_term_structure = quantlib.RelinkableZeroInflationTermStructureHandle() inflation_index.setTermStructure(inflation_yield_term_structure) - 修正通胀曲线基准:用最新的CPI固定值(如2022-07-31的296.276)计算基准通胀率,或直接基于该CPI值初始化曲线,确保曲线锚定真实历史数据。
- 传入有效名义折现曲线:构建
ZeroCouponInflationSwapHelper时,传入与后续定价一致的discount_curve,而非0利率曲线。 - 验证观察期对应关系:通过
inflation_index.fixing(start_date - contract_observation_lag)确认参考CPI值是否正确,确保与BBG的计算逻辑一致。
完整示例关键要点
- 确保CPI fixings覆盖swap起息日之前的观察期
- 通胀曲线构建时使用与定价一致的名义折现曲线
- 指数插值方式(
True表示插值)需匹配市场惯例 - 手动验算通胀端现金流:
名义金额 * (期末CPI/期初CPI - 1),折现后与BBG结果对比验证
内容的提问来源于stack exchange,提问作者AGPeddle
相关产品推荐
相关产品推荐

