2 votos

La curva de 3M basada en las comillas de 6M y los intercambios de base 6Mvs3M en Quantlib no tiene un precio de cero

Estoy tratando de entender el ayudante de la tasa más en detalle. En principio, quiero construir una curva a plazo de 3M basada en las comillas de 6M y 6Mvs3M.

El 6M funciona y cotiza a 0. No estoy seguro de si para el 3M estoy haciendo lo correcto alimentando la comilla del mercado y el basisswap-spread en el pricer del vanilla swap porque en los vencimientos más grandes estoy obteniendo desviaciones?

import QuantLib as ql

date = ql.Date(9, ql.February, 2015)
ql.Settings.instance().evaluationDate = date

#Definition of OIS and Libor Index
TONAR_JPY = ql.OvernightIndex("Tonar", 2, ql.JPYCurrency(), ql.Japan(), ql.Actual365Fixed())
Libor_JPY_3M = ql.JPYLibor(ql.Period(3, ql.Months))
Libor_JPY_6M = ql.JPYLibor(ql.Period(6, ql.Months))

#--------------------------------------------------------------------
# Discounting curve
#--------------------------------------------------------------------

#2015-02-09

# setup DepositRateHelper for 0-2 days
helpers_disc = [ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/100)),
                                     ql.Period(2,ql.Days), fixingDays,
                                     ql.Japan(), ql.ModifiedFollowing, False, ql.Actual365Fixed())
            for rate, fixingDays in [(0.081, 0)]]

# OIS quotes up to 30 years
# setup OISRateHelper from 15 months to 30 years
helpers_disc += [ql.OISRateHelper(2, ql.Period(*tenor),
                                 ql.QuoteHandle(ql.SimpleQuote(rate/100)), TONAR_JPY)
            for rate, tenor in [(0.0713, (1,ql.Weeks)), (0.0688, (2,ql.Weeks)), (0.0663, (3,ql.Weeks)), (0.0656, (1,ql.Months)), 
                                (0.0563, (4,ql.Months)), (0.055, (5,ql.Months)), (0.0538, (6,ql.Months)), (0.05, (11,ql.Months)),
                                (0.0494, (12,ql.Months)), (0.0481, (15,ql.Months)), (0.0506, (18,ql.Months)), (0.0538, (2,ql.Years)),
                                (0.0769, (3,ql.Years)), (0.1119, (4,ql.Years)), (0.2925, (8,ql.Years)), (0.3356, (9,ql.Years)),
                                (0.6888, (15,ql.Years)), (0.965, (20,ql.Years)), (1.1081, (25,ql.Years)), (1.1831, (30,ql.Years))]]

tonar_curve = ql.PiecewiseCubicZero(date, helpers_disc, ql.Actual365Fixed())
tonar_curve.enableExtrapolation()

discount_curve = ql.RelinkableYieldTermStructureHandle()
discount_curve.linkTo(tonar_curve)

#--------------------------------------------------------------------
#6-months JPY Libor
#--------------------------------------------------------------------

#Fixings
helpers_fwd_6M = [ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/100)),
                                     ql.Period(6,ql.Months), fixingDays,
                                     ql.Japan(), ql.ModifiedFollowing, False, ql.Actual365Fixed())
            for rate, fixingDays in [(0.14214, 0)]]

#FRA Helper
helpers_fwd_6M += [ql.FraRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/100)), start, Libor_JPY_6M)
            for rate, start in [(0.1444, 1), (0.1456, 2), (0.1463, 3),
                                (0.1475, 4), (0.1488, 5)]]
#Swap Helper
helpers_fwd_6M += [ql.SwapRateHelper(ql.QuoteHandle(ql.SimpleQuote((rate)/100)),
                                  ql.Period(tenor, ql.Years), ql.Japan(),
                                  ql.Semiannual, ql.Unadjusted, ql.Actual365Fixed(),
                                  Libor_JPY_6M, ql.QuoteHandle(), 
                                  ql.Period(0, ql.Days),
                                  discount_curve)
                for rate, tenor in [(0.1475, 1), (0.155, 2), (0.18, 3), (0.21875, 4), (0.2675, 5), (0.32, 6),
                                    (0.375, 7), (0.4325, 8), (0.49, 9), (0.55, 10), (0.67875, 12), (0.8825, 15),
                                    (1.16125, 20), (1.3075, 25), (1.385, 30)]]

jpy_libor_curve_6M = ql.PiecewiseCubicZero(date, helpers_fwd_6M, ql.Actual365Fixed())
jpy_libor_curve_6M.enableExtrapolation()

forward_curve_6M = ql.RelinkableYieldTermStructureHandle()
forward_curve_6M.linkTo(jpy_libor_curve_6M)

#--------------------------------------------------------------------
#3-months JPY Libor
#--------------------------------------------------------------------

#Fixings
helpers_fwd_3M = [ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/100)),
                                     ql.Period(3,ql.Months), fixingDays,
                                     ql.Japan(), ql.ModifiedFollowing, False, ql.Actual365Fixed())
            for rate, fixingDays in [(0.10429, 0)]]

#FRA Helper
helpers_fwd_3M += [ql.FraRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/100)), start, Libor_JPY_3M)
            for rate, start in [(0.1113, 1), (0.1138, 2), (0.115, 3), (0.1175, 4), (0.1188, 5), (0.1188, 6),
                                (0.1188, 7), (0.1188, 8)]]

helpers_fwd_3M += [ql.SwapRateHelper(ql.QuoteHandle(ql.SimpleQuote((rate)/100)),
                                  ql.Period(tenor, ql.Years), ql.Japan(),
                                  ql.Quarterly, ql.Unadjusted, ql.Actual365Fixed(),
                                  Libor_JPY_3M, ql.QuoteHandle(ql.SimpleQuote((basis/100/100))), 
                                  ql.Period(0, ql.Days),
                                  discount_curve)
            for rate, basis, tenor in [(0.1475, 3.25, 1), (0.155, 3.25, 2), (0.18, 3.25, 3), (0.21875, 3.375, 4), 
                                       (0.2675, 3.5, 5), (0.32, 3.625, 6), (0.375, 3.875, 7), (0.4325, 4.125, 8), 
                                       (0.49, 4.625, 9), (0.55, 5.125, 10), (0.67875, 6, 12), (0.8825, 6.5, 15),
                                       (1.16125, 6.5, 20), (1.3075, 6.5, 25), (1.385, 6.5, 30)]]

jpy_libor_curve_3M = ql.PiecewiseCubicZero(date, helpers_fwd_3M, ql.Actual365Fixed())
jpy_libor_curve_3M.enableExtrapolation()

forward_curve_3M = ql.RelinkableYieldTermStructureHandle()
forward_curve_3M.linkTo(jpy_libor_curve_3M)

#Swap Pricing 

settle_date = ql.Japan().advance(date, 2, ql.Days)
maturity_date = ql.Japan().advance(settle_date, 1, ql.Years)   
fixed_leg_tenor_6M = ql.Period(6, ql.Months)
float_leg_tenor_6M = ql.Period(6, ql.Months)
float_leg_tenor_3M = ql.Period(3, ql.Months)
fixed_leg_tenor_3M = ql.Period(3, ql.Months)

notional = 1000000

#6M Swap
#1Y market qoute
Market_Swap_Quote_6M = (0.1475/100)

#Fixed Rate
fixed_schedule_6M = ql.Schedule(settle_date, maturity_date, fixed_leg_tenor_6M, ql.Japan(), ql.ModifiedFollowing, ql.ModifiedFollowing,
                             ql.DateGeneration.Backward, True)

#Floating Rate
floating_schedule_6M = ql.Schedule(settle_date, maturity_date, float_leg_tenor_6M, ql.Japan(), ql.ModifiedFollowing, ql.ModifiedFollowing,
                                ql.DateGeneration.Backward, True)

index_complete_6M = ql.JPYLibor(ql.Period(6, ql.Months), forward_curve_6M)

swap_6M = ql.VanillaSwap(ql.VanillaSwap.Payer, notional,
                      fixed_schedule_6M, Market_Swap_Quote_6M, ql.Actual365Fixed(),
                      floating_schedule_6M, index_complete_6M, 0, ql.Actual360())   

swap_6M.setPricingEngine(ql.DiscountingSwapEngine(discount_curve))

#NPV
print('6M Swap NPV =', swap_6M.NPV())
print('6M Swap Fair Rate =', swap_6M.fairRate())

#3M Swap
#1Y market qoute
Market_Swap_Quote_3M = (0.1475/100)
Market_Quote_Spread_6M3M = (3.25/100/100)

#Fixed Rate
fixed_schedule_3M = ql.Schedule(settle_date, maturity_date, fixed_leg_tenor_3M, ql.Japan(), ql.ModifiedFollowing, ql.ModifiedFollowing,
                             ql.DateGeneration.Backward, True)

#Floating Rate
floating_schedule_3M = ql.Schedule(settle_date, maturity_date, float_leg_tenor_3M, ql.Japan(), ql.ModifiedFollowing, ql.ModifiedFollowing,
                                ql.DateGeneration.Backward, True)

index_complete_3M = ql.JPYLibor(ql.Period(3, ql.Months), forward_curve_3M)

swap_3M = ql.VanillaSwap(ql.VanillaSwap.Payer, notional,
                      fixed_schedule_3M, Market_Swap_Quote_3M, ql.Actual365Fixed(),
                      floating_schedule_3M, index_complete_3M, Market_Quote_Spread_6M3M, ql.Actual360())   

swap_3M.setPricingEngine(ql.DiscountingSwapEngine(discount_curve))

#NPV
print('3M Swap NPV =', swap_3M.NPV())
print('3M Swap Fair Rate =', swap_3M.fairRate())

1voto

Paulo J. Matos Puntos 165

La fucnión del VAN te da con la comilla del mercado el swap fuera de mercado. Para calcular el tipo fijo del swap a la par hay que utilizar la función

swap_3M.fairRate()

lo que resulta en un VAN igual a cero ( PV Fixed Leg = PV Floating Leg ).

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