You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用QuantLib从即期利率构建贴现曲线遇浮点数期限错误求助

问题根源

你遇到的TypeError是因为QuantLib的Period构造函数不接受浮点数作为第一个参数。看报错里的原型提示:Period::Period(Integer,TimeUnit),第一个参数必须是整数类型,但你的spot_tenors里有0.5、1.5这类非整数值,直接用Period(n, Years)肯定会触发类型错误。

解决思路

你的即期利率是按半年间隔设置的,最直接的修正方式是把年份转成对应的月份数(毕竟0.5年=6个月,1.5年=18个月),用Months作为时间单位来构造Period,这样就能用整数参数了。

具体修正步骤
  1. 修正期限节点的创建:
    把原来的这行代码:

    nodes = [today + Period(n, Years) for n in spot_tenors]
    

    修改为:

    nodes = [today + ql.Period(int(n * 12), ql.Months) for n in spot_tenors]
    

    这里用n * 12把年数转成月数,再转成整数,完美匹配Period的参数要求。

  2. 利率格式修正(重要!):
    你的spots列表里的数值是百分比(比如5.25代表5.25%),但QuantLib的ZeroCurve要求利率是小数形式(比如0.0525),所以必须先转换:

    spots = [s / 100.0 for s in spots]
    

    不做这一步的话,构造的曲线会把5.25当成525%的利率,计算出来的债券价格完全不符合预期。

修正后的完整代码

把这两处修改后,代码就能正常运行了,我帮你整理了完整版本:

import matplotlib
matplotlib.use('macosx')
import matplotlib.pyplot as plt
import QuantLib as ql

# 债券创建逻辑保持不变
issueDate = ql.Date(15, 1, 2015)
maturityDate = ql.Date(15, 1, 2025)
tenor = ql.Period(ql.Semiannual)
calendar = ql.UnitedStates()
businessConvention = ql.Unadjusted
dateGeneration = ql.DateGeneration.Backward
monthEnd = False
schedule = ql.Schedule(issueDate, maturityDate, tenor, calendar, businessConvention, businessConvention, dateGeneration, monthEnd)

dayCount = ql.Thirty360()
couponRate = .06
coupons = [couponRate]
settlementDays = 0
faceValue = 100
bond = ql.FixedRateBond(settlementDays, faceValue, schedule, coupons, dayCount)

today = ql.Date(30, ql.January, 2020)
spot_tenors = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0]
# 转换利率为小数格式
spots = [s / 100.0 for s in [0.0, 5.25, 5.43, 5.76, 6.02, 6.28, 6.55, 6.82, 6.87, 7.1, 7.21, 7.26, 7.31, 7.43, 7.48, 7.54, 7.67, 7.8, 7.79, 7.93, 8.07]]
# 用月份构造正确的期限节点
nodes = [today + ql.Period(int(n * 12), ql.Months) for n in spot_tenors]

discount_curve = ql.ZeroCurve(nodes, spots, ql.Actual360())
discount_handle = ql.YieldTermStructureHandle(discount_curve)
bond.setPricingEngine(ql.DiscountingBondEngine(discount_handle))

# 可以打印债券价格验证
print("债券净价:", bond.cleanPrice())
补充说明

如果你的期限不是严格的半年倍数,比如有像1.2年这种非整数,也可以用ql.Period(int(n * 360), ql.Days)来构造,但要注意和你用的日计数惯例(这里是Actual360)保持一致,避免日期计算偏差。

内容的提问来源于stack exchange,提问作者TRex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 13:04:07