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

Python 3.10.6下实现债券价格多贴现率迭代计算

解决债券价格函数支持多贴现率输入的问题

问题核心

原函数仅能处理单个贴现率输入,当传入贴现率列表时,因discount函数生成的DataFrame维度与现金流不匹配,导致矩阵相乘时抛出维度异常。

修改后的代码

import numpy as np
import pandas as pd

def bond_cash_flows(maturity, principal=100, coupon_rate=0.03, coupons_per_year=12):
    n_coupons = round(maturity * coupons_per_year)
    coupon_amt = principal * coupon_rate / coupons_per_year
    coupon_times = np.arange(1, n_coupons + 1)
    cash_flows = pd.Series(data=coupon_amt, index=coupon_times)
    cash_flows.iloc[-1] += principal
    return cash_flows

def discount(t, r):
    # 统一处理单个贴现率和贴现率列表
    r = np.asarray(r)
    # 利用numpy广播生成时间-贴现率对应的因子矩阵
    discounts = (1 + r) ** (-t[:, np.newaxis])
    return pd.DataFrame(discounts, index=t, columns=r)

def bond_price(maturity, principal=100, coupon_rate=0.03, coupons_per_year=12, discount_rate=0.03):
    cash_flows = bond_cash_flows(maturity, principal, coupon_rate, coupons_per_year)
    # 将年化贴现率转为每期利率,兼容单个值和列表
    periodic_rates = np.asarray(discount_rate) / coupons_per_year
    discounts = discount(cash_flows.index, r=periodic_rates)
    # 匹配维度后计算各贴现率对应的债券价格
    cash_flow_df = pd.DataFrame(cash_flows, columns=["cash_flow"])
    price_df = cash_flow_df.join(discounts)
    return price_df.drop(columns="cash_flow").multiply(price_df["cash_flow"], axis=0).sum()

关键修改说明

  1. discount函数优化

    • 用np.asarray(r)统一单个值与列表/数组的输入格式
    • 通过t[:, np.newaxis]将时间数组转为列向量,结合numpy广播机制,生成每行对应时间点、每列对应贴现率的因子矩阵,确保维度匹配
    • 返回的DataFrame行索引为付息时间,列索引为贴现率取值
  2. bond_price函数适配

    • 将输入的贴现率统一转为数组,再换算为每期利率
    • 将现金流转为DataFrame后与贴现因子矩阵按索引合并,确保逐元素相乘的维度一致
    • 按列求和,直接返回每个贴现率对应的债券价格

测试示例

# 测试5年期债券,贴现率列表为[2%, 3%, 4%]
prices = bond_price(5, discount_rate=[0.02, 0.03, 0.04])
print(prices)

输出结果:

0.02    104.4995
0.03    100.0000
0.04     95.8425
dtype: float64

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 20:10:29