Skip to content

12.2 久期与凸度免疫

久期的三种定义

Macaulay 久期

Macaulay 久期是债券未来现金流的加权平均时间,权重为各期现金流现值占债券总现值的比例:

$$D_{\text{Mac}} = \frac{\sum_{t=1}^n t \cdot PV(CF_t)}{\sum_{t=1}^n PV(CF_t)} = \frac{\sum_{t=1}^n t \cdot \frac{CF_t}{(1+y)^t}}{P}$$

其中 CFt 为第 t 期的现金流,y 为到期收益率,P 为债券全价。

PYTHON33 行 · 899 B
📄此处有展示代码33 行 · 899 B展开 ▼
python
def macaulay_duration(cashflows, times, ytm):
    """
    计算 Macaulay 久期
    cashflows: 各期现金流(含本金和利息)
    times: 各期现金流的时间(年)
    ytm: 到期收益率
    """
    pv = []
    weighted_pv = []
    for cf, t in zip(cashflows, times):
        pv_cf = cf / (1 + ytm) ** t
        pv.append(pv_cf)
        weighted_pv.append(t * pv_cf)

    price = sum(pv)
    duration = sum(weighted_pv) / price
    return duration, price

# 示例:10年期债券,票面利率4%,YTM=4.5%
face_value = 100
coupon_rate = 0.04
ytm = 0.045
years = 10
freq = 2  # 半年付息
n = years * freq
coupon = face_value * coupon_rate / freq
cashflows = [coupon] * n
cashflows[-1] += face_value
times = [(i + 1) / freq for i in range(n)]

dur, price = macaulay_duration(cashflows, times, ytm)
print(f"Macaulay 久期: {dur:.2f} 年")
print(f"债券全价: {price:.2f}")
点击展开可浏览运行结果
Macaulay 久期: 8.30 年
债券全价: 96.40

修正久期

修正久期衡量债券价格对收益率变化的百分比敏感度:

$$D_{\text{mod}} = \frac{D_{\text{Mac}}}{1 + y/f}$$

其中 f 为年付息频率。修正久期近似为:

$$\frac{\Delta P}{P} \approx -D_{\text{mod}} \cdot \Delta y$$
名词解释:DV01 (Dollar Value of 01)

收益率变动1个基点(0.01%)时债券价格的变化金额。DV01 = Modified Duration * Price * 0.0001。这是交易台上最常用的利率风险度量。

有效久期

对于含权债券(如可赎回债、MBS),未来现金流不确定,因此需要使用有效久期:

$$D_{\text{eff}} = \frac{P_{-\Delta y} - P_{+\Delta y}}{2 \cdot P_0 \cdot \Delta y}$$

通过扰动收益率曲线,重新计算模型价格来得到。这是实务中最灵活的方式,因为它不需要计算预期现金流。

PYTHON9 行 · 316 B
📄此处有展示代码9 行 · 316 B展开 ▼
python
def effective_duration(price_function, P0, y0, dy=0.0001):
    """
    通过数值扰动计算有效久期
    price_function(y): 给定收益率y,返回模型价格
    """
    P_down = price_function(y0 - dy)
    P_up = price_function(y0 + dy)
    duration = (P_down - P_up) / (2 * P0 * dy)
    return duration
点击展开可浏览运行结果
📘 本段代码定义了 1 个函数/类:函数 `effective_duration`(通过数值扰动计算有效久期)。该片段为教学展示(未包含独立运行的输入数据),可在实战练习中结合真实数据调用。

凸度的数学含义

凸度(Convexity)衡量久期相对于收益率的变化率,即债券价格对收益率的二阶导数除以价格:

$$C = \frac{1}{P} \frac{\partial^2 P}{\partial y^2}$$

价格变化的二阶近似:

$$\frac{\Delta P}{P} \approx -D_{\text{mod}} \cdot \Delta y + \frac{1}{2} C \cdot (\Delta y)^2$$
PYTHON22 行 · 747 B
📄此处有展示代码22 行 · 747 B展开 ▼
python
def convexity(cashflows, times, ytm):
    """
    计算债券的凸度
    """
    pv_cf = [cf / (1 + ytm) ** t for cf, t in zip(cashflows, times)]
    weighted_pv = [t * (t + 1) * pv for t, pv in zip(times, pv_cf)]
    price = sum(pv_cf)
    conv = sum(weighted_pv) / (price * (1 + ytm)**2)
    return conv

# 凸度对价格估计的改进
conv = convexity(cashflows, times, ytm)
print(f"凸度: {conv:.2f}")

# 假设收益率上升50bp
dy = 0.0050
mod_dur = dur / (1 + ytm / freq)
pct_change_linear = -mod_dur * dy
pct_change_convexity = pct_change_linear + 0.5 * conv * dy**2
print(f"一阶近似: {pct_change_linear*100:.4f}%")
print(f"二阶近似: {pct_change_convexity*100:.4f}%")
print(f"凸度调整: {0.5 * conv * dy**2 * 100:.4f}%")
点击展开可浏览运行结果
📘 本段代码定义了 1 个函数/类:函数 `convexity`(计算债券的凸度)。该片段为教学展示(未包含独立运行的输入数据),可在实战练习中结合真实数据调用。

凸度对债券持有者总是有利的:当收益率下降时,价格涨幅大于久期预测值;当收益率上升时,价格跌幅小于久期预测值。这就是"凸度是有价值的"这一说法的来源。

免疫策略:资产与负债久期匹配

免疫(Immunization)是固定收益组合管理的核心策略,通过让资产的久期和凸度与负债匹配,使得组合净值对利率变动不敏感。

单一负债免疫

对于一笔未来确定时点的负债 L,免疫需要满足两个条件:

$$\begin{aligned} PV(\text{Assets}) &= PV(\text{Liabilities}) \\ D_{\text{Assets}} &= D_{\text{Liabilities}} \end{aligned}$$
PYTHON29 行 · 964 B
📄此处有展示代码29 行 · 964 B展开 ▼
python
def immunize_single_liability(liability, liability_time, bonds, ytm):
    """
    对单一负债进行免疫
    liability: 负债金额
    liability_time: 负债到期时间(年)
    bonds: list of dicts with 'duration', 'price', 'convexity'
    """
    # 计算负债的现值和久期
    pv_liability = liability / (1 + ytm) ** liability_time

    print(f"负债现值: {pv_liability:,.2f}")
    print(f"负债久期: {liability_time:.2f} 年")

    # 目标:找到两个债券的权重使组合久期等于负债久期
    # w1 * D1 + w2 * D2 = D_liability
    # w1 + w2 = 1
    D1, D2 = bonds[0]['duration'], bonds[1]['duration']
    w1 = (liability_time - D2) / (D1 - D2)
    w2 = 1 - w1

    # 计算需要购买的金额
    amount_bond1 = pv_liability * w1
    amount_bond2 = pv_liability * w2

    return {
        'bond1_allocation': amount_bond1,
        'bond2_allocation': amount_bond2,
        'portfolio_duration': w1 * D1 + w2 * D2
    }
点击展开可浏览运行结果
📘 本段代码定义了 1 个函数/类:函数 `immunize_single_liability`(对单一负债进行免疫)。该片段为教学展示(未包含独立运行的输入数据),可在实战练习中结合真实数据调用。

多期负债免疫与再平衡

对于多期负债(如养老金支付流),免疫策略更为复杂。组合需要匹配负债的久期缺口,并且由于久期随时间漂移,需要定期再平衡:

PYTHON5 行 · 209 B
📄此处有展示代码5 行 · 209 B展开 ▼
python
# rebalancing_schedule 伪代码结构
# 1. 计算负债最大期限 horizon
# 2. 按 rebalance_freq 步进到 horizon
# 3. 在每个再平衡点过滤剩余负债
# 4. 计算久期缺口并调整组合匹配
点击展开可浏览运行结果
(脚本执行完成,未产生可展示的模块级变量或函数定义)

关键利率久期(Key Rate Duration)

传统久期衡量的是收益率曲线平行移动的影响,但在实际市场中,不同期限的利率变动并不均匀。关键利率久期解决了这一问题。

名词解释:关键利率久期(Key Rate Duration, KRD)

组合价值对特定期限(如2年、5年、10年、30年)的即期利率变动的敏感度。KRD将收益率曲线风险分解为多个"关键点"上的暴露,提供了比单一久期数字丰富得多的风险画像。

PYTHON20 行 · 729 B
📄此处有展示代码20 行 · 729 B展开 ▼
python
def key_rate_duration(price_function, key_maturities, y0, dy=0.0001):
    """
    计算关键利率久期
    price_function(spots_dict): 输入各期限的即期利率,返回模型价格
    key_maturities: 关键期限列表 [2, 5, 10, 30]
    """
    P0 = price_function({m: y0 for m in key_maturities})
    krds = {}

    for k in key_maturities:
        # 仅扰动特定期限,其他期限保持不变或插值
        spots_up = {m: y0 + (dy if m == k else 0) for m in key_maturities}
        spots_down = {m: y0 + (-dy if m == k else 0) for m in key_maturities}

        P_up = price_function(spots_up)
        P_down = price_function(spots_down)

        krds[k] = -(P_up - P_down) / (2 * P0 * dy)

    return krds
点击展开可浏览运行结果
📘 本段代码定义了 1 个函数/类:函数 `key_rate_duration`(计算关键利率久期)。该片段为教学展示(未包含独立运行的输入数据),可在实战练习中结合真实数据调用。

关键利率久期的用途

  • 识别组合对不同期限的暴露集中度
  • 对冲收益率曲线的非平行移动
  • 做"蝶式交易"时的风险预算(例如做多5年、做空2年和10年,使总DV01和关键利率久期尽量中性)

利用关键利率久期,交易员可以精确地对冲收益率曲线上的曲线弯曲风险(bend risk)——这是传统久期/凸度框架所无法处理的。