付息/零息债券的定价——基于单一贴现率
一般复利下,债券价格P = ΣCt/(1+y)t+F/(1+y)T;连续复利下,P = ΣCte-yt+Fe-yT,Ct是第t期支付的现金流,F为债券面值,y为贴现率。
例1:一新发行的3年期债券面值1000元,票面利率10%,每半年付息,贴现率10%,求债券价格:
def bp(ct,F,y,t):
a=ct/(1+y)**t
b=F/(1+y)**len(t)
return sum(a,b)
import pandas as pd
y=0.1/2;F=1000;ct=1000*0.1*0.5
t=pd.Series([1,2,3,4,5,6])
bp(ct,F,y,t)
Out[1]: 999.9999999999998#平值债券
例2:一个8年期的零息债券面值1000元,每半年付息,市场年利率8%,求债券价格:
def bp0(F,y,t):
b=F/(1+y)**t
return b
y=0.08/2;F=1000;t=8*2
bp0(F,y,t)
Out[2]: 533.9081756858412
例3:“08国开11”债券的面值为100元,期限20年,票面利率5.25%,每半年付息。假定该债券剩余期限10年,贴现率为4.2%(连续复利),求债券今天的价格:
import numpy as np
def bondp(F,r,y,t):#r,y,t均为每一期对应数据
a=F*r*np.exp(-y*t)
b=F*np.exp(-y*len(t))
return sum(a,b)
t=pd.Series(range(1,21))
bondp(100,0.0525/2,0.042/2,t)
Out[3]: 108.12527888522294
付息债券的定价——基于不同期限贴现率
息票剥离法计算零息利率
例4:在国内债券市场,期限在1年以内(不含1年)的短期国债是不带票息的零息债券。根据下表不同期限国债(面值均为100)的信息计算各期限的零息利率(连续复利):
序号 | 剩余期限 | 票面利率 | 债券价格 |
---|---|---|---|
1 | 0.25 | 0 | 99.42元 |
2 | 0.5 | 0 | 98.83元 |
3 | 1 | 2.77%(每年付息) | 100.09元 |
4 | 1.5 | 3.46%(半年付息) | 101.32元 |
5 | 2 | 2.53%(半年付息) | 99.39元 |
from scipy import optimize
def f(r):
r1,r2,r3,r4,r5=r
p1,p2,p3,p4,p5=99.42,98.83,100.09,101.32,99.39
c3,c4,c5=0.0277,0.0346/2,0.0253/2#注意半年付息的要除以2
b1=100*np.exp(-r1*0.25)-p1
b2=100*np.exp(-r2*0.5)-p2
b3=100*(1+c3)*np.exp(-r3*1)-p3
b4=100*(1+c4)*np.exp(-r4*1.5)+c4*100*np.exp(-r3*1)\
+c4*100*np.exp(-r2*0.5)-p4
b5=100*(1+c5)*np.exp(-r5*2)+c5*100*np.exp(-r4*1.5)\
+c5*100*np.exp(-r3*1)+c5*100*np.exp(-r2*0.5)-p5
return [b1,b2,b3,b4,b5]
zerorates=optimize.fsolve(f,[0.1,0.1,0.1,0.1,0.1])
zerorates#分别对应0.25,0.5,1,1.5,2年的零息利率
Out[4]: array([0.02326754, 0.02353797, 0.0264237, 0.02541116, 0.028313])
基于不同期限的零息利率给债券定价
不同期限的贴现率不一样,即y也作为一个数组输入,需要用append函数。
例5:有一个剩余期限为1.5年的债券,面值为100元,票面利率3.46%,每半年付息。0.5年、1年、1.5年的零息利率分别为4.7076%,5.2848%,5.0822%(连续复利),求债券今天的价格:
def bond_value(y,t,r,F):
cashflow=[]
for i in range(len(t)):
a=F*r*np.exp(-y[i]*t[i])
cashflow.append(a)
b=F*np.exp(-y[len(t)-1]*t[len(t)-1])
return sum(cashflow)+b
y=pd.Series([0.047076,0.052848,0.050822])*0.5
t=pd.Series([0.5,1,1.5])
bond_value(y,t,0.0346/2,100)
Out[5]: 101.32002263990809
有时我们能够算出的零息利率期限间隔不一样,比如例4中没有0.75年、1.25年、1.75年的债券数据,这时我们就要进行插值处理:
t=np.array([0.25,0.5,1,1.5,2])
T=np.array([0.25,0.5,0.75,1,1.25,1.5,1.75,2])
from scipy.interpolate import interp1d
f=interp1d(t,zerorates,kind='quadratic')
f(T)
Out[6]:
array([0.02326754, 0.02353797, 0.02509468, 0.0264237 , 0.02601105,
0.02541116, 0.02617848, 0.028313 ])
计算债券到期收益率(YTM)
例6:有一个剩余期限为5年的债券,面值为100元,票面利率5%,每半年付息。假设该债券的市场价格为98元,求债券的YTM:
from scipy import optimize
def YTM(F,r,t,P):
def f(y):#把要求解的方程写出来
cashflow=[]
for i in range(len(t)):
a=F*r*np.exp(-y*t[i])
cashflow.append(a)
b=F*np.exp(-y*t[len(t)-1])
return sum(cashflow)+b-P#此处返回一个等于零的式子
return optimize.fsolve(f,0.1)#f是要求解的函数,0.1是猜测解
t=pd.Series(np.linspace(0.5,5,10))
YTM(100,0.025,t,98)
Out[7]: array([0.05389247])
YTM的检查:当债券票面利率c>YTM时,投资人可以获得更多的收益,所以发行方会多收一部分钱,溢价发行;反之债券票面利率c<YTM时,发行方会折价发行来补偿投资者。