2 votos

Utilización de la estructura temporal de rendimientos para la valoración de bonos en QuantLib: ¿Es necesaria una curva cupón cero?

He estado utilizando QuantLib para construir una curva de rendimiento y fijar el precio de un bono. Me pregunto si estoy utilizando el método correcto para crear mi estructura de plazos de rendimiento ( yts ) para el proceso de fijación de precios.

Este es el ejemplo reproducible :

import QuantLib as ql
import math

calculation_date = ql.Date().todaysDate()

ql.Settings.instance().evaluationDate = calculation_date
yts = ql.RelinkableYieldTermStructureHandle()

index = ql.OvernightIndex("USD Overnight Index", 0, ql.USDCurrency(), ql.UnitedStates(ql.UnitedStates.Settlement), ql.Actual360(),yts)

swaps = {
    ql.Period("1W"): 0.05064,
    ql.Period("2W"): 0.05067,
    ql.Period("3W"): 0.05072,
    ql.Period("1M"): 0.051021000000000004,
    ql.Period("2M"): 0.051391,
    ql.Period("3M"): 0.051745,
    ql.Period("4M"): 0.05194,
    ql.Period("5M"): 0.051980000000000005,
    ql.Period("6M"): 0.051820000000000005,
    ql.Period("7M"): 0.051584000000000005,
    ql.Period("8M"): 0.05131,
    ql.Period("9M"): 0.050924,
    ql.Period("10M"): 0.050603999999999996,
    ql.Period("11M"): 0.050121,
    ql.Period("12M"): 0.049550000000000004,
    ql.Period("18M"): 0.04558500000000001,
    ql.Period("2Y"): 0.042630999999999995,
    ql.Period("3Y"): 0.038952,
    ql.Period("4Y"): 0.036976,
    ql.Period("5Y"): 0.035919,
    ql.Period("6Y"): 0.03535,
    ql.Period("7Y"): 0.034998,
    ql.Period("8Y"): 0.034808,
    ql.Period("9Y"): 0.034738000000000005,
    ql.Period("10Y"): 0.034712,
    ql.Period("12Y"): 0.034801,
    ql.Period("15Y"): 0.034923,
    ql.Period("20Y"): 0.034662,
    ql.Period("25Y"): 0.03375,
    ql.Period("30Y"): 0.032826,
    ql.Period("40Y"): 0.030834999999999998,
    ql.Period("50Y"): 0.02896
}

rate_helpers = []

for tenor, rate in swaps.items():
    helper = ql.OISRateHelper(2, tenor, ql.QuoteHandle(ql.SimpleQuote(rate)), index)
    rate_helpers.append(helper)

curve = ql.PiecewiseFlatForward(calculation_date, rate_helpers, ql.Actual360())
yts.linkTo(curve)

index = index.clone(yts)

engine = ql.DiscountingSwapEngine(yts)

print("maturity |  market  |  model  |  zero rate  |  discount factor |  present value")
for tenor, rate in swaps.items():
    ois_swap = ql.MakeOIS(tenor, index, rate)
    pv = ois_swap.NPV()
    fair_rate = ois_swap.fairRate()
    maturity_date = ois_swap.maturityDate()
    discount_factor = curve.discount(maturity_date)
    zero_rate = curve.zeroRate(maturity_date, ql.Actual365Fixed() , ql.Continuous).rate()
    print(f"   {tenor}    | {rate*100:.6f} | {fair_rate*100:.6f} | {zero_rate*100:.6f} | {discount_factor:.6f} | {pv:.6f}")

issue_date = ql.Date(12,1,2022)
maturity_date = ql.Date(12,1,2027)
coupon_frequency = ql.Period(ql.Semiannual)
calendar = ql.UnitedStates(ql.UnitedStates.GovernmentBond)
date_generation = ql.DateGeneration.Backward
coupon_rate = 4.550000/100
day_count = ql.Thirty360(ql.Thirty360.USA)
spread = ql.SimpleQuote(89.965 / 10000.0)

schedule = ql.Schedule( issue_date,
                        maturity_date,
                        coupon_frequency,
                        calendar,
                        ql.Unadjusted,
                        ql.Unadjusted,
                        date_generation,
                        False)

bond = ql.FixedRateBond(2, 100, schedule, [coupon_rate], day_count)

spread_handle = ql.QuoteHandle(spread)
spreaded_curve = ql.ZeroSpreadedTermStructure(yts, spread_handle)
spreaded_curve_handle = ql.YieldTermStructureHandle(spreaded_curve)
bond.setPricingEngine(ql.DiscountingBondEngine(spreaded_curve_handle))
print(f"NPV {bond.NPV()} vs dirty price {bond.dirtyPrice()} - clean price {bond.cleanPrice()}")

Utilizo la estructura temporal de rendimientos ( yts ) vinculada a la curva ( curve ) construido utilizando ql.PiecewiseFlatForward .

Me pregunto si es correcto utilizar la yts que enlaza con la curva a plazo para fijar el precio del bono.

O, ¿necesito construir una curva de cupón cero para la fijación de precios? En caso afirmativo, ¿cómo puedo construir y utilizar esta curva de cupón cero?

He observado que QuantLib permite la conversión de tipos a plazo a tipos cero utilizando la función zeroRate() función. ¿Es suficiente esta función para obtener los tipos cupón cero correctos a partir de los tipos a plazo para la fijación del precio de los bonos, o es necesaria una construcción más explícita de una curva cupón cero?

Agradecería cualquier orientación o ejemplo. Gracias.

2voto

Brad Tutterow Puntos 5628

La curva a utilizar tiene poco que ver con QuantLib en sí y más con la forma de modelizar el riesgo de crédito de su bono.

Si se utilizan los tipos OIS, con QuantLib o sin él, se obtiene un tipo sin riesgo que, de hecho, también puede dar tipos cero (integrando los contratos a plazo) y, si se utiliza QuantLib, se puede pasar a DiscountingBondEngine . Pero probablemente sea la curva equivocada para descontar porque no tiene riesgo.

La curva de riesgo que se utilice dependerá de los datos de que disponga. Puede ajustar una sobre los precios de los bonos cotizados (véase, por ejemplo, QuantLib's FittedBondDiscountCurve ), o puede añadir un diferencial z sobre la curva libre de riesgo para añadir riesgo de crédito (con ZeroSpreadedTermStructure en QuantLib), o puede interpolar tasas cero o factores de descuento procedentes de alguna otra mesa ( ZeroCurve o DiscountCurve respectivamente).

Sin embargo, es una elección de modelo y depende de tu contexto. Buscar cómo utilizar la clase correspondiente es probablemente la parte fácil.

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