5 votos

Evaluación de precios de un bono a tasa fija en Quantlib Python

Estoy tratando de implementar un modelo de precios para bonos con tasa fija con el código a continuación.

import QuantLib as ql
import pandas as pd

todaysDate = ql.Date(31, 8, 2017)
ql.Settings.instance().evaluationDate = todaysDate

spotDates = [ql.Date(1,9,2017), ql.Date(5,9,2017), ql.Date(7,9,2017), ql.Date(14,9,2017),   ql.Date(21,9,2017), ql.Date(2,10,2017), ql.Date(31,10,2017), ql.Date(30,11,2017), ql.Date(2,1,2018), ql.Date(31,1,2018), ql.Date(28,2,2018), ql.Date(3,4,2018), ql.Date(30,4,2018)]
spotRates = [0.066682, 0.067199, 0.067502, 0.068526, 0.069462, 0.070742, 0.072984, 0.073566, 0.073174, 0.072844, 0.072610, 0.072467, 0.072366]

dayCount = ql.Actual365Fixed()
calendar = ql.SouthAfrica()
interpolation = ql.Linear()
compounding = ql.Compounded
compoundingFrequency = ql.Semiannual

spotCurve = ql.ZeroCurve(spotDates, spotRates, dayCount, calendar, 
interpolation, compounding, compoundingFrequency)
spotCurveHandle = ql.YieldTermStructureHandle(spotCurve)

issueDate = ql.Date(20, 4, 2009)
maturityDate = ql.Date(20, 4, 2018)
tenor = ql.Period(ql.Semiannual)
calendar = ql.SouthAfrica()
bussinessConvention = ql.Following
dateGeneration = ql.DateGeneration.Backward
monthEnd = False

schedule = ql.Schedule (issueDate, maturityDate, tenor, calendar, bussinessConvention, bussinessConvention, dateGeneration, monthEnd)

dayCount = ql.Actual365Fixed()
couponRate = 0.0925
coupons = [couponRate]

settlementDays = 3
faceValue = 100
fixedRateBond = ql.FixedRateBond(settlementDays, faceValue, schedule, coupons, dayCount)

bondEngine = ql.DiscountingBondEngine(spotCurveHandle)
fixedRateBond.setPricingEngine(bondEngine)

fixedRateBond.NPV()
print(fixedRateBond.NPV())
print(fixedRateBond.dirtyPrice())
print(fixedRateBond.cleanPrice())
print(fixedRateBond.accruedAmount())
print(fixedRateBond.dayCounter())
print(fixedRateBond.settlementDate())

for c in fixedRateBond.cashflows():
    print('%20s %12f' % (c.date(), c.amount()))

Mi cronograma de flujo de efectivo parece un poco extraño, esperaba valores de 4.625.

October 20th, 2009     4.637671
April 20th, 2010       4.612329
October 20th, 2010     4.637671
April 20th, 2011       4.612329
October 20th, 2011     4.637671
April 20th, 2012       4.637671
October 22nd, 2012     4.688356
April 22nd, 2013       4.612329
October 21st, 2013     4.612329
April 22nd, 2014       4.637671
October 20th, 2014     4.586986
April 20th, 2015       4.612329
October 20th, 2015     4.637671
April 20th, 2016       4.637671
October 20th, 2016     4.637671
April 20th, 2017       4.612329
October 20th, 2017     4.637671
April 20th, 2018       4.612329
April 20th, 2018     100.000000

Los valores del modelo producidos son:

104.60163528858176
104.6774279539175
101.18016767994489
3.497260273972613
Actual/365 (Fixed) day counter
September 5th, 2017

El valor que obtengo por intereses devengados es correcto con los valores proporcionados por nuestro sistema interno, pero los precios están un poco desfasados. La expectativa de precio limpio es 100.81517 y la expectativa de precio sucio es 104.31243

0 votos

QuantLib no puede estar equivocado aquí. Es 100% correcto. O tu sistema interno está equivocado o tus entradas no son consistentes. ¿Puedes mostrar un cálculo manual de por qué crees que deberías tener 4.625?

2 votos

Es correcto, dados los inputs. Por ejemplo, el cálculo de los cupones es correcto basado en la convención de conteo de días Act/365 utilizada durante la construcción. Si tus cupones pagan 4.625 en la vida real, significa que probablemente están utilizando una convención Act/Act y debes pasar esta última al constructor FixedRateBond.

0 votos

Está bien, el valor del cupón siendo exacto aquí no es la mayor preocupación, ya que mis montos de interés acumulados están exactamente en línea, por lo tanto mi convención de conteo de días debe ser correcta. Mi principal preocupación sería por qué el precio limpio y el precio total no están en línea con mis expectativas. ¿Es correcto mi uso de la curva de tasas de interés cero en las fechas que he especificado?

6voto

Brian Jonestown Puntos 71

Intenta:

dayCount = ql.ActualActual(ql.ActualActual.ISMA,schedule)

1voto

David Radcliffe Puntos 136

Su bono paga fijo 9.25% al año, dos veces al año. Para la mayoría de bonos de cupón fijo, el cupón no se "daycounted" - debería ser exactamente cupón anual / frecuencia = 4.625% (hay muy pocas excepciones, como los mbonos mexicanos). El daycount se usa si necesitas calcular el devengado en el medio del período del cupón, por ejemplo, para obtener un precio sucio. Para la mayoría de préstamos de cupón fijo, lpns, piernas de cupón fijo de swaps de tasa de interés, etc., la convención del mercado es daycount los cupones, que es lo que hace tu código.

Solo enfocándonos en proyectar los flujos de efectivo esperados, no creo que cambiar la convención de daycount a Actual / Actual ayude. Resultaría en una fracción de período de 182/365 o 183/365 o (en año bisiesto) /366, mientras que quieres exactamente 1/2, independientemente de los días festivos y el número de días en varios meses. También produciría un devengado diferente durante el período del cupón, y estás satisfecho con el devengado que tienes ahora.

Creo (no lo he intentado) que una forma de obtener los flujos de efectivo deseados de QL puede ser cambiar el bussinessConvention que pasas al horario de

bussinessConvention = ql.Following

a bussinessConvention = ql.Unadjusted

Pero luego querrás que los factores de descuento que aplicas a tus flujos de efectivo sean en días hábiles (ajustados para fines de semana y días festivos).

0 votos

@Dmitri Vulis si no te importa explicar, al calcular el precio de los bonos del gobierno en FX con la convención Actual/365, ¿afectará el calendario del país al cálculo del precio sucio?

0 votos

Lo siento, ¿a qué te refieres con bonos de FX?

0 votos

@Dmitri Vulis perdón por no decirlo exactamente, me refería a bonos del gobierno del mercado local de FX, por lo tanto, bonos del gobierno de países como India, Nigeria, Argentina, etc. Sé que no todos usan Act/365, pero mi pregunta era sobre Act/Act (o Act/365), ¿cómo afecta el uso de un calendario de días festivos incorrecto o inexistente al cálculo del precio limpio/sucio? Según entiendo, el hecho de que los flujos de efectivo no se paguen en fines de semana/días festivos, pero generalmente ModificadoSiguiente (con algunas excepciones como México) afectará ligeramente el precio limpio/sucio final, porque los flujos de efectivo que caen en esos días malos se descuentan (se trasladan a) desde fechas comerciales. Gracias.

0voto

user47082 Puntos 36

He necesitado hacer exactamente lo mismo y encontré la solución al configurar tanto daycount = SimpleDayCounter() como bussinessConvention = Unadjusted

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