运行时错误 - 远期利率计算

问题描述

我正在尝试使用从 1 周到 50 年的期限输入来构建远期年度 EONIA 远期曲线。

到目前为止,我已经设法编写代码

data
   maturity  spot rate
0         1     -0.529
1         2     -0.529
2         3     -0.529
3         1     -0.504
4         2     -0.505
5         3     -0.506
6         4     -0.508
7         5     -0.509
8         6     -0.510
9         7     -0.512
10        8     -0.514
11        9     -0.515
12       10     -0.517
13       11     -0.518
14        1     -0.520
15       15     -0.524
16       18     -0.526
17       21     -0.527
18        2     -0.528
19        3     -0.519
20        4     -0.501
21        5     -0.476
22        6     -0.441
23        7     -0.402
24        8     -0.358
25        9     -0.313
26       10     -0.265
27       11     -0.219
28       12     -0.174
29       15     -0.062
30       20      0.034
31       25      0.054
32       30      0.039
33       40     -0.001
34       50     -0.037

terms= data["maturity"].tolist()
rates= data['spot rate'].tolist()


calendar = ql.TARGET() 
business_convention = ql.ModifiedFollowing
day_count = ql.Actual360()
settlement_days_EONIA = 2
EONIA = ql.OvernightIndex("EONIA",settlement_days_EONIA,ql.EURCurrency(),calendar,day_count)

# Deposit Helper
depo_facility = -0.50
depo_helper = [ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(depo_facility/100)),ql.Period(1,ql.Days),1,ql.Unadjusted,False,day_count)]

# OIS Helper
OIS_helpers = []
for i in range(len(terms)):
    if i < 3:
        tenor = ql.Period(ql.Weeks)
        eon_rate = rates[i]
        OIS_helpers.append(ql.OISRateHelper(settlement_days_EONIA,tenor,ql.QuoteHandle(ql.SimpleQuote(eon_rate/100)),EONIA))    
    elif i < 12: 
        tenor = ql.Period(ql.Months)
        eon_rate = rates[i]
        OIS_helpers.append(ql.OISRateHelper(settlement_days_EONIA,EONIA)) 
    else:
        tenor = ql.Period(ql.Years)
        eon_rate = rates[i]
        OIS_helpers.append(ql.OISRateHelper(settlement_days_EONIA,EONIA))
    
rate_helpers = depo_helper +  OIS_helpers

eonia_curve_c = ql.PiecewiseLogCubicdiscount(0,ql.TARGET(),rate_helpers,day_count)
#This doesn't give me a daily grid of rates,but only the rates at the tenors of my input

eonia_curve_c.enableExtrapolation()


days = ql.MakeSchedule(eonia_curve_c.referenceDate(),eonia_curve_c.maxDate(),ql.Period('1Y'))

rates_fwd = [
    eonia_curve_c.forwardrate(d,calendar.advance(d,365,day_count,ql.Simple).rate()*100
    for d in days
]

问题是当我运行代码时,出现以下错误

RuntimeError: more than one instrument with pillar June 18th,2021

OIS 帮助程序的代码中某处可能存在错误,其中存在重叠,但我不确定我做错了什么。有人知道问题出在哪里吗?

解决方法

首先,为任何不优雅的 Python 道歉,因为我来自 C++:

原始问题的主要问题是 ql.Period() 在与整数个周期一起使用时采用两个参数:例如 ql.Period(3,ql.Years)。相反,如果您使用 Tenors 的字符串表示来构造输入数组,例如“3y”,您可以将此字符串传递给 ql.Period()。所以 ql.Period(3,ql.Years) 和 ql.Period('3y') 给出相同的结果。

import QuantLib as ql

import numpy as np
import pandas as pd

curve = [ ['1w',-0.529],['2w',['3w',['1m',-0.504],['2m',-0.505],['3m',-0.506],['4m',-0.508],['5m',-0.509],['6m',-0.510],['7m',-0.512],['8m',-0.514],['9m',-0.515],['10m',-0.517],['11m',-0.518],['1y',-0.520],['15m',-0.524],['18m',-0.526],['21m',-0.527],['2y',-0.528],['3y',-0.519],['4y',-0.501],['5y',-0.476],['6y',-0.441],['7y',-0.402],['8y',-0.358],['9y',-0.313],['10y',-0.265],['11y',-0.219],['12y',-0.174],['15y',-0.062],['20y',0.034],['25y',0.054],['30y',0.039],['40y',-0.001],['50y',-0.037] ]

data = pd.DataFrame(curve,columns = ['maturity','spot rate'])

print('Input curve\n',data)

terms= data["maturity"].tolist()
rates= data['spot rate'].tolist()

calendar = ql.TARGET() 
day_count = ql.Actual360()
settlement_days_EONIA = 2
EONIA = ql.OvernightIndex("EONIA",settlement_days_EONIA,ql.EURCurrency(),calendar,day_count)

# Deposit Helper
depo_facility = -0.50
depo_helper = [ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(depo_facility/100)),ql.Period(1,ql.Days),1,ql.Unadjusted,False,day_count)]

# OIS Helper
OIS_helpers = []
for i in range(len(terms)):
        tenor = ql.Period(terms[i])
        eon_rate = rates[i]
        OIS_helpers.append(ql.OISRateHelper(settlement_days_EONIA,tenor,ql.QuoteHandle(ql.SimpleQuote(eon_rate/100)),EONIA))    
    
rate_helpers = depo_helper +  OIS_helpers

eonia_curve_c = ql.PiecewiseLogCubicDiscount(0,ql.TARGET(),rate_helpers,day_count)
#This doesn't give me a daily grid of rates,but only the rates at the tenors of my input

eonia_curve_c.enableExtrapolation()


days = ql.MakeSchedule(eonia_curve_c.referenceDate(),eonia_curve_c.maxDate(),ql.Period('1Y'))

rates_fwd = [
    eonia_curve_c.forwardRate(d,calendar.advance(d,365,day_count,ql.Simple).rate()*100
    for d in days
]

print('Output\n',pd.DataFrame(rates_fwd,columns=['Fwd rate']))