Python

在 Quantlib Python 中使用 RateHelper(引導)和加速

  • March 11, 2018

我想知道是否有可能使用 ratehelpers/bootstrapping 以某種方式加速我的腳本。我每天都在創建一個新的 ratehelper。有沒有辦法只建立一次ratehelper然後每天引導?如果是的話,一個例子會是什麼樣子?

更新:

我的數據:

fact_date product_type    fra_start_period    maturity    tenor   quote   currency
2015-02-09    Deposit 0D  1D      0.081   JPY
2015-02-09    OIS     1W      0.0713  JPY
2015-02-09    OIS     3W      0.0663  JPY
2015-02-09    OIS     1M      0.0656  JPY
2015-02-09    OIS     2M      0.0613  JPY
2015-02-09    OIS     3M      0.06    JPY
2015-02-09    OIS     10M     0.05    JPY
2015-02-09    OIS     12M     0.0494  JPY
2015-02-09    OIS     5Y      0.1563  JPY
2015-02-09    OIS     6Y      0.2025  JPY
2015-02-09    OIS     7Y      0.2481  JPY
2015-02-09    OIS     10Y     0.3806  JPY
2015-02-09    OIS     15Y     0.6888  JPY
2015-02-09    OIS     20Y     0.965   JPY
2015-02-09    OIS     25Y     1.1081  JPY
2015-02-09    OIS     30Y     1.1831  JPY
2015-02-10    Deposit 0D  1D      0.074   JPY
2015-02-10    OIS     1W      0.0725  JPY
2015-02-10    OIS     3W      0.0688  JPY
2015-02-10    OIS     1M      0.0681  JPY
2015-02-10    OIS     2M      0.0625  JPY
2015-02-10    OIS     3M      0.0606  JPY
2015-02-10    OIS     10M     0.0531  JPY
2015-02-10    OIS     12M     0.0525  JPY
2015-02-10    OIS     5Y      0.1719  JPY
2015-02-10    OIS     6Y      0.2244  JPY
2015-02-10    OIS     7Y      0.2744  JPY
2015-02-10    OIS     10Y     0.4169  JPY
2015-02-10    OIS     15Y     0.7269  JPY
2015-02-10    OIS     20Y     1.0044  JPY
2015-02-10    OIS     25Y     1.1475  JPY
2015-02-10    OIS     30Y     1.2225  JPY

我的程式碼:

import QuantLib as ql
import pandas as pd
import datetime as dt

def Convert(Period):
   unit =[]
   if Period[-1:] == 'D':
       unit = ql.Days
   elif Period[-1:] == 'M':
       unit = ql.Months
   elif Period[-1:] == 'W':
       unit = ql.Weeks
   elif Period[-1:] == 'Y':
       unit = ql.Years
   period_object = ql.Period(int(Period[:-1]), unit)
   return period_object

def qlStr2periodNumber(Period):
   if Period[-1:] == "D":
       period_unit = int(Period[:1])
   elif Period[-1:] == 'M':
       period_unit = int(Period[:1])
   elif Period[-1:] == 'W':
       period_unit = int(Period[:1])
   elif Period[-1:] == 'Y':
       period_unit = int(Period[:1])
   elif Period == '':
       period_unit = int(0)
   else:
       raise Exception('(qlStr2periodNumber) Period'+ Period + 'not recognized!')
   return period_unit

def Datetime2ql(date):
   dates = ql.DateParser.parseFormatted(date,'%Y-%m-%d')
   return dates

def ql2Datetime(date):
   dates = dt.datetime(date.year(), date.month(), date.dayOfMonth())
   return dates

Index_OIS = ql.OvernightIndex("Tonar", 2, ql.JPYCurrency(), ql.Japan(), ql.Actual365Fixed())

data = pd.read_csv('C:/Book1.csv').fillna('')

quote_map = {}
helpers = []

for product_type, fra_start_period, maturity, quote in zip(data.product_type, data.fra_start_period, data.maturity, data.quote): 
   quotes = ql.SimpleQuote(quote/100)
   if product_type == 'Deposit':
       helper = ql.DepositRateHelper(ql.QuoteHandle(quotes),
                                     ql.Period(2,ql.Days),
                                     qlStr2periodNumber(fra_start_period),
                                     ql.Japan(),
                                     ql.ModifiedFollowing,
                                     False,
                                     ql.Actual365Fixed()                                      
                                     )
   elif product_type == 'OIS':
       helper = ql.OISRateHelper(2,
                                 Convert(maturity),
                                 ql.QuoteHandle(quotes),
                                 Index_OIS)

   helpers.append(helper)        

   quote_map[(product_type,fra_start_period,maturity)] = quotes

curve = ql.PiecewiseCubicZero(0, ql.Japan(), helpers, ql.Actual365Fixed())

for current_date in zip(data.fact_date):
   time = current_date[0]
   ql.Settings.instance().evaluationDate = Datetime2ql(str(time))
   for row in data:
       quote_map[(product_type, fra_start_period, maturity, quote)].setValue(quote)

是的,可以減少要創建的對像數量;這是否會加快您的計算取決於創建它們所花費的時間以及實際引導所花費的時間。任何狀況之下:

  1. 創建費率助手時,請確保您傳遞的是報價對象而不是簡單的數字;也就是說,類似
q1 = SimpleQuote(0.0125)
h1 = DepositRateHelper(QuoteHandle(q1), index)

並不是

h1 = DepositRateHelper(0.0125, index)
  1. 創建曲線時,不要明確指定其參考日期;相反,將其指定為從全域評估日期算起的天數(可能為 0);也就是說,類似
curve = PiecewiseFlatForward(0, UnitedStates(), helpers, day_counter)

如果您希望參考日期等於評估日期,或者

curve = PiecewiseFlatForward(2, UnitedStates(), helpers, day_counter)

如果你想讓它開始點。這樣,當評估日期發生變化時,曲線的參考日期將移動。 3. 現在你已經設置好了。當你想改變一個新的日期時,你會寫

Settings.instance().evaluationDate = new_today

對於每一個報價,

q1.setValue(new_value)

曲線將檢測變化並相應地重新計算。

在虛擬碼中,我們的想法是進行如下設置:

quote_map = {}
helpers = []
for type, fra_start_date, maturity in ...  # extract unique helper data
   quote = SimpleQuote(...)
   if type == 'Deposit':
       helper = ...
   else:
       ...
   helpers.append(helper)
   quote_map[(type,fra_start_date,maturity)] = quote
curve = PiecewiseCubicZero(2, Japan(), helpers, day_counter)

然後在日期上循環:

for current_date in ...
   # Don't build stuff, just change date and quotes
   Settings.instance().evaluationDate = current_date
   for row in ...
       quote_map[(type,fra_start_date,maturity)].setValue(value)
   # now the curve is updated and you can use it

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