2 votos

en FixedRateBondHelper de quantlib

Estoy trabajando con 10 bonos con diferentes vencimientos y quiero obtener la curva cero. He probado el quantlib. Sin embargo, no puedo entender el parámetro en FixedRateBondHelper. Aquí está mi código:

def bootstrap(ytm_data):
calc_date = ql.Date(13, 4, 2020)
ql.Settings.instance().evaluationDate = calc_date

ytm_data['ytm'] = (1+ytm_data['ytm']/2).pow(2)-1 # annulize YTM
calendar = ql.UnitedStates()
bussiness_convention = ql.Unadjusted
#day_count_bill = ql.Actual360()
day_count = ql.ActualActual(ql.ActualActual.Bond)

end_of_month = False
settlement_days = 2
face_amount = 100
coupon_frequency = ql.UnitedStates.GovernmentBond

depo_helper = []
bond_helper = []

for date,rate,quote in ytm_data.values.tolist():
    timedelta = date - calc_date
    period = ql.Period('%dd'%timedelta)
    if timedelta<365:
        depo_helper.append(ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate)), period, settlement_days, calendar, bussiness_convention, end_of_month, day_count))
    if timedelta>365:
        schedule = ql.Schedule(calc_date, date,
           coupon_frequency,
           calendar,
           bussiness_convention,
           bussiness_convention,
           ql.DateGeneration.Backward,
           end_of_month)
        helper = ql.FixedRateBondHelper(ql.QuoteHandle(ql.SimpleQuote(quote)),
                                    settlement_days,
                                    face_amount,
                                    schedule,
                                    [rate],
                                    day_count,
                                    bussiness_convention,
                                    )
        bond_helper.append(helper)

rate_helper = depo_helper + bond_helper
yieldcurve = ql.PiecewiseLogCubicDiscount(calc_date,
                         rate_helper,
                         day_count)

spots = []
tenors = []

for d in yieldcurve.dates():
    yrs = day_count.yearFraction(calc_date, d)
    compounding = ql.Compounded
    freq = ql.Semiannual
    zero_rate = yieldcurve.zeroRate(yrs, compounding, freq)
    tenors.append(yrs)
    eq_rate = zero_rate.equivalentRate(day_count,
                                       compounding,
                                       freq,
                                       calc_date,
                                       d).rate()
    spots.append(eq_rate)

return spots,tenors,yieldcurve

Estos son los datos del mercado enter image description here Aquí está ytm_data enter image description here

He calculado el YTM de cada bono. Esta es la pregunta:

  1. ¿cuáles son los datos que debo poner en el ql.QuoteHandle(ql.SimpleQuote(rate))? Sólo uso YTM anulado como tasa
  2. cuál es la [tasa] en ql.FixedRateBondHelper, la tasa del cupón nuestra tasa YTM.
  3. Qué precio debo poner en ql.QuoteHandle(ql.SimpleQuote(quote)), precio limpio o precio completo.
  4. después del cálculo, el nodo en yieldcurve tiene una fecha diferente con los datos originales del mercado. ¿Por qué ocurre esto?

Soy bastante nuevo en quantlib. Gracias de antemano.

2voto

Chris Mc Puntos 31

La clase FixedRateBondHelper en python tiene el siguiente constructor:

ql.FixedRateBondHelper(
 price, settlementDays, faceAmount, schedule, coupons,
 dayCounter, paymentConv=Following, redemption=100.0,
 issueDate=Date(), paymentCalendar=Calendar(),
 exCouponPeriod=Period(), exCouponCalendar=Calendar(), 
 exCouponConvention=Unadjusted, exCouponEndOfMonth=False,
 useCleanPrice=True
)
  1. El primer argumento debería ser el precio.
  2. Debe introducir el cupón.
  3. Debe introducir el cupón. Alternativamente, podrías usar un precio de 100 y usar el YTM como cupón, lo que sería una aproximación bastante buena.
  4. A no ser que su calendario y sus convenciones trasladen las fechas a días laborables, los días deberían coincidir.

Prueba este ejemplo simplificado:

import QuantLib as ql

calc_date = ql.Date(13, 4, 2020)
ql.Settings.instance().evaluationDate = calc_date

data = [
    ('17-03-2020', '12-05-2020', 0, 99.99),
    ('09-01-2020', '09-07-2020', 0, 99.97),
    ('10-10-2019', '08-10-2020', 0, 99.94),
    ('26-03-2020', '25-03-2021', 0, 99.88),
    ('31-03-2020', '31-03-2022', 0.375, 100.28),
    ('15-04-2020', '15-04-2023', 0.25, 99.88),
    ('31-03-2020', '31-03-2025', 0.5, 100.4),
    ('18-02-2020', '31-03-2027', 0.625, 100.15),
    ('18-02-2020', '15-02-2030', 1.5, 107.25),
    ('18-02-2020', '15-02-2050', 2.0, 115.95),
]

helpers = []
day_count = ql.ActualActual(ql.ActualActual.Bond)

for issue_date, maturity, coupon, price in data:
    price = ql.QuoteHandle(ql.SimpleQuote(price))
    issue_date = ql.Date(issue_date, '%d-%m-%Y')
    maturity = ql.Date(maturity, '%d-%m-%Y')
    schedule = ql.MakeSchedule(issue_date, maturity, ql.Period(ql.Semiannual))
    helper = ql.FixedRateBondHelper(price, 2, 100, schedule, [coupon / 100], day_count)
    helpers.append(helper)
yieldcurve = ql.PiecewiseLogCubicDiscount(calc_date, helpers, day_count)    

Si compruebas los nodos de la curva, deberían coincidir con las fechas de vencimiento de tus instrumentos...

yieldcurve.nodes()

((Fecha(13,4,2020), 1.0),
(Date(12,5,2020), 0.999892874058905),
(Date(9,7,2020), 0.9996928754839124),
(Date(8,10,2020), 0.9993928776218975),
(Date(25,3,2021), 0.9987928818978993),
(Date(31,3,2022), 0.9954638937930196),
(Date(15,4,2023), 0.9913234618735143),
(Date(31,3,2025), 0.9794138780398628),
(Date(31,3,2027), 0.9586836389927256),
(Date(15,2,2030), 0.9291051282013438),
(Date(15,2,2050), 0.6518640785683848))

0 votos

¡Oh, gracias! Muy útil

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