python - QuantLib:交换到零息曲线自举
问题描述
我试图将美国掉期曲线引导成零息曲线(见彭博截图)。我有从 1996 年 6 月 21 日到今天的 3M、1Y、2Y、5Y、7Y、10Y 到期日的每日数据(有些日子不见了,请参阅 DataFrame 屏幕截图)。我想获得从 3M 到 10Y 的所有期限的相应零利率。
这是我写的一段代码:
zero_rates = {}
helpers_mat =[]
# loop over time
for t in range(irs.shape[0]):
# date of pricing (= DataFrame index line by line)
pricing_date = ql.DateParser.parseFormatted(str(irs.index[t]),'%Y-%m-%d')
# define evaluation date
ql.Settings.instance().evaluationDate = pricing_date
# list of maturities and corresponding swap rates
for m in irs.columns:
helpers_mat.append([(m, ql.Months), irs[m][t]])
# helper function to intput details
helpers = [ql.SwapRateHelper(
ql.QuoteHandle(ql.SimpleQuote(rate/100.0)),
ql.Period(*tenor),
ql.TARGET(),
ql.Semiannual,
ql.ModifiedFollowing,
ql.Thirty360(),
ql.Euribor3M())
for tenor, rate in helpers_mat]
# build zero-coupon curve (cubic spline interpolation)
zc_curve = ql.PiecewiseCubicZero(pricing_date, helpers, ql.Actual360())
# pre-allocate
zero_rate = []
tenors = []
# loop over wanted maturities
for n in np.arange(3, 120+1, 3):
# maturities
yrs = n/12.0
tenors.append(yrs)
# extract zero-coupon rate
zc_rate = zc_curve.zeroRate(yrs, ql.Compounded, ql.Annual).rate()
zero_rate.append(zc_rate*100)
# pandas export
zero_rates[t] = pd.DataFrame(np.transpose(list(zip(zero_rate))), columns = list(zip(tenors)),
index = [irs.index[t]])
zero_rates = pd.concat(zero_rates, axis=0)
使用该代码,我得到以下错误:
RuntimeError: 不止一种仪器与支柱 1996 年 7 月 25 日
所以我想我对日期有疑问。我的理解是SwapRateHelper具有掉期固定腿的特点。但是我在哪里输入浮动腿的?
解决方案
浮动腿参数来自索引。在您的情况下,您似乎正在使用 ql.Euribor3M() ,它与您真正想要的 USD Libor 3M 足够接近。区别基本上是错误的日历。
但是,不知道数据的形状很难找出问题所在。
有许多不同的方法可以构建辅助函数,对于美元曲线,您不妨将 USDLibor 指数用于存款,将 ql.UsdLiborSwapIsdaFixAm 用于掉期。
检查我根据您的数据制作的这个示例是否有帮助......
import pandas as pd
import QuantLib as ql
data = [
{'Date': '1996-06-21 00:00:00', '3M': 5.57813, '1Y': 6.19, '2Y': 6.55, '5Y': 7.02, '7Y': 7.17, '10Y': 7.31},
{'Date': '1996-06-24 00:00:00', '3M': 5.56641, '1Y': 6.18, '2Y': 6.54, '5Y': 6.99, '7Y': 7.14, '10Y': 7.31},
{'Date': '1996-06-25 00:00:00', '3M': 5.5625, '1Y': 6.155, '2Y': 6.52, '5Y': 6.99, '7Y': 7.15, '10Y': 7.31},
{'Date': '1996-06-26 00:00:00', '3M': 5.57031, '1Y': 6.14, '2Y': 6.52, '5Y': 6.94, '7Y': 7.1, '10Y': 7.27},
{'Date': '1996-06-27 00:00:00', '3M': 5.59766, '1Y': 6.16, '2Y': 6.5, '5Y': 6.93, '7Y': 7.09, '10Y': 7.26},
{'Date': '1996-06-28 00:00:00', '3M': 5.58203, '1Y': 6.075, '2Y': 6.44, '5Y': 6.87, '7Y': 7.03, '10Y': 7.2},
{'Date': '1996-07-01 00:00:00', '3M': 5.5625, '1Y': 6.03, '2Y': 6.33, '5Y': 6.75, '7Y': 6.92, '10Y': 7.09},
{'Date': '1996-07-02 00:00:00', '3M': 5.5625, '1Y': 6.05, '2Y': 6.36, '5Y': 6.77, '7Y': 6.93, '10Y': 7.11},
{'Date': '1996-07-03 00:00:00', '3M': 5.59766, '1Y': 6.11, '2Y': 6.43, '5Y': 6.84, '7Y': 7.0, '10Y': 7.17},
{'Date': '1996-07-04 00:00:00', '3M': 5.57031, '1Y': 6.07, '2Y': 6.37, '5Y': 6.79, '7Y': 6.95, '10Y': 7.13},
{'Date': '1996-07-05 00:00:00', '3M': 5.57422, '1Y': 6.075, '2Y': 6.4, '5Y': 6.8, '7Y': 6.96, '10Y': 7.13},
{'Date': '1996-07-08 00:00:00', '3M': 5.6875, '1Y': 6.33, '2Y': 6.69, '5Y': 7.11, '7Y': 7.27, '10Y': 7.44},
{'Date': '1996-07-09 00:00:00', '3M': 5.6875, '1Y': 6.31, '2Y': 6.64, '5Y': 7.07, '7Y': 7.23, '10Y': 7.41},
{'Date': '1996-07-10 00:00:00', '3M': 5.6875, '1Y': 6.28, '2Y': 6.545, '5Y': 6.985, '7Y': 7.145, '10Y': 7.325},
{'Date': '1996-07-11 00:00:00', '3M': 5.6875, '1Y': 6.22, '2Y': 6.465, '5Y': 6.925, '7Y': 7.085, '10Y': 7.255},
{'Date': '1996-07-12 00:00:00', '3M': 5.67578, '1Y': 6.17, '2Y': 6.465, '5Y': 6.905, '7Y': 7.055, '10Y': 7.225},
{'Date': '1996-07-15 00:00:00', '3M': 5.67578, '1Y': 6.19, '2Y': 6.485, '5Y': 6.925, '7Y': 7.075, '10Y': 7.245},
{'Date': '1996-07-16 00:00:00', '3M': 5.68359, '1Y': 6.22, '2Y': 6.425, '5Y': 6.855, '7Y': 7.025, '10Y': 7.205}
]
calendar = ql.UnitedStates()
zeros = []
deposits = ['3M']
swaps = ['1Y', '2Y', '5Y', '7Y', '10Y']
for row in data:
# Build Curve for the date
curve_date = ql.Date(row['Date'][:10], '%Y-%m-%d')
ql.Settings.instance().evaluationDate = curve_date
spot_date = calendar.advance(curve_date, 2, ql.Days)
helpers = ql.RateHelperVector()
for tenor in deposits:
index = ql.USDLibor(ql.Period(tenor))
helpers.append(
ql.DepositRateHelper(row[tenor] / 100, index)
)
for tenor in swaps:
swap_index = ql.UsdLiborSwapIsdaFixAm(ql.Period(tenor))
helpers.append(
ql.SwapRateHelper(row[tenor] / 100, swap_index)
)
curve = ql.PiecewiseCubicZero(curve_date, helpers, ql.Actual360())
# Get Zero Rates
for tenor in deposits + swaps:
date = calendar.advance(spot_date, ql.Period(tenor))
rate = curve.zeroRate(date, ql.Actual360(), ql.Compounded, ql.Annual).rate()
zeros.append({ 'curve_date': curve_date, 'tenor': tenor, 'zero_rate': rate})
pd.DataFrame(zeros)