2. 附息债券现金流与定价
任务说明
构建一只附息债券的现金流表:每期票息 + 到期本金,然后用给定的即期贴现因子对每笔现金流贴现并加总,得到债券理论价格。同时计算应计利息与全价,便于与市场报价(净价)对照。
实现思路
- 输入:面值、票息率、付息频率、剩余期数、每期贴现因子。
- 现金流表:第 1..n-1 期只有票息,第 n 期票息 + 面值。
- 理论价格 = Σ 现金流t × 贴现因子t。
- 应计利息按“上一付息日到结算日”的占比计算,全价 = 净价 + 应计利息。
核心代码
from dataclasses import dataclass
@dataclass
class Bond:
face: float # 面值
coupon_rate: float # 年票息率
freq: int # 每年付息次数
periods: int # 剩余付息期数
def cashflows(self):
"""返回 [(期数, 现金流)],最后一期含本金。"""
c = self.face * self.coupon_rate / self.freq
flows = [(t, c) for t in range(1, self.periods)]
flows.append((self.periods, c + self.face))
return flows
def price(self, discount_factors):
"""用即期贴现因子对现金流贴现并加总。"""
assert len(discount_factors) == self.periods, "贴现因子数量须等于期数"
return sum(cf * df for (_, cf), df in zip(self.cashflows(), discount_factors))
def accrued_interest(self, days_since_last, days_in_period):
"""应计利息:票息 × 已过天数占比。"""
c = self.face * self.coupon_rate / self.freq
return c * days_since_last / days_in_period
if __name__ == "__main__":
bond = Bond(face=100.0, coupon_rate=0.06, freq=2, periods=4)
# 4 期即期贴现因子(示例输入)
dfs = [0.9709, 0.9426, 0.9151, 0.8885]
flows = bond.cashflows()
print("期数 现金流 贴现因子 现值")
for (t, cf), df in zip(flows, dfs):
print(f"{t:>3} {cf:>7.3f} {df:>8.4f} {cf*df:>8.4f}")
clean = bond.price(dfs)
ai = bond.accrued_interest(days_since_last=45, days_in_period=180)
print(f"\n理论净价 = {clean:.4f}")
print(f"应计利息 = {ai:.4f}")
print(f"全价 = {clean + ai:.4f}")
运行与验证
python bond_pricing.py
判定标准:
- 现金流表共 4 行,前 3 行为票息 3.000,第 4 行为 103.000(票息 + 面值)。
- 理论净价等于各行“现值”之和,即 2.9127 + 2.8278 + 2.7453 + 91.5155 = 100.0013(由代码逻辑唯一确定)。
- 应计利息 = 3.000 × 45/180 = 0.7500,全价 = 净价 + 0.7500。
关键点
贴现因子数量必须与剩余期数一致,否则 assert 会报错;票息按 面值 × 年票息率 / 付息频率 计算,最后一期现金流需加上面值。若贴现因子来自即期利率曲线,可先用 df = 1 / (1 + z_t)**t 生成后再传入 price。