目錄python
若是未作特別說明,文中的程序都是 Python3 代碼。算法
理論和實踐上有多種方法能夠構建與市場一致的收益率曲線,背後的方法論取決於市場上的可得到金融工具的流動性。在構建收益率曲線時有兩個選項必須選定好:擬合方法和所選的金融工具。bootstrap
quantlib-python 容許構建下列兩大類收益率曲線:app
DiscountCurve
,根據貼現因子構建*ZeroCurve
型的收益率曲線,根據債券零息收益率構建(前綴表示具體的構建方法)ForwardCurve
,根據遠期收益率構建FixedRateBond
)構建:
Piecewise**
型的收益率曲線,根據若干不一樣類型金融工具(存款收益率、收益率遠期合約和互換等等)的報價分段構建(後綴表示具體的構建方法和曲線類型)FittedBondDiscountCurve
,根據若干債券的價格構建本文介紹第二種。函數
載入 QuantLib:工具
import QuantLib as ql print(ql.__version__)
1.12
YieldTermStructure
事實上,全部上述類都派生自基類 YieldTermStructure
,該基類實現了一些經常使用的功能。例如,實現了返回基準日期、天數計算規則、日曆的函數,以及返回收益率的最小或最大日期的函數。優化
YieldTermStructure
經常使用的成員函數:lua
discount(d, extrapolate = False)
:浮點數,d
是 Date
對象, extrapolate
是布爾型。返回貼現因子大小。zeroRate(d, resultDayCounter, comp, freq = Annual, extrapolate = False)
:InterestRate
,d
是 Date
對象,resultDayCounter
是 DayCounter
對象,comp
和 freq
是預置整數,extrapolate
是布爾型。返回等價的零息收益率對象。forwardRate(d1, d2, dc, comp, freq = Annual, extrapolate = false)
:InterestRate
,d1
和 d2
是 Date
對象,resultDayCounter
是 DayCounter
對象,comp
和 freq
是 quantlib-python 預置整數(表示付息方式和頻率),extrapolate
是布爾型。返回 d1
和 d2
之間的遠期收益率對象。以貨幣網 2018-07-23 發佈的國債收盤收益率曲線爲基準,構造一組樣本券:spa
此時,這些樣本券肯定的「到期」收益率曲線即爲發佈的收盤收益率曲線,由於對於每一年付息一次的固息債,全價等於 100 時票息率剛好等於到期收益率。rest
下面,從上述樣本券中構造出知足某種限制條件的「即期」收益率曲線。理論上,從新構造出的即期收益率應當與貨幣網發佈的即期收益率很是接近,甚至相等。
期限 | 到期收益率 | 即期收益率 |
---|---|---|
1 | 3.0544 | 3.0544 |
2 | 3.1549 | 3.1565 |
3 | 3.2489 | 3.2531 |
4 | 3.2702 | 3.2744 |
5 | 3.2915 | 3.2964 |
6 | 3.3958 | 3.4092 |
7 | 3.5000 | 3.5237 |
8 | 3.5050 | 3.5264 |
9 | 3.5100 | 3.5298 |
10 | 3.5150 | 3.5337 |
15 | 3.7765 | 3.8517 |
20 | 3.8163 | 3.8884 |
30 | 3.9568 | 4.0943 |
50 | 3.9720 | 4.0720 |
Piecewise**
quantlib-python 提供的若干 Piecewise**
型的收益率曲線意爲「分段收益率曲線」,能夠根據若干固收類金融工具的報價推算出特按期限的收益率(或貼現因子),進而構建收益率曲線。
分段收益率曲線接受一組不一樣期限的固收類金融工具(如固息債、利率互換和遠期利率協議等等),根據具體金融工具的貼現方法、期限、價格等等因素拆解(bootstrap)出對應期限的即期收益率(或等價的貼現因子)。再經過某種插值手段——一般是樣條插值,構造出與實際即期收益率(或貼現因子)最接近的理論收益率曲線。
Piecewise**
對象的構造PiecewiseLogCubicDiscount
從金融工具報價中拆解出貼現因子,並用對數三次樣條插值構建理論貼現因子曲線。其構造函數具備如下實現
PiecewiseLogCubicDiscount(referenceDate, instruments, dayCounter, jumps, jumpDates, accuracy, i)
或
PiecewiseLogCubicDiscount(settlementDays, calendar, instruments, dayCounter, jumps, jumpDates, accuracy, i)
這些變量的類型和解釋以下:
referenceDate
:Date
對象,構造麴線的基準日期settlementDays
:整數,結算日天數calendar
:Calendar
對象,市場對應的日曆表instruments
:一列 *Helper
類的對象,特定金融工具的輔助類,用於拆解計算。dayCounter
:DayCounter
對象,市場對應的天數計算規則jumps
:一列 RelinkableQuoteHandle
對象,收益率跳躍的幅度,默認是空的jumpDates
:一列 Date
對象,收益率跳躍的日期,默認是空的accuracy
:浮點數,收斂精度,默認是 1e-12i
:MonotonicLogCubic
對象,插值方法,默認是 MonotonicLogCubic()
PiecewiseLogCubicDiscount
經常使用的成員函數均繼承自基類 YieldTermStructure
。
PiecewiseLogCubicDiscount
對收益率曲線的形狀沒有「結構性」的限制,能夠很好的擬合實際獲得的收益率數據,代價是缺乏理論性的解釋能力。
FittedBondDiscountCurve
和 PiecewiseLogCubicDiscount
相反,FittedBondDiscountCurve
對收益率曲線的形狀提出了「結構性」的限制,最終擬合曲線的理論解釋性更強,曲線也更光滑,但代價是擬合程度會下降。
FittedBondDiscountCurve
的原理FittedBondDiscountCurve
接受一組不一樣期限的固息債對象,同時假設理論即期收益率(或貼現因子)知足某種特定的函數形式——一般由幾個參數控制。用理論曲線對算出債券的理論價格,尋找最佳參數,使得理論價格和實際價格的距離最小。最佳參數肯定的曲線即是擬合出的理論曲線。
FittedBondDiscountCurve
的構造FittedBondDiscountCurve
從一列固息債對象中拆解出貼現因子,並用要求理論貼現因子曲線知足某種參數形式。其構造函數具備如下實現
FittedBondDiscountCurve(referenceDate, helpers, dayCounter, fittingMethod, accuracy, maxEvaluations, guess, simplexLambda)
或
FittedBondDiscountCurve(settlementDays, calendar, helpers, dayCounter, fittingMethod, accuracy, maxEvaluations, guess, simplexLambda)
這些變量的類型和解釋以下:
referenceDate
:Date
對象,構造麴線的基準日期settlementDays
:整數,結算日天數calendar
:Calendar
對象,市場對應的日曆表helps
:一列 *Helper
類的對象,固息債的輔助類,用於拆解計算。dayCounter
:DayCounter
對象,市場對應的天數計算規則fittingMethod
:FittingMethod
對象,規定理論曲線的函數形式。accuracy
:浮點數,收斂精度,默認是 1e-10maxEvaluations
:整數,數值優化計算中的最大迭代次數guess
:一列浮點數,數值優化計算的初始參數,默認是空的simplexLambda
:浮點數,單純型算法中的尺度,默認是 1.0FittedBondDiscountCurve
經常使用的成員函數均繼承自基類 YieldTermStructure
。
FittingMethod
類FittingMethod
是一個基類,quantlib-python 具體提供的 FittingMethod
子類有如下幾個:
ExponentialSplinesFitting
:指數樣條模型,貼現因子的形式爲 \(d(t) = \sum_{i=1}^9 c_i \exp^{-\kappa \cdot i \cdot t}\),其中 \(c_i\) 和 \(\kappa\) 是須要肯定的參數。CubicBSplinesFitting
:三次 B-樣條模型,貼現因子的形式爲一組三次 B-樣條 \(N_{i,3}(t)\) 的組合,\(d(t) = \sum_{i=0}^{n} c_i \cdot N_{i,3}(t)\),其中 \(c_i\) 是須要肯定的參數。SimplePolynomialFitting
:簡單多項式模型,貼現因子的形式爲多項式NelsonSiegelFitting
:Nelson-Siegel 模型,即期收益率的形式爲 \(r(t) = c_0 + (c_1 + c_2) \cdot (1 - exp^{-\kappa \cdot t})/(\kappa \cdot t) - c_2 exp^{- \kappa \cdot t}\),其中 \(c_i\) 和 \(\kappa\) 是須要肯定的參數。SvenssonFitting
:Svensson-Nelson-Siegel 模型,即期收益率的形式爲 \(r(t) = c_0 + (c_0 + c_1)(\frac {1 - exp^{-\kappa \cdot t}}{\kappa \cdot t}) - c_2exp^{ - \kappa \cdot t} + c_3{(\frac{1 - exp^{-\kappa_1 \cdot t}}{\kappa_1 \cdot t} -exp^{-\kappa_1 \cdot t})}\),其中 \(c_i\)、\(\kappa\) 和 \(\kappa_1\) 是須要肯定的參數。下面分別用 PiecewiseLogCubicDiscount
和 FittedBondDiscountCurve
擬合「問題描述」中構造出的樣本券對應的即期收益率曲線,FittedBondDiscountCurve
方法使用 Svensson-Nelson-Siegel 模型。
理論上,PiecewiseLogCubicDiscount
擬合出的曲線應該很是接近貨幣網發佈的即期收益率曲線,極可能是鋸齒狀的,不光滑的(因爲市場的深度和廣度有限)。FittedBondDiscountCurve
擬合出的曲線應該很是光滑,而且足夠接近貨幣網發佈的曲線。
例子,擬合曲線並輸出 Svensson-Nelson-Siegel 模型的參數。
import QuantLib as ql import pandas as pd import seaborn as sb def testingYields3(): maturities = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 30, 50] pars = [0.030544, 0.031549, 0.032489, 0.032702, 0.032915, 0.033958, 0.03500, 0.035050, 0.035100, 0.035150, 0.037765, 0.038163, 0.039568, 0.03972] spots = [0.030544, 0.031565, 0.032531, 0.032744, 0.032964, 0.034092, 0.035237, 0.035264, 0.035298, 0.035337, 0.038517, 0.038884, 0.040943, 0.040720] numberOfBonds = len(maturities) cleanPrice = [100.0] * numberOfBonds quote = [ql.SimpleQuote(c) for c in cleanPrice] quoteHandle = [ql.RelinkableQuoteHandle()] * numberOfBonds for i in range(len(quoteHandle)): quoteHandle[i].linkTo(quote[i]) frequency = ql.Annual dc = ql.ActualActual(ql.ActualActual.ISMA) accrualConvention = ql.ModifiedFollowing convention = ql.ModifiedFollowing redemption = 100.0 calendar = ql.China(ql.China.IB) today = calendar.adjust(ql.Date(23, 7, 2018)) ql.Settings.evaluationDate = today bondSettlementDays = 0 bondSettlementDate = calendar.advance( today, ql.Period(bondSettlementDays, ql.Days)) instruments = [] for j in range(len(maturities)): maturity = calendar.advance( bondSettlementDate, ql.Period(maturities[j], ql.Years)) schedule = ql.Schedule( bondSettlementDate, maturity, ql.Period(frequency), calendar, accrualConvention, accrualConvention, ql.DateGeneration.Backward, False) helper = ql.FixedRateBondHelper( quoteHandle[j], bondSettlementDays, 100.0, schedule, [pars[j]], dc, convention, redemption) instruments.append(helper) tolerance = 1.0e-10 max = 5000 svensson = ql.SvenssonFitting() ts0 = ql.PiecewiseLogCubicDiscount( bondSettlementDate, instruments, dc) ts1 = ql.FittedBondDiscountCurve( bondSettlementDate, instruments, dc, svensson, tolerance, max) spline = [] sv = [] print('{0:>9}{1:>9}{2:>9}{3:>9}'.format( "tenor", "spot", "spline", "svensson")) for i in range(len(instruments)): cfs = instruments[i].bond().cashflows() cfSize = len(instruments[i].bond().cashflows()) tenor = dc.yearFraction(today, cfs[cfSize - 1].date()) print( '{0:9.3f}{1:9.3f}{2:9.3f}{3:9.3f}'.format( tenor, 100.0 * spots[i], 100.0 * ts0.zeroRate(cfs[cfSize - 1].date(), dc, ql.Compounded, frequency).rate(), 100.0 * ts1.zeroRate(cfs[cfSize - 1].date(), dc, ql.Compounded, frequency).rate())) spline.append(ts0.zeroRate(cfs[cfSize - 1].date(), dc, ql.Compounded, frequency).rate()) sv.append(ts1.zeroRate(cfs[cfSize - 1].date(), dc, ql.Compounded, frequency).rate()) df = pd.DataFrame( dict( mat=maturities * 4, rate=pars + spots + spline + sv, type=['par'] * 14 + ['spot'] * 14 + ['spline'] * 14 + ['sv'] * 14)) print(ts1.fitResults().solution()) return df rs = testingYields3() sb.relplot( x='mat', y='rate', kind='line', hue='type', data=rs, height=5, aspect=1.6)
結果以下:
tenor spot spline svensson 1.000 3.054 2.993 3.011 2.000 3.157 3.121 3.104 3.000 3.253 3.226 3.187 4.000 3.274 3.258 3.262 5.000 3.296 3.281 3.330 6.000 3.409 3.393 3.392 7.000 3.524 3.507 3.448 8.000 3.526 3.512 3.499 9.000 3.530 3.517 3.547 10.000 3.534 3.523 3.591 15.000 3.852 3.843 3.771 20.000 3.888 3.877 3.906 30.000 4.094 4.085 4.084 50.000 4.072 4.044 4.025 [ -0.190874; 0.219538; 0.0953552; 0.586634; 0.0896221; 0.0226007 ]
將結果可視化。藍色線表示到期曲線,橙色線表示即期曲線,綠色線是 PiecewiseLogCubicDiscount
擬合的結果,紅色線是 FittedBondDiscountCurve
擬合的 Svensson-Nelson-Siegel 模型,與預期徹底一致。