如何用QuantLib构建附息国债YTM曲线及对应即期曲线?
用QuantLib构建YTM曲线与即期曲线的方法
一、构建附息债YTM曲线
QuantLib中没有直接封装“YTM曲线”的类,但可以通过自定义插值的收益率曲线实现。核心逻辑是:YTM是针对特定条款附息债券的到期收益率,先匹配你所使用国债的标准发行条款,再将已知的期限-YTM节点插值得到连续的YTM曲线。
具体步骤:
- 配置核心参数:日历、日计数规则、付息频率、计价货币等,必须与目标国债的条款完全匹配(比如国内国债通常为按年付息,日计数采用Actual/Actual)。
- 整理节点数据:将每个期限转换为具体到期日(以当前估值日为起点),对应YTM作为该期限标准附息债的收益率。
- 创建曲线实例:使用
InterpolatedYieldCurve类,传入估值日、到期日列表、YTM列表,选择合适的插值方法(如线性插值、立方样条插值),即可得到YTM曲线。
- 创建曲线实例:使用
注意:所有节点的YTM必须对应同条款的附息债,否则插值结果不具备参考意义。
二、用同一数据构建即期(零息)曲线
要对比YTM曲线与即期曲线,可先将已知YTM转换为对应附息债的净价,再通过bootstrap方法构建即期曲线:
具体步骤:
- 生成债券助手(Bond Helper):基于相同的国债条款,为每个期限创建
FixedRateBondHelper——用已知YTM计算对应附息债的净价,将净价、到期日、票面利率等参数传入助手。
- 生成债券助手(Bond Helper):基于相同的国债条款,为每个期限创建
- 引导构建即期曲线:使用
PiecewiseZeroCurve或PiecewiseYieldCurve类,传入所有债券助手,设置插值规则,bootstrap得到即期曲线。
- 引导构建即期曲线:使用
- 提取对比数据:从即期曲线中获取任意期限的零息收益率,即可与YTM曲线的对应期限收益率做对比。
代码示例(Python版QuantLib)
构建YTM曲线
import QuantLib as ql # 1. 配置基础参数 valuation_date = ql.Date(1, 1, 2024) ql.Settings.instance().evaluationDate = valuation_date calendar = ql.China() day_counter = ql.ActualActual(ql.ActualActual.Bond) frequency = ql.Annual standard_coupon = 0.03 # 匹配目标国债的标准票面利率 # 2. 输入期限-YTM样本数据 tenors = [ql.Period(1, ql.Years), ql.Period(3, ql.Years), ql.Period(5, ql.Years), ql.Period(10, ql.Years)] ytm_samples = [0.022, 0.025, 0.027, 0.030] # 转换为到期日列表 maturity_dates = [calendar.advance(valuation_date, t) for t in tenors] # 3. 创建YTM曲线(采用线性插值) ytm_curve = ql.InterpolatedYieldCurve( valuation_date, maturity_dates, ytm_samples, day_counter, ql.Linear() ) ytm_curve.enableExtrapolation() # 示例:获取2年期附息债YTM two_year_ytm = ytm_curve.yieldRate(ql.Period(2, ql.Years), day_counter, ql.Compounded, frequency) print(f"2年期附息债YTM: {two_year_ytm:.4%}")
构建即期曲线并对比
# 1. 创建FixedRateBondHelper列表 bond_helpers = [] for tenor, ytm in zip(tenors, ytm_samples): maturity_date = calendar.advance(valuation_date, tenor) # 生成债券付息日程 schedule = ql.Schedule( valuation_date, maturity_date, ql.Period(frequency), calendar, ql.Unadjusted, ql.Unadjusted, ql.DateGeneration.Backward, False ) # 计算对应YTM下的债券净价 bond = ql.FixedRateBond(0, 100, schedule, [standard_coupon], day_counter) bond.setPricingEngine(ql.DiscountingBondEngine(ql.YieldTermStructureHandle(ql.FlatForward(valuation_date, ytm, day_counter)))) clean_price = bond.cleanPrice() # 创建债券助手 helper = ql.FixedRateBondHelper( ql.QuoteHandle(ql.SimpleQuote(clean_price)), 0, 100, schedule, [standard_coupon], day_counter, ql.Following ) bond_helpers.append(helper) # 2. Bootstrap即期曲线 spot_curve = ql.PiecewiseZeroCurve( valuation_date, bond_helpers, day_counter, ql.Linear() ) spot_curve.enableExtrapolation() # 3. 对比2年期YTM与即期收益率 two_year_spot = spot_curve.zeroRate(ql.Period(2, ql.Years), day_counter, ql.Compounded, frequency).rate() print(f"2年期即期收益率: {two_year_spot:.4%}")
关键提示
- YTM曲线的准确性依赖于所有节点YTM对应的债券条款一致性,若样本YTM对应不同票面的债券,需先统一条款再插值。
- 即期曲线bootstrap时,债券助手的条款必须与YTM对应的债券完全匹配,才能保证两组曲线的对比有效性。
- 插值方法可根据需求调整,线性插值适合数据波动小的场景,立方样条插值能得到更平滑的曲线。
内容的提问来源于stack exchange,提问作者darkuss
相关产品推荐
相关产品推荐

