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())