Yield-Curve

QL-Python 引導收益率曲線 FuturesRateHelper 拋出結果

  • November 11, 2016

我正在嘗試根據存款利率、期貨和掉期來執行收益率曲線的引導,並且由於期貨到期時間相差兩個數量級(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.`

引用自:https://quant.stackexchange.com/questions/30972