從本篇開始計劃開啓一個系列,以《Interest Rate Risk Modeling》爲藍本,介紹有關利率風險的計算案例,內容涉及從簡單的久期、凸性到主成分久期和久期向量模型等高階的度量指標。python
固息債的久期、凸性和 BPS 是最多見的利率風險度量指標,下面將以 200205 爲例,計算 2020-07-28 這一天的價格,以及久期、凸性和 BPS。函數
首先從中國貨幣網查詢債券的基本信息,用以配置 FixedRateBond
對象。lua
import QuantLib as ql import prettytable as pt today = ql.Date(28, ql.July, 2020) ql.Settings.instance().evaluationDate = today settlementDays = 1 faceAmount = 100.0
settlementDays = 1
表示 T+1 結算,而估值日期就是 2020-07-28 這一天。rest
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) # for s in schedule: # print(s) 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)
須要注意的是,日曆採用中國的銀行間市場,遇到假期不調整。code
若是像下面同樣,採用基於期限結構的訂價引擎,在構造 ActualActual
對象時要附加上債券現金流支付的日期表(Schedule
對象),不然在計算貼現因子的時候可能產生誤差,具體的討論請查看 StackExchange 上的討論:https://quant.stackexchange.com/questions/12707/pricing-a-fixedratebond-in-quantlib-yield-vs-termstructureorm
在上海清算所查詢估值、價格和久期等數據,做爲比較基準。對象
因爲使用的是估值,也就是「到期利率」,這隱含要求於一個「水平」(flat)的期限結構,因此使用 FlatForward
類。對於水平的期限結構而言,遠期利率、即期利率和到期利率三者相等。blog
DiscountingBondEngine
是最多見的債券訂價引擎,主要用於現金流的貼現計算。ci
bondYield = 3.4124 / 100.0 compounding = ql.Compounded frequency = ql.Annual termStructure = ql.YieldTermStructureHandle( ql.FlatForward( settlementDays, calendar, bondYield, accrualDayCounter, compounding, frequency)) engine = ql.DiscountingBondEngine(termStructure) bond.setPricingEngine(engine)
價格信息能夠經過 FixedRateBond
的成員函數得到,而久期等指標的計算在 BondFunctions
的內部函數中實現(BondFunctions
的內部函數也能夠依據到期利率計算價格信息)。get
cleanPrice = bond.cleanPrice() dirtyPrice = bond.dirtyPrice() accruedAmount = bond.accruedAmount() duration = ql.BondFunctions.duration( bond, bondYield, accrualDayCounter, compounding, frequency) convexity = ql.BondFunctions.convexity( bond, bondYield, accrualDayCounter, compounding, frequency) bps = ql.BondFunctions.basisPointValue( bond, bondYield, accrualDayCounter, compounding, frequency) tab = pt.PrettyTable(['item', 'QuantLib', 'ShClearing']) tab.add_row(['clean price', cleanPrice, 97.2211]) tab.add_row(['dirty price', dirtyPrice, 98.4071]) tab.add_row(['accrued amount', accruedAmount, 1.1859]) tab.add_row(['duration', duration, 8.0771]) tab.add_row(['convexity', convexity, 79.2206]) tab.add_row(['bps', abs(bps), 0.0795]) tab.float_format = '.4' print(tab)
+----------------+----------+------------+ | item | QuantLib | ShClearing | +----------------+----------+------------+ | clean price | 97.2212 | 97.2211 | | dirty price | 98.4071 | 98.4071 | | accrued amount | 1.1859 | 1.1859 | | duration | 8.0771 | 8.0771 | | convexity | 79.2206 | 79.2206 | | bps | 0.0795 | 0.0795 | +----------------+----------+------------+
最終結果和上海清算所公佈的幾乎一致。
BondFunctions
的 duration
函數能夠計算三種久期,分別是簡單久期(Simple)、麥考利久期(Macaulay)和修正久期(Modified),只需配置久期類型參數便可,默認計算的是修正久期。
程序實現上,麥考利久期的計算依賴於修正久期。
所謂簡單久期,即現金流的期限關於現金流貼現值的加權平均。若是計息方式是複利,簡單久期等於麥考利久期。不過,若是是連續複利,計算麥考利久期將會報錯,簡單久期依然能夠計算出來,更有普適性。連續複利的狀況下,簡單久期等於修正久期。
durationSimple = ql.BondFunctions.duration( bond, bondYield, accrualDayCounter, compounding, frequency, ql.Duration.Simple) durationModified = ql.BondFunctions.duration( bond, bondYield, accrualDayCounter, compounding, frequency, ql.Duration.Modified) durationMacaulay = ql.BondFunctions.duration( bond, bondYield, accrualDayCounter, compounding, frequency, ql.Duration.Macaulay) tabDuration = pt.PrettyTable(['type', 'value']) tabDuration.add_row(['Simple', durationSimple]) tabDuration.add_row(['Modified', durationModified]) tabDuration.add_row(['Macaulay', durationMacaulay]) print(tabDuration)
+----------+-------------------+ | type | value | +----------+-------------------+ | Simple | 8.352745733674992 | | Modified | 8.077122021802985 | | Macaulay | 8.352745733674992 | +----------+-------------------+