如何在QuantLib中提取以债券结算日为基准的折现因子
以债券结算日为基准提取折现因子的方法
核心逻辑
折现因子本质是两个日期之间的现金流折现系数:
- 估值日(Evaluation Date)到现金流日的折现因子:
curve.discount(cashflow_date) - 结算日(Settlement Date)到现金流日的折现因子:
curve.discount(settlement_date, cashflow_date)
你代码里尝试的curve.discount(bond.settlementDate(), row['date'])逻辑是正确的,只需优化细节确保结果准确。
代码优化与细节修正
原代码思路没问题,但有几个可改进的点:
- 替换
eval():直接调用Coupon对象方法更安全易维护 - 统一日期类型:确保所有日期都是QuantLib的
ql.Date对象,避免类型不一致导致错误 - 明确日计数规则:和构建收益率曲线时的规则保持一致
修正后的代码如下:
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
相关产品推荐
相关产品推荐

