4. 债券定价模型:零息债券、附息债券的定价公式,到期收益率(YTM)的计算与插值法
债券定价,说白了就是回答一个问题:这张债券现在值多少钱?
我刚开始做固收交易时,总觉得债券定价不就是折现嘛,有啥难的。直到有一次,我拿着零息债券的公式去算一个30年期国债,结果发现市场报价和我算出来的差了整整2块钱。嗯,后来我才意识到——计息基准、节假日调整、应计利息,这些细节才是真正吃人的地方。
今天咱们就把债券定价这件事拆开揉碎,从零息到附息,从YTM到插值法,一个一个过。
4.1 零息债券定价
零息债券,顾名思义,中间不付息,到期一次性还本。它的定价逻辑最简单:
零息债券定价公式:
P = F / (1 + r)^n
其中:P = 债券价格,F = 面值,r = 到期收益率(年化),n = 剩余期限(年)
举个例子:一张面值100元、剩余期限2年的零息债,假设市场要求的年化收益率是5%,那么它的价格就是:
P = 100 / (1 + 0.05)^2 = 100 / 1.1025 ≈ 90.70元
我在项目中遇到过一个问题:如果剩余期限不是整数年怎么办?比如还剩1年零3个月。这时候就不能直接用整数次方了,得用实际天数/365来算指数。
实战小技巧:很多交易系统用的是ACT/365计息基准,但有些债券市场(比如中国银行间)用的是ACT/360。我建议你写代码时,把计息基准作为参数传进去,别写死。
4.2 附息债券定价
附息债券就复杂一些了。它定期付息,到期还本。定价公式是:
附息债券定价公式:
P = Σ [C / (1 + r)^t] + F / (1 + r)^T
其中:C = 每期票息,t = 第t期,T = 总期数
说白了,就是把每一笔现金流(票息+本金)都折现到今天,然后加总。
举个例子:一张面值100元、票面利率5%、每年付息一次、剩余期限3年的债券,市场收益率是4%。它的价格是:
P = 5/(1.04)^1 + 5/(1.04)^2 + 5/(1.04)^3 + 100/(1.04)^3
= 4.808 + 4.623 + 4.445 + 88.900
= 102.776元
你看,当票面利率(5%)高于市场收益率(4%)时,债券价格高于面值,这叫溢价交易。反过来就是折价交易。
注意:附息债券定价时,有一个容易踩的坑——应计利息。如果你在两个付息日之间买入债券,你需要支付给卖方从上一个付息日到交割日这段时间的利息。这个利息叫应计利息,全价 = 净价 + 应计利息。我刚开始做交易时,有一次忘了加应计利息,结果报价比市场低了0.5元,被做市商秒吃...嗯,从那以后我再也不敢忘了。
4.3 到期收益率(YTM)的计算
YTM是什么?你买入债券后,持有到期的年化收益率。它其实就是让债券定价公式两边相等的那个折现率。
对于零息债券,YTM可以直接算:
r = (F / P)^(1/n) - 1
但对于附息债券,YTM没有解析解,只能用数值方法求解。最常用的就是牛顿迭代法。
我给大家写一个简单的Python实现:
def ytm_calculator(price, face, coupon, periods, guess=0.05):
"""
用牛顿法计算到期收益率
price: 债券价格
face: 面值
coupon: 每期票息
periods: 剩余期数
guess: 初始猜测值
"""
r = guess
for i in range(100): # 最多迭代100次
# 计算当前价格
pv = sum([coupon / (1 + r)**t for t in range(1, periods + 1)])
pv += face / (1 + r)**periods
# 计算导数
dpv = sum([-t * coupon / (1 + r)**(t+1) for t in range(1, periods + 1)])
dpv += -periods * face / (1 + r)**(periods + 1)
# 更新r
r_new = r - (pv - price) / dpv
# 收敛判断
if abs(r_new - r) < 1e-8:
return r_new
r = r_new
return r # 返回近似值
个人经验:牛顿法的初始猜测很重要。我一般用票面利率作为初始值,或者用当前价格/面值做个粗略估计。如果初始值选得太离谱,迭代可能会发散。
4.4 插值法:当YTM不是整数期限时
现实交易中,你很少能遇到正好是整数年的债券。比如,一个债券还剩2.3年到期,你怎么算它的YTM?
这时候就需要插值法了。最常用的是线性插值和三次样条插值。
线性插值最简单:
假设已知:
- 2年期YTM = 3.0%
- 3年期YTM = 3.5%
求2.3年期YTM:
YTM(2.3) = 3.0% + (3.5% - 3.0%) * (2.3 - 2) / (3 - 2)
= 3.0% + 0.5% * 0.3
= 3.15%
但线性插值有个问题——它假设收益率曲线是直线,而实际上收益率曲线往往是弯曲的。所以更精确的做法是用三次样条插值或Nelson-Siegel模型。
避坑指南:我曾经在做一个国债期货定价项目时,用了线性插值来算YTM,结果发现期货的理论价格和实际价格差了0.3个点。后来换成三次样条插值,误差降到了0.05个点以内。所以,如果你的精度要求高,别偷懒用线性插值。
4.5 知识体系总览
下面这张图,把债券定价的核心逻辑串起来了:
这张图把整个知识脉络理清了:从债券定价出发,分零息和附息两条线,然后引出YTM的计算,最后用插值法解决非整数期限的问题。你写代码时,也可以按这个结构来组织你的函数。
4.6 实战中的几个坑
最后,我把自己踩过的几个坑分享给你:
- 计息基准不一致:不同市场用不同基准(ACT/365、ACT/360、30/360等),一定要确认清楚。
- 节假日调整:付息日如果遇到节假日,要顺延到下一个工作日。这个会影响现金流的时间。
- YTM的局限性:YTM假设所有现金流都能以YTM再投资,这在现实中很难做到。所以YTM只是一个近似指标,别把它当绝对真理。
- 插值法的选择:线性插值简单但粗糙,三次样条插值精确但复杂。我建议你根据精度需求来选,别盲目追求复杂。
一句话总结:债券定价的核心就是现金流折现,YTM就是那个让等式成立的折现率,插值法就是处理非整数期限的工具。把这三点吃透了,债券定价这块你就拿下了。