日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

QuantLib 金融计算——案例之固息债的关键利率久期(KRD)

發布時間:2023/12/13 综合教程 51 生活家
生活随笔 收集整理的這篇文章主要介紹了 QuantLib 金融计算——案例之固息债的关键利率久期(KRD) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄QuantLib 金融計算——案例之固息債的關鍵利率久期(KRD)概述關鍵利率久期的基本概念從擾動的角度計算 KRD計算案例Quote 類和引用帶來的便利參考文獻擴展閱讀

QuantLib 金融計算——案例之固息債的關鍵利率久期(KRD)

概述

作為利率風險系列的第二篇,本文將以《Interest Rate Risk Modeling》為藍本,介紹關鍵利率久期(KRD)的基本概念,并依托 QuantLib 展示相關的計算案例。

有關 KRD 的高級內容請見《《Interest Rate Risk Modeling》閱讀筆記——第九章》。

關鍵利率久期的基本概念

上一篇《案例之固息債的價格、久期、凸性和 BPS》中出現的久期和凸性均是基于到期利率(YTM)的風險度量指標。使用 YTM 分析債券隱含了一個重要假設:利率期限結構上各期限的利率同步變化。這個隱含的假設與現實有所出入,盡管期限結構上各期限的利率變化高度相關,但并非 100% 一致。顯然,傳統的久期無法描述債券價格對期限結構非平行變化的敏感性。

若要更精細地刻畫債券關于利率變化的敏感性,需要分別考慮不同期限上利率變化對債券價格的影響,這要求把期限結構本身作為一個動態變量。

一個期限結構其實可以看做是一個無限維的向量,任意一個期限均是一個維度。考慮一個無限維的向量是一個高深的數學問題,然而基于經驗觀察,期限結構的平滑性相當好,所以只需要選取幾個特殊期限作為“錨點”,實踐中就可以幾乎完全把握整個曲線的變化。

關鍵利率久期(KRD)就是債券價格關于這些錨點期限上利率的敏感性,一組 KRD 也就描述了債券價格對期限結構非平行變化的敏感性。

從擾動的角度計算 KRD

假設根據當前期限結構算出來的債券價格是 (P),此時某個關鍵期限 (K) 上的利率出現了一個微小的擾動 (Delta y),擾動出現后重新計算出的債券價格是 (P^{prime}),那么債券價格關于 (K) 期限利率的敏感性就近似是

[frac{P^{prime} - P}{P imes Delta y}
]

也可以采用精度更高的近似方法,正負擾動對應的價格分別是 (P^{+}) 和 (P^{-}),敏感性近似是

[frac{P^{+} - P^{-}}{2 P imes Delta y}
]

為保證期限結構的平滑性,擾動不能只影響一個特定期限,其影響要平滑地擴散到臨近的期限。在 KRD 分析中,要求擾動以線性遞減的形式擴展到左右相鄰的期限,而不會影響相距更遠的期限。例如,選定 5、7、10 年三個相鄰期限,7 年期上 1 bp 的擾動只能影響到 5 和 10 年期。并且,7-5 年之間,擾動以每年 0.5 bp 的速度遞減,7-10 年之間,擾動以每年 1/3 bp 的速度遞減。

計算案例

繼續以上一篇《案例之固息債的價格、久期、凸性和 BPS》中出現的 200205 為例,計算 2020-07-28 這一天的久期和 KRD。

首先從中國貨幣網查詢債券的基本信息,用以配置 FixedRateBond 對象。

債券起息日:2020-03-10
到期兌付日:2030-03-10
債券期限:10 年
面值(元):100.00
計息基準:A/A
息票類型:附息式固定利率
付息頻率:年
票面利率(%):3.0700
結算方式:T+1

import QuantLib as ql
import prettytable as pt
import seaborn as sns

today = ql.Date(28, ql.July, 2020)
ql.Settings.instance().evaluationDate = today

settlementDays = 1
faceAmount = 100.0

effectiveDate = ql.Date(10, ql.March, 2020)
terminationDate = ql.Date(10, ql.March, 2030)
tenor = ql.Period(1, ql.Years)
calendar = ql.China(ql.China.IB)
convention = ql.Unadjusted
terminationDateConvention = convention
rule = ql.DateGeneration.Backward
endOfMonth = False

schedule = ql.Schedule(
    effectiveDate,
    terminationDate,
    tenor,
    calendar,
    convention,
    terminationDateConvention,
    rule,
    endOfMonth)

coupons = ql.DoubleVector(1)
coupons[0] = 3.07 / 100.0
accrualDayCounter = ql.ActualActual(
    ql.ActualActual.Bond, schedule)
paymentConvention = ql.Unadjusted

bond = ql.FixedRateBond(
    settlementDays,
    faceAmount,
    schedule,
    coupons,
    accrualDayCounter,
    paymentConvention)

在上海清算所查詢估值。由于使用的是估值,也就是到期利率,所以當前的期限結構用 FlatForward 類表示。對于水平的期限結構而言,遠期利率、即期利率和到期利率三者相等。

bondYield = 3.4124 / 100.0

compounding = ql.Compounded
frequency = ql.Annual

flatCurve = ql.YieldTermStructureHandle(
    ql.FlatForward(
        settlementDays,
        calendar,
        bondYield,
        accrualDayCounter,
        compounding,
        frequency))

計算 KRD 的時候需要向當前的期限結構添加關鍵期限上的擾動,為此可以借助 QuantLib 中的 InterpolatedPiecewiseZeroSpreadedTermStructure 類模板,它需要一個模板參數 Interpolator,表示所使用的插值方法類。對于 KRD 的計算來說,選擇 Linear 作為模板參數,以表示線性插值。

要配置實例化后的類 InterpolatedPiecewiseZeroSpreadedTermStructure<Linear>,需要提供三個核心參數:

一個 Handle<YieldTermStructure> 對象,也就是當前的期限結構,關鍵期限上的擾動將被施加在此期限結構上;
一列 Handle<Quote> 對象,表示關鍵期限上的利率擾動;
一列 Date 對象,表示擾動對應的關鍵期限。

具體到 python 環境下,實例化后的類 InterpolatedPiecewiseZeroSpreadedTermStructure<Linear> 被包裝并重命名為 SpreadedLinearZeroInterpolatedTermStructure 類。

在計算 KRD 之前,所有擾動的初始值被設置成零。關鍵期限有 11 個,分別是 6 個月和 1~10 年,均勻地覆蓋每個付息周期。

initValue = 0.0
rate6m = ql.SimpleQuote(initValue)
rate1y = ql.SimpleQuote(initValue)
rate2y = ql.SimpleQuote(initValue)
rate3y = ql.SimpleQuote(initValue)
rate4y = ql.SimpleQuote(initValue)
rate5y = ql.SimpleQuote(initValue)
rate6y = ql.SimpleQuote(initValue)
rate7y = ql.SimpleQuote(initValue)
rate8y = ql.SimpleQuote(initValue)
rate9y = ql.SimpleQuote(initValue)
rate10y = ql.SimpleQuote(initValue)

rate6mHandle = ql.QuoteHandle(rate6m)
rate1yHandle = ql.QuoteHandle(rate1y)
rate2yHandle = ql.QuoteHandle(rate2y)
rate3yHandle = ql.QuoteHandle(rate3y)
rate4yHandle = ql.QuoteHandle(rate4y)
rate5yHandle = ql.QuoteHandle(rate5y)
rate6yHandle = ql.QuoteHandle(rate6y)
rate7yHandle = ql.QuoteHandle(rate7y)
rate8yHandle = ql.QuoteHandle(rate8y)
rate9yHandle = ql.QuoteHandle(rate9y)
rate10yHandle = ql.QuoteHandle(rate10y)

spreads = ql.QuoteHandleVector()
spreads.append(rate6mHandle)
spreads.append(rate1yHandle)
spreads.append(rate2yHandle)
spreads.append(rate3yHandle)
spreads.append(rate4yHandle)
spreads.append(rate5yHandle)
spreads.append(rate6yHandle)
spreads.append(rate7yHandle)
spreads.append(rate8yHandle)
spreads.append(rate9yHandle)
spreads.append(rate10yHandle)

dates = ql.DateVector()
dates.append(flatCurve.referenceDate() + ql.Period(6, ql.Months))
dates.append(flatCurve.referenceDate() + ql.Period(1, ql.Years))
dates.append(flatCurve.referenceDate() + ql.Period(2, ql.Years))
dates.append(flatCurve.referenceDate() + ql.Period(3, ql.Years))
dates.append(flatCurve.referenceDate() + ql.Period(4, ql.Years))
dates.append(flatCurve.referenceDate() + ql.Period(5, ql.Years))
dates.append(flatCurve.referenceDate() + ql.Period(6, ql.Years))
dates.append(flatCurve.referenceDate() + ql.Period(7, ql.Years))
dates.append(flatCurve.referenceDate() + ql.Period(8, ql.Years))
dates.append(flatCurve.referenceDate() + ql.Period(9, ql.Years))
dates.append(flatCurve.referenceDate() + ql.Period(10, ql.Years))

termStructure = ql.YieldTermStructureHandle(
    ql.SpreadedLinearZeroInterpolatedTermStructure(
        flatCurve,
        spreads,
        dates,
        compounding,
        frequency,
        accrualDayCounter))

債券定價引擎采用最常見的 DiscountingBondEngine

engine = ql.DiscountingBondEngine(termStructure)
bond.setPricingEngine(engine)

Quote 類和引用帶來的便利

在底層 C++ 代碼中,QuantLib 類的構造函數和成員函數大量使用了常引用參數和觀察者模式,這使得作為參數的對象具有了“穿透性”,參數對象值的改變可以靠引用和觀察者模式串聯起來的鏈條影響關聯的所有其他對象。

具體到 KRD 的計算,無需重新配置定價引擎,只要改變關鍵利率的值就可以自動觸發債券的計算。

擾動的大小定為 1 bp,調用成員方法 setValue 便可改變 SimpleQuote 對象的值。

duration = ql.BondFunctions.duration(
    bond,
    bondYield,
    accrualDayCounter,
    compounding,
    frequency,
    ql.Duration.Modified)


tab = pt.PrettyTable(['item', 'value'])
tab.add_row(['duration', duration])

# calculate KRDs

bp = 0.01 / 100.0
krdSum = 0.0
krds = []
times = []

# 6m KRD
rate6m.setValue(bp)
dirtyPrice1 = bond.dirtyPrice()
rate6m.setValue(-bp)
dirtyPrice2 = bond.dirtyPrice()
rate6m.setValue(initValue)
krd6m = -(dirtyPrice1 - dirtyPrice2) / (2.0 * bp * dirtyPrice)
krdSum += krd6m
krds.append(krd6m)
times.append(0.5)

tab.add_row(['krd6m', krd6m])

# 1y KRD
rate1y.setValue(bp)
dirtyPrice1 = bond.dirtyPrice()
rate1y.setValue(-bp)
dirtyPrice2 = bond.dirtyPrice()
rate1y.setValue(initValue)
krd1y = -(dirtyPrice1 - dirtyPrice2) / (2.0 * bp * dirtyPrice)
krdSum += krd1y
krds.append(krd1y)
times.append(1.0)

tab.add_row(['krd1y', krd1y])

# 2y KRD
rate2y.setValue(bp)
dirtyPrice1 = bond.dirtyPrice()
rate2y.setValue(-bp)
dirtyPrice2 = bond.dirtyPrice()
rate2y.setValue(initValue)
krd2y = -(dirtyPrice1 - dirtyPrice2) / (2.0 * bp * dirtyPrice)
krdSum += krd2y
krds.append(krd2y)
times.append(2.0)

tab.add_row(['krd2y', krd2y])

# 3y KRD
rate3y.setValue(bp)
dirtyPrice1 = bond.dirtyPrice()
rate3y.setValue(-bp)
dirtyPrice2 = bond.dirtyPrice()
rate3y.setValue(initValue)
krd3y = -(dirtyPrice1 - dirtyPrice2) / (2.0 * bp * dirtyPrice)
krdSum += krd3y
krds.append(krd3y)
times.append(3.0)

tab.add_row(['krd3y', krd3y])

# 4y KRD
rate4y.setValue(bp)
dirtyPrice1 = bond.dirtyPrice()
rate4y.setValue(-bp)
dirtyPrice2 = bond.dirtyPrice()
rate4y.setValue(initValue)
krd4y = -(dirtyPrice1 - dirtyPrice2) / (2.0 * bp * dirtyPrice)
krdSum += krd4y
krds.append(krd4y)
times.append(4.0)

tab.add_row(['krd4y', krd4y])

# 5y KRD
rate5y.setValue(bp)
dirtyPrice1 = bond.dirtyPrice()
rate5y.setValue(-bp)
dirtyPrice2 = bond.dirtyPrice()
rate5y.setValue(initValue)
krd5y = -(dirtyPrice1 - dirtyPrice2) / (2.0 * bp * dirtyPrice)
krdSum += krd5y
krds.append(krd5y)
times.append(5.0)

tab.add_row(['krd5y', krd5y])

# 6y KRD
rate6y.setValue(bp)
dirtyPrice1 = bond.dirtyPrice()
rate6y.setValue(-bp)
dirtyPrice2 = bond.dirtyPrice()
rate6y.setValue(initValue)
krd6y = -(dirtyPrice1 - dirtyPrice2) / (2.0 * bp * dirtyPrice)
krdSum += krd6y
krds.append(krd6y)
times.append(6.0)

tab.add_row(['krd6y', krd6y])

# 7y KRD
rate7y.setValue(bp)
dirtyPrice1 = bond.dirtyPrice()
rate7y.setValue(-bp)
dirtyPrice2 = bond.dirtyPrice()
rate7y.setValue(initValue)
krd7y = -(dirtyPrice1 - dirtyPrice2) / (2.0 * bp * dirtyPrice)
krdSum += krd7y
krds.append(krd7y)
times.append(7.0)

tab.add_row(['krd7y', krd7y])

# 8y KRD
rate8y.setValue(bp)
dirtyPrice1 = bond.dirtyPrice()
rate8y.setValue(-bp)
dirtyPrice2 = bond.dirtyPrice()
rate8y.setValue(initValue)
krd8y = -(dirtyPrice1 - dirtyPrice2) / (2.0 * bp * dirtyPrice)
krdSum += krd8y
krds.append(krd8y)
times.append(8.0)

tab.add_row(['krd8y', krd8y])

# 9y KRD
rate9y.setValue(bp)
dirtyPrice1 = bond.dirtyPrice()
rate9y.setValue(-bp)
dirtyPrice2 = bond.dirtyPrice()
rate9y.setValue(initValue)
krd9y = -(dirtyPrice1 - dirtyPrice2) / (2.0 * bp * dirtyPrice)
krdSum += krd9y
krds.append(krd9y)
times.append(9.0)

tab.add_row(['krd9y', krd9y])

# 10y KRD
rate10y.setValue(bp)
dirtyPrice1 = bond.dirtyPrice()
rate10y.setValue(-bp)
dirtyPrice2 = bond.dirtyPrice()
rate10y.setValue(initValue)
krd10y = -(dirtyPrice1 - dirtyPrice2) / (2.0 * bp * dirtyPrice)
krdSum += krd10y
krds.append(krd10y)
times.append(10.0)

tab.add_row(['krd10y', krd10y])

tab.add_row(['krdSum', krdSum])

tab.float_format = '.8'

print(tab)
+----------+------------+
|   item   |   value    |
+----------+------------+
| duration | 8.07712202 |
|  krd6m   | 0.01412836 |
|  krd1y   | 0.02182248 |
|  krd2y   | 0.05615594 |
|  krd3y   | 0.08163788 |
|  krd4y   | 0.10535800 |
|  krd5y   | 0.12735475 |
|  krd6y   | 0.14771823 |
|  krd7y   | 0.16683071 |
|  krd8y   | 0.18443629 |
|  krd9y   | 0.11944279 |
|  krd10y  | 7.05223796 |
|  krdSum  | 8.07712340 |
+----------+------------+

從結果上看 KRD 有兩個局部高點,一個是接近久期的關鍵期限(8 年),另一個是接近剩余期限(也就是現金流最大的時期)的關鍵期限(10 年)。

理論上,各個 KRD 之和約等于修正久期,這是因為各個關鍵期限上同時發生擾動的話就相當于曲線發生了平行移動。數值結果正好驗證了這一點。

KRD 的曲線圖是這樣的:

sns.pointplot(
    x=times, y=krds, markers='o')

參考文獻

《Interest Rate Risk Modeling》
楊筱燕,《關鍵利率久期計算及實例分析》

擴展閱讀

《QuantLib 金融計算》系列合集

總結

以上是生活随笔為你收集整理的QuantLib 金融计算——案例之固息债的关键利率久期(KRD)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。