首页 > 解决方案 > QuantLib:交换到零息曲线自举

问题描述

我试图将美国掉期曲线引导成零息曲线(见彭博截图)。我有从 1996 年 6 月 21 日到今天的 3M、1Y、2Y、5Y、7Y、10Y 到期日的每日数据(有些日子不见了,请参阅 DataFrame 屏幕截图)。我想获得从 3M 到 10Y 的所有期限的相应零利率。

彭博社 5 年美国掉期截图

交换曲线数据

这是我写的一段代码:

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具有掉期固定腿的特点。但是我在哪里输入浮动腿的?

标签: pythonquantlib

解决方案


浮动腿参数来自索引。在您的情况下,您似乎正在使用 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)

推荐阅读