Skip to content

到期收益率、即期收益率、远期收益率、久期、凸性

约 4560 字大约 15 分钟

债券固定收益Python收益率

2025-07-04

一、基本概念

PP是债券价格,ytmytm是收益率,CCMMnn是已知的票息、面值、期限。

P=i=1nC(1+ytm)i+...+M(1+ytm)nP=\sum^n_{i=1}\frac{C}{(1+ytm)^i}+...+\frac{M}{(1+ytm)^n}

1.1 到期收益率

到期收益率(Yield to Maturity,YTM)是指投资者持有一定期限的债券,一直持有到债券到期时所能获得的年化收益率。它是考虑债券的购买价、票面价值、到期期限和利息支付频率等因素后的综合指标。到期收益率反映了投资者在债券投资中可能获得的实际回报。

1.1.1 单利

对于处于最后付息周期的固定利率债券和浮动利率债券、待偿还期在1年以内的到期一次还本附息债券和零息债券,到期收益率按照单利计算。

y=FVPVPVDTy=\frac{\frac{FV-PV}{PV}}{\frac{D}{T}}

其中,

  • yy:到期收益率
  • FVFV:到期兑付日债券本息和,固定利率债券为M+C/ f,到期一次还本付息债券为M+N×C,零息券为M
  • PP:债券全价
  • DD:债券结算日至到期付日的实际天数
  • MM:债券面值
  • NN:债券期限(年),即从起日至到期兑付日的整年
  • CC:债券面年利息
  • ff:年付息频率
  • TT:当前计息年度的实际天数,算头不算尾前计息年度的实际天数,算头不算尾

1.1.2 复利

1.1.2.1 对待偿还期在1年以上的到期一次还本附息债券和零息债券,到期收益率按复利计算。

PV=FV(1+y)dTY+mPV=\frac{FV}{(1+y)^{\frac{d}{TY}+m}}

其中:

  • PVPV:债券全价
  • FVFV:到期兑付日债券本息和,到期一次还本付息债券为M+N×C,零息债券为M
  • yy:到期收益率
  • dd:结算日至下一最近理论付息日的实际天数
  • mm:结算日至到期兑付日的整年数
  • MM:债券面值
  • NN:债券期限(年),即从起息日至到期兑付日的整年数
  • CC:债券票面年利息
  • TT:当前计息年度的实际天数,算头不算尾:当前计息年度的实际天数,算头不算尾
#对待偿还期在1年以上的到期一次还本附息债券和零息债券
'''计算债券到期收益率的函数
    bondtype:表示债券类型,1为到期一次还本付息债券,2为零息债券;
    PV:表示债券全价;
    M:债券面值;
    C:票面年利息;
    N:债券期限(年),即从起息日至到期兑付日的整年数;
    y:到期收益率;
    d:结算日至下一最近理论付息日的实际天数;
    m:结算日至到期兑付日的整年数;
    T:当前计息年度的实际天数,算头不算尾
'''
def YTM_coupond(bondtype,PV,M,C,N,d,m,T):
    if bondtype==1:
        FV=M+N*C
    else: 
        FV=M
    return (FV/PV)**(1/(d/T+m))-1
YTM_coupond(bondtype=1,PV=105.8932,M=100,C=5.5,N=3,d=342,m=2,T=365)
0.03303677003445582

1.1.2.2 对不处于最后付息周期的固定利率债券,到期收益率按复利计算。

PV=C/f(1+y/f)dTS+C/f(1+y/f)dTS+1...+C/f(1+y/f)dTS+n1+M(1+y/f)dTS+n1PV=\frac{C/f}{(1+y/f)^{\frac{d}{TS}}}+\frac{C/f}{(1+y/f)^{\frac{d}{TS}+1}}...+\frac{C/f}{(1+y/f)^{\frac{d}{TS}+n-1}}+\frac{M}{(1+y/f)^{\frac{d}{TS}+n-1}}

其中:

  • PV:债券全价
  • C:票面年利息
  • f:年付息频率
  • y:到期收益率
  • d:债券结算日至下一最近付息日之间的实际天数
  • n:结算日至到期兑付日的债券付息次数
  • M:债券面值
  • TS:当前付息周期的实际天数
import numpy as np
#对不处于最后付息周期的固定利率债券
'''计算债券到期收益率的函数
    PV:表示债券全价;
    C:票面年利息;
    k:年付息频率;
    y:到期收益率;
    d:债券结算日至下一最近付息日之间的实际天数;
    n:结算日至到期兑付日的债券付息次数;'
    M:债券面值;
    TS:当前付息周期的实际天数。'''
def YTM_fixbond_nolastcoupon(PV,C,k,d,n,M,TS):
    import scipy.optimize as so
    import numpy as np
    def f(y):
        coupon=[]
        for i in np.arange(0,n):
            coupon.append((C/k)/pow(1+y/k,d/TS+i))
        return np.sum(coupon)+M/pow(1+y/k,d/TS+n-1)-PV  #相当于输出一个等于0的式子
    return so.fsolve(f,0.1)     #0.1为猜测的求解值
ytm = YTM_fixbond_nolastcoupon(PV=102.3124,C=3.29,k=2,d=3,n=18,M=100,TS=186)
print(np.round(ytm,6))
[0.031962]

1.1.3 浮息债券的到期收益率

依据以下公式计算浮息债券时,每一付息周期需要根据现金流的变化做调整。例如,非含权、非提前还本浮动利率债券,非处于最后付息周期的浮息债券计算如下:

PV=(R1+r)T1(1+y/f)dTS+(R2+r)T1(1+y/f)dTS+1+...+(R2+r)Tn+M(1+y/f)dTS+n1PV=\frac{(R_1+\triangle r)*T_1}{(1+y/f)^{\frac{d}{TS}}}+\frac{(R_2+\triangle r)*T_1}{(1+y/f)^{\frac{d}{TS}+1}}+...+\frac{(R_2+\triangle r)*T_n+M}{(1+y/f)^{\frac{d}{TS}+n-1}}

  • PV:债券全价
  • R1:当前付息周期的基准利率,根据基准利率确定日规则决定
  • R2:计算日基准利率
  • Ti:根据债券计息基准计算的计息区间年化期限
  • △r:债券基本利差
  • y:到期收益率;
  • f:年付息频率
  • d:估值日至下一最近理论付息日的实际天数
  • TS:当前付息周期的实际天数
  • n:未来付息次数
  • M:债券面值
#非含权、非提前还本浮动利率债券,非处于最后付息周期的浮息债券
'''计算浮动利率债券的到期收益率;
    R2:估值日基准利率
    R:付息周期基准利率;
    T:根据债券计息基准计算的计息区间年化期限;
    r:债券基本利差;
    y:设该债券待偿期为T,点差收益率曲线T期限对应的点差;
    f:年付息频率;
    d:债券结算日至下一最近付息日之间的实际天数;
    n:结算日至到期兑付日的债券付息次数;'
    M:债券面值;
    TS:当前付息周期的实际天数。'''
def Float_Bond_ytm_nolastcoupon(PV,R2,R,T,r,k,d,n,M,TS):
    import scipy.optimize as so
    import numpy as np
    def f(y):
        coupon=[]
        for i in np.arange(0,n):
            coupon.append(M*(R[i]+r)*T[i]/pow(1+y/k,d/TS+i))
        return np.sum(coupon)+M/pow(1+y/k,d/TS+n-1)-PV 
    return so.fsolve(f,0.1)     #0.1为猜测的求解值

R2=2.7200/100
R=[2.6/100,R2,R2]
T=[92/360,92/360,89/360]
Bond_yield4=Float_Bond_ytm_nolastcoupon(PV=100.7499,R2=R2,R=R,T=T,r=0.1/100,k=4,d=26,n=3,M=100,TS=92)
print(np.round(Bond_yield4,6))
[0.023746]

1.2 即期收益率

即期收益率(spot rate)就是我们最常理解的收益率,也称零息债券收益率,是指零息债券的到期收益率,本质上附息债券可分解为一系列现金流来构建即期收益率曲线,计算公式如下。在债券市场中,即期收益率曲线被认为是真实的利率期限结构,因为考虑来再投资风险,该曲线也是确定债券相对价值的最好曲线。

PV=i=1nC(1+rsn)n+M(1+rsn)nPV=\sum^n_{i=1}\frac{C}{(1+rs_n)^n}+\frac{M}{(1+rs_n)^n}

  • PVPV:债券现值
  • nn:现金流的时间期数
  • CC:每期的现金流金额
  • MM:未来时点的剩余价值(通常是未来某个时刻的终值或剩余值)
  • rr:折现率(discount rate)
  • sns_n:折现因子(discount factor),它是(1+r)n(1+r)^{-n}

1.3 远期收益率

远期收益率是指债券在未来的即期收益率,即隐含在给定的即期利率中从未来的某一个时间点到另一个时点的利率水平。远期收益率可以根据当前的即期利率推到,推到的利率称为隐含远期利率,具体如下:

(1+rSn)n=(1+r0f1)(1+r1f2)...(1+rn1fn)(1+rS_n)^n=(1+r_0f_1)(1+r_1f_2)...(1+r_{n-1}f_n)

在连续时间下,即期利率r(t)与瞬时远期利率f(t)关系如下:

r(t)t=01f(u)dur(t)t=\int_0^1 f(u)du

1.4 麦氏久期(DmacD_{mac})

麦考利久期(Macaulay Duration)是衡量一只债券每笔现金流的加权平均回本时间(不是总时间),即债券的加权平均剩余期限的方法。麦氏久期的单位是年。它考虑了债券的剩余期限和每期现金流的现值。

Dmac=i=1TWi×TiD_{mac}=\sum_{i=1}^T W_i\times T_i

其中:

  • CFi是指第i笔现金流金额CF_i 是指第i笔现金流金额
  • YTM是指到期收益率YTM 是指到期收益率
  • PVi是指第i笔现金流的贴现值PV_i 是指第i笔现金流的贴现值
  • Ti是指第i笔现金对应的时间T_i 是指第i笔现金对应的时间
  • Wi=PViPVW_i=\frac{PV_i}{PV}
  • PVi=CFi(1+YTM)iPV_i=\frac{CF_i}{(1+YTM)^i}
  • PV=i=1TPViPV=\sum_{i=1}^T PV_i
  • CFi=Cr,其中C表示债券面值,r表示票面利率CF_i=C*r,其中C表示债券面值,r表示票面利率

Dmac=i=1TPViPV×TiD_{mac}=\sum_{i=1}^T \frac{PV_i}{PV}\times T_i

Dmac=i=1TCFi(1+YTM/freq)iPV×TiD_{mac}=\sum_{i=1}^T \frac{\frac{CF_i}{(1+YTM/freq)^i}}{PV}\times T_i

Dmac=i=1TTi×CFi(1+YTM/freq)i×1PVD_{mac}=\sum_{i=1}^T \frac{T_i \times CF_i}{(1+YTM/freq)^i}\times \frac{1}{{PV}}

怎么计算麦氏久期?

假设某只5年期的债券面额为100元,息票率为5%,到期收益率为10%,其现金流如下表所示:

接下来,我们计算债券的现值 PV,即所有未来现金流的折现值之和:

PV=i=110[CFi(1+YTM)i]+F(1+YTM)TPV=\sum_{i=1}^{10} \Big[ \frac{CF_i}{(1+YTM)^i}\Big]+\frac{F}{(1+YTM)^T}

F=100
r=5/100
T=5
YTM=10/100
import numpy as np
def PV(F, r, YTM, T):
    sum_pv = []
    for i in range(1,T):
        present_value = (F * r / (1 + YTM) ** (i))
        sum_pv.append(present_value)
    # 计算并四舍五入债券的现值
    bond_pv = round(np.sum(sum_pv) + (F+r*F) / (1 + YTM) ** T, 2)
    return bond_pv
bond_pv = PV(F,r,YTM,T)
bond_pv
81.05

现在,我们计算麦考利久期DmacD_{mac}

Dmac=i=1TTi×CFi(1+YTM)i×1PVD_{mac}=\sum_{i=1}^T \frac{T_i \times CF_i}{(1+YTM)^i}\times \frac{1}{{PV}}

import numpy as np

def MacDuration(bond_pv, T, r, F, YTM):
    sum_mac = []
    for i in range(1, T):  # 使用t来避免重新赋值i
        sum_mac.append(i * (F * r / (1 + YTM) ** i) / bond_pv)
    # 最后一期的现金流(本金加利息)的加权平均时间
    sum_mac.append((T * (F + F * r) / (1 + YTM) ** T) / bond_pv)
    d_mac = round(np.sum(sum_mac),2)
    # 计算并返回麦考利久期
    return d_mac
MacDuration(bond_pv,T,r,F,YTM)
4.49

1.5 修正久期(DmodD_{mod})

麦氏久期只是衡量加权平均回本时间,并没有考虑其他特征。 比如,债券价格波动,如何衡量呢? 修正久期应运而生,修正久期,是衡量一只债券的债券价格对收益率变化的敏感程度的指标。 即,求P对ymt的一阶导,过程如下所示:

$债券价格公式: P = \sum_{i=1}^{T} \frac{c_i}{(1+y)^i} $

\Downarrow

$ 对y求一阶导: dP = -i\times \sum_{i=1}^{T} \Big[\frac{c_i}{(1+y)^{i+1}} dy \Big] $

\Downarrow

$dP = -\frac{D_{mac}\times P}{1+y} dy $

\Downarrow

两边同时除以P,然后提出公因子,得到:

dPP=Dmac1+ydy\frac{dP}{P}=-\frac{D_{mac}}{1+y}dy

Dmod=Dmac1+y/mm是每年内付息次数D_{mod}=-\frac{D_{mac}}{1+y/m},m是每年内付息次数

mac_duration = MacDuration(bond_pv,T,r,F,YTM)
def ModifiedDuration(mac_duration, YTM, m=1):
    d_mod = -mac_duration / (1 + YTM / m)
    return round(d_mod, 2)
ModifiedDuration(mac_duration, YTM, m=1)
-4.08

修正久期,是衡量一只债券的债券价格对收益率变化的敏感程度的指标。

Dmod=PVPV+2(Yield)PV0D_{mod}=\frac{PV_{-}-PV_{+}}{2*(Yield)*PV_0}

1.6 组合久期

债券组合的久期是由组合中单个债券的久期乘以该债券价值在总组合价值之比计算得来:

Dportfolio=n=1NWN×DND_{portfolio}=\sum_{n=1}^N W_N \times D_N

1.7 凸性

凸性,是指久期对于收益率变化的敏感度,即,当收益率变化一个单位时,久期的变化幅度。 因为久期本身也是随着到期收益率y的变化而变化,无法完全代表价格对利率变动的敏感性,因此根据久期作出预测将有所偏离。 我们对价格收益率曲线进行二次求导,即对久期求导,得出的公式再除以价格P,我们称为凸性。

$债券价格公式: P = \sum_{i=1}^{T} \frac{c_i}{(1+y)^i} $

$ 对y求一阶导: dP = -i\times \sum_{i=1}^{T} \Big[\frac{c_i}{(1+y)^{i+1}} dy \Big] $

$ 对y二次求导: \frac{d2P}{dy2} = \sum_{i=1}^{T} \Big[\frac{i\times(i+1)\times c_i}{(1+y)^{i+2}} dy \Big] $

两边同时除以P,然后提出公因子,得到:

凸性(Convexity=C=1P×d2Pdy2=1P×i=1T[i×(i+1)×ci(1+y)i+2dy]凸性(Convexity)=C= \frac{1}{P}\times \frac{d^2P}{dy^2} =\frac{1}{P}\times\sum_{i=1}^{T} \Big[\frac{i\times(i+1)\times c_i}{(1+y)^{i+2}} dy \Big]

1.8 DV01

1.8.1 DV01是指当收益率变动1个基点(0.01%)时,债券价格的变化量。

DV01=ΔPΔr=PP0.01DV01=\frac{\Delta P}{\Delta r}=\frac{P-P^*}{0.01}

其中:

  • P是债券在当前利率下的价格P是债券在当前利率下的价格
  • P是债券在利率上升一个基点后的价格P*是债券在利率上升一个基点后的价格

1.8.2 DV01对冲:DV01对冲的目的是确保投资组合的DV01总和为零,从而使得投资组合的市场价值对利率变动不敏感。

对冲比率=对冲工具的DV01被对冲债券的DV01对冲比率= \frac {对冲工具的DV01}{被对冲债券的DV01}

FB=FA×DV01ADV01BF^B=\frac{F^A \times DV01^A}{DV01^B}

其中:

  • DV01^A 表示对冲工具的DV01
  • DV01^B 表示被对冲标的或组合的DV01
  • F^A 表示对冲工具的的面值总额
  • F^B 表示被对冲标的或组合的的面值总额

对冲的步骤:

  • 确定对冲目标:首先,需要确定哪些债券或资产需要进行对冲。
  • 计算DV01:对于需要对冲的每个债券,计算其DV01值。
  • 选择对冲工具:选择适当的对冲工具,比如利率互换,其DV01也需要计算。
  • 确定对冲比率:通过比较需要对冲的债券的DV01和对冲工具的DV01,确定所需的对冲比率。
  • 执行对冲交易:根据对冲比率,执行相应的买入或卖出交易,以建立对冲头寸。
  • 监控和调整:持续监控市场条件和投资组合价值,必要时调整对冲头寸以维持DV01的中性。

1.9 有效久期

有效久期,是指无风险收益率曲线发生1个单位的平移后,债券价格的变化幅度。

Deff=PVPV+2(Curve)PV0D_{eff}=\frac{PV_{-}-PV_{+}}{2*(Curve)*PV_0}

2.0 有效凸性

2.1 基于有效久期和凸性的对冲

2.2 关键利率久期(Key-Rate Duration, KRD)

关键利率久期,是指无风险收益率曲线在某一个关键期限的收益率上发生1个单位的变化后,债券价格的变化幅度。 是一种分析固定收益证券价格对关键期限利率变化敏感性的方法。它特别关注金融市场交易者心理中至关重要的整数期限利率,如1年期、5年期和10年期。

计算单个关键利率期限的久期的公式:

KRDt=i=1nPVi(Rt+ΔR)PVi(Rt)PV(Rt)Rt×ΔRKRD_t=\frac{\sum_{i=1}^n\frac{PV_i(R_t+\Delta R)-PV_i(R_t)}{PV(R_t)}}{R_t}\times \Delta R

其中:

  • KRDt是关键利率久期KRD_t 是关键利率久期
  • t是关键利率期限t是关键利率期限
  • PVi是第i个现金流在原始利率Rt下的现值PV_i是第i个现金流在原始利率R_t下的现值
  • PVRt)是债券在原始利率Rt下的总现值PV(R_t)是债券在原始利率R_t下的总现值
  • ΔR是利率变化的微小量\Delta R是利率变化的微小量
def calculate_pv(yield_rate, duration):
    """
    模拟债券估价全价的函数。
    :param yield_rate: 收益率
    :param duration: 债券的期限
    :return: 债券的估价全价
    """
    # 这里我们简单地模拟估价全价,实际情况需要根据具体的债券定价模型计算
    base_pv = 100  # 假设债券面值为100
    pv = base_pv / (1 + yield_rate * duration)
    return pv

def calculate_key_duration(PV0, PV_plus, PV_minus, delta_r):
    """
    计算关键利率久期。
    :param PV0: 债券的日间估价全价
    :param PV_plus: 收益率向上变动后的估价全价
    :param PV_minus: 收益率向下变动后的估价全价
    :param delta_r: 收益率变动值,通常为1BP(0.01%)
    :return: 关键利率久期
    """
    KeyDuri = (PV_plus - PV_minus) / (2 * PV0) * delta_r
    return KeyDuri

# 假设数据
delta_r = 0.0001  # 1BP
durations = [1/365, 1/12, 2/12, 3/12, 6/12, 9/12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 30, 40, 50]  # 期限点对应的年化时间
PV0_values = [calculate_pv(0.01, duration) for duration in durations]  # 假设的PV0值

# 计算每个关键期限点的关键利率久期
key_durations = []
for i, PV0 in enumerate(PV0_values):
    PV_plus = calculate_pv(0.01 + delta_r, durations[i])
    PV_minus = calculate_pv(0.01 - delta_r, durations[i])
    KeyDuri = calculate_key_duration(PV0, PV_plus, PV_minus, delta_r)
    key_durations.append(KeyDuri)

# 输出结果
for i, duration in enumerate(durations):
    print(f"期限点: {duration:.2f}年, 关键利率久期: {key_durations[i]:.4f}")
期限点: 0.00年, 关键利率久期: -0.0000
期限点: 0.08年, 关键利率久期: -0.0000
期限点: 0.17年, 关键利率久期: -0.0000
期限点: 0.25年, 关键利率久期: -0.0000
期限点: 0.50年, 关键利率久期: -0.0000
期限点: 0.75年, 关键利率久期: -0.0000
期限点: 1.00年, 关键利率久期: -0.0000
期限点: 2.00年, 关键利率久期: -0.0000
期限点: 3.00年, 关键利率久期: -0.0000
期限点: 4.00年, 关键利率久期: -0.0000
期限点: 5.00年, 关键利率久期: -0.0000
期限点: 6.00年, 关键利率久期: -0.0000
期限点: 7.00年, 关键利率久期: -0.0000
期限点: 8.00年, 关键利率久期: -0.0000
期限点: 9.00年, 关键利率久期: -0.0000
期限点: 10.00年, 关键利率久期: -0.0000
期限点: 15.00年, 关键利率久期: -0.0000
期限点: 20.00年, 关键利率久期: -0.0000
期限点: 30.00年, 关键利率久期: -0.0000
期限点: 40.00年, 关键利率久期: -0.0000
期限点: 50.00年, 关键利率久期: -0.0000

2.3 组合关键利率久期怎么计算?

整个投资组合的关键利率久期,等于组合中每只债券的关键利率久期的加权平均:

KRDi=j=1Nwj×krdj,iKRD_i=\sum_{j=1}^Nw_j\times krd_{j,i}

其中:

  • KRDi:投资组合在关键期限i上的关键利率久期KRD_i:投资组合在关键期限i上的关键利率久期
  • wj:债券j的市值在投资组合中的占比w_j:债券j的市值在投资组合中的占比
  • krdj,i:债券j在关键期限i上的关键利率久期krd_{j,i}:债券j在关键期限i上的关键利率久期

2.4 如何计算关键利率DV01?

DV01i=KeyDuri×PV010000DV01_i=KeyDur_i \times \frac{PV_0}{10000}

其中:

  • DV01i:债券的关键利率基点价值DV01_i:债券的关键利率基点价值
  • KeyDuri:债券的关键利率久期KeyDur_i:债券的关键利率久期
  • PV0:债券的日间估价全价PV_0:债券的日间估价全价

注意:

投资组合关键利率(或期限)DV01同样采用各个债券的加权平均计算。

2.5 组合DV01怎么计算?

组合DV01i=j=1Nwj×DV01i组合DV01_i=\sum_{j=1}^Nw_j \times DV01_i

其中:

  • DV01i:债券的关键利率基点价值DV01_i:债券的关键利率基点价值
  • wj:债券j的市值在投资组合中的占比w_j:债券j的市值在投资组合中的占比

2.6 某债券的关键利率久期之后和等于该债券的修正久期

关键利率久期=Dmod\sum关键利率久期=D_{mod}