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

如何在QuantLib中提取以债券结算日为基准的折现因子

以债券结算日为基准提取折现因子的方法

核心逻辑

折现因子本质是两个日期之间的现金流折现系数:

  • 估值日(Evaluation Date)到现金流日的折现因子:curve.discount(cashflow_date)
  • 结算日(Settlement Date)到现金流日的折现因子:curve.discount(settlement_date, cashflow_date)

你代码里尝试的curve.discount(bond.settlementDate(), row['date'])逻辑是正确的,只需优化细节确保结果准确。

代码优化与细节修正

原代码思路没问题,但有几个可改进的点:

  1. 替换eval():直接调用Coupon对象方法更安全易维护
  2. 统一日期类型:确保所有日期都是QuantLib的ql.Date对象,避免类型不一致导致错误
  3. 明确日计数规则:和构建收益率曲线时的规则保持一致

修正后的代码如下:

import QuantLib as ql
import pandas as pd

fields = ['accrualStartDate', 'accrualEndDate', 'date', 'nominal', 'rate',
          'amount', 'accrualDays', 'accrualPeriod']
BondCashflows = []

# 确保日计数规则和构建曲线时一致
day_count = ql.Actual365Fixed()
valuation_date = today  # 此处today需为ql.Date类型的估值日
settlement_date = bond.settlementDate()

for cf in list(map(ql.as_fixed_rate_coupon, bond.cashflows()))[:-1]:
    # 直接调用方法获取现金流属性,替代eval
    row = {
        'accrualStartDate': cf.accrualStartDate(),
        'accrualEndDate': cf.accrualEndDate(),
        'date': cf.date(),
        'nominal': cf.nominal(),
        'rate': cf.rate(),
        'amount': cf.amount(),
        'accrualDays': cf.accrualDays(),
        'accrualPeriod': cf.accrualPeriod()
    }
    # 手动计算应计周期(和原逻辑一致)
    row['AccrualPeriod'] = round((row['accrualEndDate'] - row['accrualStartDate']) / 365, 4)
    
    if row['date'] >= valuation_date:
        # 估值日基准的零息率与折现因子(用于现值计算)
        row['ZeroRate (NPV)'] = round(curve.zeroRate(row['date'], day_count, ql.Compounded, ql.Annual).rate(), 9)
        row['DiscFactor (NPV)'] = round(curve.discount(row['date']), 9)
        
        # 结算日基准的零息率与折现因子(用于全价计算)
        row['ZeroRate (Dirty Price)'] = round(curve.forwardRate(settlement_date, row['date'], day_count, ql.Compounded, ql.Annual).rate(), 9)
        row['DiscFactor (Dirty Price)'] = round(curve.discount(settlement_date, row['date']), 9)
        
        row['NPV'] = round(row['DiscFactor (NPV)'] * row['amount'], 9)
    else:
        # 现金流日期早于估值日,按需求设置默认值
        row['ZeroRate (NPV)'] = 0
        row['ZeroRate (Dirty Price)'] = 0
        row['DiscFactor (NPV)'] = 0
        row['DiscFactor (Dirty Price)'] = 0
        row['NPV'] = 0
    
    BondCashflows.append(row)

BondCashflows = pd.DataFrame(BondCashflows)
print(BondCashflows)

额外说明

  • 折现因子转换:如果已有估值日到现金流日的折现因子DF(E, C),也可通过DF(S, C) = DF(E, C) / DF(E, S)计算,其中DF(E, S)是估值日到结算日的折现因子,等价于curve.discount(settlement_date)
  • 全价验证:债券全价 = 各现金流用结算日折现因子折现后的总和 + 应计利息,可通过此逻辑验证结果正确性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 16:20:09