QuantLib Python 掉期收益率曲線自舉日期和到期日
這與我在這裡提出的問題有些相關,但更簡單。我正在嘗試從掉期引導收益率曲線,並且對即將出現的日期/到期日有問題。我正在使用的程式碼如下,我遇到的問題是當返回結果時,Maturities 欄位與我輸入的期限不匹配。
import QuantLib as ql from pandas import DataFrame import matplotlib.pyplot as plt import csv def get_spot_rates(yieldcurve, day_count, calendar=ql.UnitedStates(), months=121): spots = [] tenors = [] ref_date = yieldcurve.referenceDate() calc_date = ref_date for yrs in yieldcurve.times(): d = calendar.advance(ref_date, ql.Period(int(yrs*365.25), ql.Days)) compounding = ql.Compounded freq = ql.Semiannual zero_rate = yieldcurve.zeroRate(yrs, compounding, freq) tenors.append(yrs) eq_rate = zero_rate.equivalentRate(day_count,compounding,freq,calc_date,d).rate() spots.append(eq_rate*100) return DataFrame(list(zip(tenors, spots)),columns=["Maturities","Curve"],index=['']*len(tenors)) swap_maturities = [ql.Date(9,9,2016), ql.Date(15,9,2016), ql.Date(22,9,2016), ql.Date(29,9,2016), ql.Date(11,10,2016), ql.Date(9,11,2016), ql.Date(8,12,2016), ql.Date(10,1,2017), ql.Date(8,2,2017), ql.Date(8,3,2017), ql.Date(8,6,2017), ql.Date(8,9,2017), ql.Date(8,3,2018), ql.Date(10,9,2018), ql.Date(10,9,2019), ql.Date(10,9,2020), ql.Date(9,9,2021), ql.Date(8,9,2022), ql.Date(8,9,2023), ql.Date(10,9,2024), ql.Date(10,9,2025), ql.Date(10,9,2026), ql.Date(8,9,2028), ql.Date(10,9,2031), ql.Date(10,9,2036), ql.Date(10,9,2041), ql.Date(10,9,2046), ql.Date(8,9,2056) ] swap_periods = [ql.Period(1,ql.Days), ql.Period(1,ql.Weeks), ql.Period(2,ql.Weeks), ql.Period(3,ql.Weeks), ql.Period(1,ql.Months), ql.Period(2,ql.Months), ql.Period(3,ql.Months), ql.Period(4,ql.Months), ql.Period(5,ql.Months), ql.Period(6,ql.Months), ql.Period(9,ql.Months), ql.Period(1,ql.Years), ql.Period(18,ql.Months), ql.Period(2,ql.Years), ql.Period(3,ql.Years), ql.Period(4,ql.Years), ql.Period(5,ql.Years), ql.Period(6,ql.Years), ql.Period(7,ql.Years), ql.Period(8,ql.Years), ql.Period(9,ql.Years), ql.Period(10,ql.Years), ql.Period(12,ql.Years), ql.Period(15,ql.Years), ql.Period(20,ql.Years), ql.Period(25,ql.Years), ql.Period(30,ql.Years), ql.Period(40,ql.Years) ] swap_rates = [0.37, 0.4025, 0.4026, 0.399, 0.3978, 0.4061, 0.41, 0.4155, 0.4273, 0.4392, 0.461, 0.4805, 0.5118, 0.538, 0.587, 0.638, 0.7, 0.756, 0.818, 0.865, 0.913, 0.962, 1.045, 1.137, 1.2355, 1.281, 1.305, 1.346 ] """ Parameter Setup """ calc_date = ql.Date(1,9,2016) ql.Settings.instance().evaluationDate = calc_date calendar = ql.UnitedStates() bussiness_convention = ql.ModifiedFollowing day_count = ql.Actual360() coupon_frequency = ql.Annual """ SwapRateHelper """ swap_helpers = [] for rate,tenor in list(zip(swap_rates,swap_periods)): swap_helpers.append(ql.SwapRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/100.0)), tenor, calendar, coupon_frequency, bussiness_convention, day_count, ql.Euribor3M())) rate_helpers = swap_helpers yc_linearzero = ql.PiecewiseLinearZero(calc_date,rate_helpers,day_count) yc_cubiczero = ql.PiecewiseCubicZero(calc_date,rate_helpers,day_count) max_maturity = 40*12 splz = get_spot_rates(yc_linearzero, day_count, months=max_maturity + 1) spcz = get_spot_rates(yc_cubiczero, day_count, months=max_maturity + 1) max_rate = swap_rates[-1] min_rate = min(splz.Curve) max_rate = max(splz.Curve) """Plotting""" plt.plot(splz["Maturities"],splz["Curve"],'--', label="LinearZero") plt.plot(spcz["Maturities"],spcz["Curve"],label="CubicZero") plt.xlabel("Years", size=12) plt.ylabel("Zero Rate", size=12) plt.xlim(0,max_maturity/12.0) plt.ylim([min_rate * 0.9,max_rate * 1.1]) plt.legend() plt.show() rows = zip(splz.Maturities,splz.Curve) with open('OISBootstrap.csv','w',newline='') as f: writer = csv.writer(f) for row in rows: writer.writerow(row)
任何使用 Python 和 QL 的人都可以執行整個程序並查看結果,但例如,我得到最後五個到期日的以下值:15.2361111111、20.3111111111、25.3777777778、30.45、40.5972222222 而不是 15、20、25、30,和 40。
提前感謝我認為是一個非常新的問題。
根據您告訴曲線使用的日期計數器,15 年確實對應於 t=15.236。
首先,無論如何你都不能準確地得到 15。您的計算日期為 2016 年 9 月 1 日;根據通常的慣例,您所報價的掉期利率從即期開始,即計算日期後的兩個工作日。考慮到週末(您的計算日期是星期四)和勞動節(9 月 4 日)的假期,您將在 9 月 6 日登陸。因此,15 年期互換將於 2031 年 9 月 6 日到期;但那是星期六,所以它滾動到 2031 年 9 月 8 日(另外,您的輸入到期日是 9 月 10 日,所以您可能也想檢查一下)。那是您的計算日期之後的 15 年零一周,對於您的曲線也是 t=0(因為您將它作為參考日期傳遞給它的建構子)。
第二:您將實際/360 的天數約定傳遞給曲線,其中一年不對應於 1,而是對應於 365/360=1.01389(或閏年的 366/360)。
綜上所述,計算日期和 15 年互換到期之間的 5485 天對應於 5485/360=5.23611。類似的計算適用於其他期限。
使用 Actual/365 (Fixed) 可以使結果更接近您的預期,因為它對應於“正常”年份的 t=1;但由於閏年對應 366/365,你仍然得到 t=5485/365=15.0274。
其他日計數器具有更好的計算利率的屬性(例如,Act/Act 為您提供 1 年的 t=1),但我不建議在期限結構中使用它們,因為它們缺乏其他屬性;例如,存在成對的日期 $ d_1 $ 和 $ d_2 $ 時間 $ T(d_1,d_2) $ 它們之間是 0,或三倍 $ d_1 $ , $ d_2 $ , $ d_3 $ 為此 $ T(d_1,d_3) \neq T(d_1,d_2) + T(d_2,d_3) $ .
相反,我建議您直接使用日期。在您的
get_spot_rates
函式中,而不是嘗試將到期日期重新計算為d = calendar.advance(ref_date, ql.Period(int(yrs*365.25), ql.Days))
call
yieldcurve.nodes()
,它為您提供與每個到期日對應的對 (date,rate) 列表。您可以在對 的呼叫中使用這些日期equivalentRate
,就像您已經做的那樣,也可以在對 的呼叫中使用這些日期yieldcurve.zeroRate
。(順便說一句,
calendar.advance(ref_date, 365, Days)
不會像你想的那樣做。它將日期提前 365個工作日,比一年多得多。)