8 votos

Utilizar QuantLib Python para calcular el Swap DV01

Quisiera utilizar QuantLib Python para calcular el DV01 de un swap de tipos de interés.

Inicialmente estaba pensando en calcular el DV01 de la pata fija y el DV01 de la pata flotante por separado, y luego sumar ambos DV01 para obtener el DV01 de la permuta. Sin embargo, no sé cómo calcular la pierna flotante DV01 usando QuantLib Python.

Al final adopté un enfoque diferente para calcular el swap de tipos de interés DV01 utilizando el siguiente código:

from QuantLib import *

# global data
calendar = TARGET()
todaysDate = Date(6,November,2001);
Settings.instance().evaluationDate = todaysDate
settlementDate = Date(8,November,2001);

# market quotes
deposits = { (1,Weeks): 0.0382,
             (1,Months): 0.0372,
             (3,Months): 0.0363,
             (6,Months): 0.0353,
             (9,Months): 0.0348,
             (1,Years): 0.0345 }

swaps = { (2,Years): 0.037125,
          (3,Years): 0.0398,
          (5,Years): 0.0443,
          (10,Years): 0.05165,
          (15,Years): 0.055175 }

# convert them to Quote objects
for n,unit in deposits.keys():
    deposits[(n,unit)] = SimpleQuote(deposits[(n,unit)])
for n,unit in swaps.keys():
    swaps[(n,unit)] = SimpleQuote(swaps[(n,unit)])

# build rate helpers

dayCounter = Actual360()
settlementDays = 2
depositHelpers = [ DepositRateHelper(QuoteHandle(deposits[(n,unit)]),
                                     Period(n,unit), settlementDays,
                                     calendar, ModifiedFollowing,
                                     False, dayCounter)
                   for n, unit in [(1,Weeks),(1,Months),(3,Months),
                                   (6,Months),(9,Months),(1,Years)] ]

fixedLegFrequency = Annual
fixedLegTenor = Period(1,Years)
fixedLegAdjustment = Unadjusted
fixedLegDayCounter = Thirty360()
floatingLegFrequency = Semiannual
floatingLegTenor = Period(6,Months)
floatingLegAdjustment = ModifiedFollowing
swapHelpers = [ SwapRateHelper(QuoteHandle(swaps[(n,unit)]),
                               Period(n,unit), calendar,
                               fixedLegFrequency, fixedLegAdjustment,
                               fixedLegDayCounter, Euribor6M())
                for n, unit in swaps.keys() ]

# term structure handles

discountTermStructure = RelinkableYieldTermStructureHandle()
forecastTermStructure = RelinkableYieldTermStructureHandle()

# term-structure construction

helpers = depositHelpers + swapHelpers
depoSwapCurve = PiecewiseFlatForward(settlementDate, helpers, Actual360())

swapEngine = DiscountingSwapEngine(discountTermStructure)

# 5Y Swap 

nominal = 1000000
maturity = calendar.advance(settlementDate,5,Years)

fixedLegFrequency = Annual
fixedLegAdjustment = Unadjusted
fixedLegDayCounter = Thirty360()
fixedRate = 0.04

floatingLegFrequency = Semiannual
spread = 0.0
fixingDays = 2
index = Euribor6M(forecastTermStructure)
floatingLegAdjustment = ModifiedFollowing
floatingLegDayCounter = index.dayCounter()

fixedSchedule = Schedule(settlementDate, maturity,
                         fixedLegTenor, calendar,
                         fixedLegAdjustment, fixedLegAdjustment,
                         DateGeneration.Forward, False)
floatingSchedule = Schedule(settlementDate, maturity,
                            floatingLegTenor, calendar,
                            floatingLegAdjustment, floatingLegAdjustment,
                            DateGeneration.Forward, False)

swap = VanillaSwap(VanillaSwap.Receiver, nominal,
                   fixedSchedule, fixedRate, fixedLegDayCounter,
                   floatingSchedule, index, spread,
                   floatingLegDayCounter)
swap.setPricingEngine(swapEngine)

discountTermStructure.linkTo(depoSwapCurve)
forecastTermStructure.linkTo(depoSwapCurve)
print('Fixed Leg DV01')
print(swap.fixedLegBPS())

shift = 0.0001

temp_fyc_handle = YieldTermStructureHandle(depoSwapCurve)
temp_dyc_handle = YieldTermStructureHandle(depoSwapCurve)
shiftedForwardCurve = ZeroSpreadedTermStructure(temp_fyc_handle, QuoteHandle(SimpleQuote(shift)))
shiftedDiscountCurve = ZeroSpreadedTermStructure(temp_dyc_handle, QuoteHandle(SimpleQuote(shift)))
discountTermStructure.linkTo(shiftedDiscountCurve)
forecastTermStructure.linkTo(shiftedForwardCurve)
P_p = swap.NPV()

temp_fyc_handle = YieldTermStructureHandle(depoSwapCurve)
temp_dyc_handle = YieldTermStructureHandle(depoSwapCurve)
shiftedForwardCurve = ZeroSpreadedTermStructure(temp_fyc_handle, QuoteHandle(SimpleQuote(-shift)))
shiftedDiscountCurve = ZeroSpreadedTermStructure(temp_dyc_handle, QuoteHandle(SimpleQuote(-shift)))
discountTermStructure.linkTo(shiftedDiscountCurve)
forecastTermStructure.linkTo(shiftedForwardCurve)
P_m = swap.NPV()

dv01 = (P_m - P_p) / 2.0
print('Swap DV01')
print(dv01)

¿Estoy en lo cierto en cuanto a cómo utilizar QuantLib Python para calcular el swap de tipos de interés DV01? El resultado del código anterior muestra que el DV01 del tramo fijo es menor que el DV01 de todo el swap. ¿Es correcto?

13voto

Brad Tutterow Puntos 5628

No, me temo que estás comparando manzanas con naranjas. Su cálculo del DV01 del canje es correcto (con una advertencia, véase más abajo), pero la cifra devuelta de swap.fixedLegBPS no es comparable.

El DV01 indica lo que ocurre con el VAN si cambia la curva de tipos de interés; en el caso del tramo fijo, esto afecta a los factores de descuento utilizados para descontar los importes de los cupones, pero no a los propios importes que son fijos.

El BPS indica lo que ocurre con el VAN si el tipo de los cupones fijos aumenta en 1 punto básico y los tipos de interés (y, por tanto, los factores de descuento) permanecen iguales. Es útil para calcular el tipo justo, o mientras se define la operación, pero probablemente no tanto una vez que el swap está construido y su tipo es fijo. Así que: cosas diferentes.

Si quieres calcular el DV01 del tramo fijo solo, puedes hacer algo así:

shift = 0.0001

temp_dyc_handle = YieldTermStructureHandle(depoSwapCurve)
shiftedDiscountCurve = ZeroSpreadedTermStructure(temp_dyc_handle, QuoteHandle(SimpleQuote(shift)))
discountTermStructure.linkTo(shiftedDiscountCurve)
P_p = CashFlows.npv(swap.fixedLeg(), discountTermStructure, False, settlementDate)

temp_dyc_handle = YieldTermStructureHandle(depoSwapCurve)
shiftedDiscountCurve = ZeroSpreadedTermStructure(temp_dyc_handle, QuoteHandle(SimpleQuote(-shift)))
discountTermStructure.linkTo(shiftedDiscountCurve)
P_m = CashFlows.npv(swap.fixedLeg(), discountTermStructure, False, settlementDate)

dv01 = (P_m - P_p) / 2.0
print('Fixed Leg DV01')
print(dv01)

Sobre la advertencia que mencioné anteriormente: estás haciendo

discountTermStructure.linkTo(depoSwapCurve)
forecastTermStructure.linkTo(depoSwapCurve)

es decir, se utiliza la misma curva para la previsión de la fijación del tipo flotante y el descuento de los flujos de caja, que es lo que hacemos en el ejemplo incluido en la versión de QuantLib. Deberíamos actualizarlo; hoy en día, la práctica es utilizar dos curvas diferentes para la previsión y el descuento. En ese caso, probablemente siga teniendo sentido definir el DV01 como la variación del VAN cuando se desplazan ambas curvas, como se hace ahora; pero asegúrese de que esto es lo que quiere.

0 votos

¿desplazamos la curva de previsión para calcular el tramo flotante DVO1?

0 votos

Yo comprobaría cómo se define en tu contexto.

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