3 votos

Usando RateHelper (bootstrapping) y Speed up en Quantlib Python

Me pregunto si es posible de alguna manera acelerar mi guión usando ratehelpers/bootstrapping. Estoy creando para cada día un nuevo ratehelper. ¿Hay alguna manera de crear sólo una vez el ratehelper y luego el bootstrap día a día? Si es así, ¿cómo sería un ejemplo?

Actualizar:

Mi Data:

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

Mi código:

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)

5voto

Brad Tutterow Puntos 5628

Sí, es posible reducir el número de objetos que creará; que esto acelere sus cálculos depende de cuánto tiempo le lleve su creación y cuánto le lleve el bootstrapping real. En cualquier caso:

  1. Cuando crees tus ayudantes de tarifa, asegúrate de pasar objetos de cita y no simples números; es decir, algo como

    q1 = SimpleQuote(0.0125)
    h1 = DepositRateHelper(QuoteHandle(q1), index)

    y no

    h1 = DepositRateHelper(0.0125, index)
  2. cuando cree su curva, no especifique su fecha de referencia explícitamente; en su lugar, especifíquela como un número de días (posiblemente 0) a partir de la fecha de evaluación global; es decir, algo como

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

    si quiere que la fecha de referencia sea igual a la fecha de evaluación, o

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

    si quieres que empiece en el lugar. De esta manera, la fecha de referencia de la curva se moverá cuando cambie la fecha de evaluación.

  3. Ahora estás preparado. Cuando quieras cambiar a una nueva fecha, escribirás

    Settings.instance().evaluationDate = new_today

    y por cada cita,

    q1.setValue(new_value)

    la curva detectará los cambios y recalculará en consecuencia.

En pseudocódigo, la idea sería tener una configuración como:

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)

y luego el bucle sobre las fechas:

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

Finanhelp.com

FinanHelp es una comunidad para personas con conocimientos de economía y finanzas, o quiere aprender. Puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X