Yield-Curve
QL-Python 引導收益率曲線 FuturesRateHelper 拋出結果
我正在嘗試根據存款利率、期貨和掉期來執行收益率曲線的引導,並且由於期貨到期時間相差兩個數量級(100 倍),插值“膨脹”了。我不確定我做錯了什麼,如果有的話,或者如果我在某個地方做了不正確的假設。我知道有些程式碼是多餘的,例如如果我還包括明確的時期,則三種類型的開始和到期日期,但我沒有太多機會清理它。我還應該注意,我嘗試將 future_rate_val 更改為簡單的價格而不是 100 價格,但我得到了類似的錯誤結果,這本身有點令人不安。任何幫助,將不勝感激。
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 month in range(0, months): yrs = month/12.0 d = calendar.advance(ref_date, ql.Period(month, ql.Months)) 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)) """ Deposit Rates """ depo_starts = [ql.Date(1,9,2016),ql.Date(2,9,2016),ql.Date(6,9,2016),ql.Date(6,9,2016),ql.Date(6,9,2016)] depo_maturities = [ql.Date(2,9,2016),ql.Date(6,9,2016),ql.Date(6,10,2016),ql.Date(7,11,2016),ql.Date(6,12,2016)] depo_periods = [ql.Period(1,ql.Days),ql.Period(2,ql.Days),ql.Period(1,ql.Months),ql.Period(2,ql.Months),ql.Period(3,ql.Months)] depo_rates = [0.45, 0.48, 0.51765, 0.6328, 0.8176] """ Futures """ future_starts = [ql.Date(21,9,2016),ql.Date(21,12,2016),ql.Date(15,3,2017),ql.Date(21,6,2017),ql.Date(20,9,2017),ql.Date(20,12,2017),ql.Date(21,3,2018),ql.Date(20,6,2018),ql.Date(19,9,2018),ql.Date(19,12,2018),ql.Date(20,3,2019),ql.Date(19,6,2019)] future_maturities = [ql.Date(21,12,2016),ql.Date(21,3,2017),ql.Date(15,6,2017),ql.Date(21,9,2017),ql.Date(20,12,2017),ql.Date(20,3,2018),ql.Date(21,6,2018),ql.Date(20,9,2018),ql.Date(19,12,2018),ql.Date(19,3,2019),ql.Date(22,6,2019),ql.Date(19,9,2019)] future_rates = [99.13,99.095,99.075,99.045,99.015,98.975,98.955,98.93,98.9,98.855,98.83,98.8] """ Swaps """ swap_maturities = [ql.Date(8,9,2020),ql.Date(7,9,2021),ql.Date(6,9,2022),ql.Date(6,9,2023),ql.Date(6,9,2024),ql.Date(8,9,2025),ql.Date(8,9,2026),ql.Date(6,9,2028),ql.Date(8,9,1931),ql.Date(8,9,1936),ql.Date(6,9,1941),ql.Date(6,9,1946),ql.Date(6,9,1956),ql.Date(6,9,1966)] swap_periods = [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),ql.Period(50,ql.Years)] swap_rates = [1.06329999999999,1.12319999999999,1.1825,1.24150000000001,1.2975,1.349,1.3965,1.484,1.579,1.68250000000001,1.73049999999999,1.75749999999999,1.77579999999999,1.76000000000001] """ 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 """ DepositRateHelper """ depo_helpers = [] for i in range(len(depo_rates)): depo_helpers.append(ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(depo_rates[i]/100)),depo_periods[i],3,ql.TARGET(),ql.ModifiedFollowing,False,ql.Actual360())) """ FuturesRateHelper """ # Convexity Adjustments conv_adjust = [0,0.0001,0.0003,0.0007,0.0013,0.0027,0.005,0.0078,0.0112,0.0158,0.0211,0.0277] convexity_quote = [] for i in range(len(conv_adjust)): convexity_quote.append(ql.SimpleQuote(conv_adjust[i]/100.0)) imm = ql.IMM.nextDate(calc_date) futures_helpers = [] for i in range(len(future_rates)): future_rate_val = (100.0-future_rates[i])/100.0 futures_helpers.append(ql.FuturesRateHelper(ql.QuoteHandle(ql.SimpleQuote(future_rate_val)),imm,ql.Euribor3M(),ql.QuoteHandle(convexity_quote[i]))) imm = ql.IMM.nextDate(imm) """ 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 = depo_helpers + futures_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 = 50*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(splcd["Maturities"],splcd["Curve"], '.',label="LogCubicDiscount") 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('LIBORBootstrap.csv','w',newline='') as f: writer = csv.writer(f) for row in rows: writer.writerow(row)
`The FuturesRateHelper class knows that futures are quoted as 100-rate, so there’s no need to convert the prices. You can just create them as
futures_helpers.append(ql.FuturesRateHelper( ql.QuoteHandle(ql.SimpleQuote(future_rates[i])), imm,ql.Euribor3M(),ql.QuoteHandle(convexity_quote[i])))
I admit that the name of the class can lead one astray by mentioning rates instead of prices. Also, the other helpers might suggest that the division by 100 is needed, but that is only because the rates are given as, say, 0.43% when they are really 0.0043.`