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

QuantLib与PYOMO连续复利到期收益率计算结果差异排查

债券到期收益率(YTM)计算:QuantLib与PYOMO连续复利结果差异问题

我在计算债券现金流的到期收益率时,发现PYOMO求解的连续复利收益率与QuantLib结果存在13bp的显著差异,但年复利结果差异控制在1bp以内。具体操作流程如下:

  • 基于日期和金额向量创建BondLeg并指定债券全价(dirty_value)
  • 调用ql.Cashflows.yieldRate分别计算年复利(Annually Compounding)和连续复利(Continuous Compounding)到期收益率
  • 采用与收益率计算一致的Actual365Fixed日计数基准生成年分数(yearFraction)
  • 使用PYOMO的ipopt非线性优化求解器,结合年分数、现金流金额和全价求解到期收益率

代码实现

导入模块

import numpy as np
import QuantLib as ql

import pyomo.environ as pyo
from pyomo.opt import SolverFactory

ql.Settings.instance().evaluationDate = ql.Date(30,6,2023)

现金流与全价

dates = [ql.Date(14,11,2023), 
         ql.Date(14,11,2024), 
         ql.Date(14,11,2025), 
         ql.Date(16,11,2026), 
         ql.Date(15,11,2027), 
         ql.Date(14,11,2028), 
         ql.Date(14,11,2029), 
         ql.Date(14,11,2030), 
         ql.Date(14,11,2031), 
         ql.Date(15,11,2032)]

amounts = [84070, 
           84070, 
           84070, 
           84537.05555555558,
           65131.50532953604,
           65131.50532953604,
           65312.930135468014,
           65312.930135468014,
           65312.930135468014,
           1065494.3549413998]

dirty_val = 1050876.388888889

QuantLib计算实现

BondLeg = ql.Leg([ql.SimpleCashFlow(amt, dt) for dt,amt in zip(dates,amounts)])

ql_ra = ql.CashFlows.yieldRate(BondLeg, dirty_val, ql.Actual365Fixed(), ql.Compounded, ql.Annual, True)
ql_rc = ql.CashFlows.yieldRate(BondLeg, dirty_val, ql.Actual365Fixed(), ql.Compounded, ql.Continuous, True)

生成年分数

year_fracs = [ql.Actual365Fixed().yearFraction(ql.Date(30,6,2023),dt) for dt in dates]

periods = np.array([frac for frac in year_fracs])
p_int = np.int_(periods)
p_frac = periods - p_int

amount_vec = np.array(amounts)

PYOMO求解实现

年复利收益率计算

model_ra = pyo.ConcreteModel()

# 决策变量
model_ra.ra = pyo.Var(domain = pyo.NonNegativeReals, initialize=0.05)
ra = model_ra.ra

# 目标函数
def ra_objective_rule(model_ra):
    return (amount_vec.dot(1/(((1+ra)**p_int)* (1+(ra*p_frac)))) - dirty_val)**2

model_ra.objf = pyo.Objective(rule=ra_objective_rule, sense=pyo.minimize)

Solver = SolverFactory('ipopt')
results_ra = Solver.solve(model_ra)

print(results_ra)
print(f'Objective Function = {model_ra.objf()}')
print(f'ra = {ra()}')

连续复利收益率计算

model_rc = pyo.ConcreteModel()

# 决策变量
model_rc.rc = pyo.Var(domain = pyo.NonNegativeReals, initialize=0.05)
rc = model_rc.rc

# 目标函数
def rc_objective_rule(model_rc):
    return (amount_vec.dot(np.array([pyo.exp(-p*rc) for p in periods])) - dirty_val)**2
    
model_rc.objf = pyo.Objective(rule=rc_objective_rule, sense=pyo.minimize)

Solver = SolverFactory('ipopt')
results_rc = Solver.solve(model_rc)

print(results_rc)
print(f'Objective Function = {model_rc.objf()}')
print(f'rc = {rc()}')

结果对比

print(f'QuantLib - Annually Compounded Rate : {ql_ra:.4%}')
print(f'QuantLib - Continuously Compounded Rate : {ql_rc:.4%}')

print(f'PYOMO - Annually Compounded Rate : {ra.value:.4%}')
print(f'PYOMO - Continuously Compounded Rate : {rc.value:.4%}')

输出结果:

QuantLib - Annually Compounded Rate : 7.3623%
QuantLib - Continuously Compounded Rate : 7.2315%

PYOMO - Annually Compounded Rate : 7.3526%
PYOMO - Continuously Compounded Rate : 7.1039%

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 09:07:38