1 votos

QuantLib devuelve un rendimiento de los bonos ligeramente diferente cuando se hace un backtesting

Estoy empezando a familiarizarme con QuantLib (en particular, con las funciones de fijación de precios de los bonos a tipo fijo). He leído una serie de ejemplos, a partir de los cuales soy capaz de calcular el precio y el rendimiento de los bonos.

El siguiente script utiliza un rendimiento de entrada (0,057154825761367800000) para calcular el precio del bono (96,9073930899788536), utilizando bond.cleanPrice.

A continuación, tomé el precio del bono calculado y lo introduje de nuevo en el cálculo de bond.bondYield (sin cambiar el resto de datos de entrada), esperando obtener el rendimiento de entrada original.

He comprobado que el rendimiento calculado a posteriori se aproxima, pero no tanto como yo esperaba ingenuamente (coincide con 8 decimales). ¿He hecho algo mal? ¿Es esta precisión aceptable basada en las iteraciones máximas del solucionador numérico? ¿Algo más?

import QuantLib as ql

def calculate_bond_price():

    settlementDays = 0
    faceValue = 100

    issueDate = ql.Date(11, 2, 2020)
    maturityDate = ql.Date(11, 2, 2025)
    tenor = ql.Period(ql.Quarterly)
    calendar = ql.NullCalendar()
    businessConvention = ql.Following
    dateGeneration = ql.DateGeneration.Backward
    monthEnd = False
    schedule = ql.Schedule (issueDate, maturityDate, tenor, calendar, businessConvention, businessConvention, dateGeneration, monthEnd)

    coupon_rate = 0.05
    coupons = [coupon_rate]

    dayCount = ql.Thirty360()

    bond = ql.FixedRateBond(settlementDays, faceValue, schedule, coupons, dayCount)

## manually specify a yield rate to 16 decimal places
## this is the value I expect to get back from bond.bondYield calculation
    yield_rate = 0.057154825761367800000

    bond_price = bond.cleanPrice(yield_rate, dayCount, ql.Simple, ql.Quarterly)
    print(f'PRICE >> calculated={bond_price:20,.16f}')
    # OUTPUTS: PRICE >> calculated= 96.9073930899788536

# feed the calculated bond price back into a bond.bondYield calculation with exact same (dayCount, Simple, Quarterly) inputs
# expect to get back the yield_rate (16 decimal); but only match to 8 decimals
    back_calculate_bond_yield = bond.bondYield(bond_price, dayCount, ql.Simple, ql.Quarterly)
    print(f'YIELD >> calculated={back_calculate_bond_yield:20,.16f} | expected={yield_rate:20,.16f} | diff={back_calculate_bond_yield-yield_rate:20,.16f}')
    # OUTPUTS: YIELD >> calculated=  0.0571548314094543 | expected=  0.0571548257613678 | diff=  0.0000000056480865

if __name__ == '__main__':
    calculate_bond_price()

0 votos

En mi opinión, igualar más allá de 8 decimales parece absolutamente irrelevante desde el punto de vista económico.

3 votos

@skoestlmeier - en la vida real, sí. Pero mostrando una coincidencia "perfecta" será más fácil convencer a Vetting de que mi código hace lo que debe.

6voto

Chris Mc Puntos 31

Yo empezaría diciendo que sí, que es una precisión aceptable.

Sin embargo, la razón por la que no se obtiene el mismo resultado es porque, por defecto, QuantLib tiene accuracy=1.0e-8 y maxEvaluations=100 .

Puedes configurar estos parámetros así:

bond.bondYield(bond_price, dayCount, ql.Simple, ql.Quarterly, ql.Date(), 1.0e-16, 100)

Esto te acercará mucho más...

RENDIMIENTO >> calculado= 0,0571548257613679 | esperado= 0,0571548257613678 | dif= 0,0000000000000001

0 votos

Gracias, ¡eso casi seguro que lo explica! Mañana haré algunas pruebas y anotaré tu respuesta. Parece que esos parámetros de precisión que mencionas están en el manual de referencia ( quantlib.org/reference/ ), pero todavía estoy buscando mi camino por allí y me lo perdí.

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