8 votos

Problema al usar QuantLib y Python para calcular el precio y los griegos de una opción americana con dividendos discretos

Estoy teniendo problemas para usar QuantLib con Python para calcular opciones americanas con dividendos discretos. Estoy usando Anaconda, Spyder, Python 3.6 y la versión más reciente de QuantLib. Creé funciones en pricingfunctions.py, que simplifican el proceso de construcción para la fijación de precios de opciones y los griegos basados en el código en esta página web - http://www.bnikolic.co.uk/blog/ql-american-disc-dividend.html:

import QuantLib as ql
#%%
def create_american_process(fecha_valoracion, tasa_rf, spot, ivol):

#establecer calendario y método de cómputo de días
calendario = ql.UnitedStates()
day_counter = ql.ActualActual()

#establecer fecha de evaluación
ql.Settings.instance().evaluation_date = fecha_valoracion 

#establecer tasas y volatilidad
rate_ts = ql.FlatForward(fecha_valoracion, ql.QuoteHandle(tasa_rf), 
                     day_counter)

vol_ts = ql.BlackConstantVol(fecha_valoracion, calendario, 
                         ql.QuoteHandle(ivol), day_counter)  
#crear proceso
proceso = ql.BlackScholesProcess(ql.QuoteHandle(spot),
                             ql.YieldTermStructureHandle(rate_ts),
                             ql.BlackVolTermStructureHandle(vol_ts))
return proceso

#%%
def american_px_greeks(fecha_valoracion, vencimiento, tipo_call_o_put, precio_ejercicio, fechas_dividendos, 
                       valores_dividendos, pasos_tiempo, proceso):

#crear instancia como call o put
if tipo_call_o_put.lower() == 'call':
    tipo = ql.Option.Call 
elif tipo_call_o_put.lower() == 'put':
    tipo = ql.Option.Put 
else:
    raise ValueError("El valor de call_or_put debe ser call o put.")        

#establecer ejercicio y payoff
ejercicio = ql.AmericanExercise(fecha_valoracion, vencimiento)
payoff = ql.PlainVanillaPayoff(tipo, precio_ejercicio)

#crear instancia de opción
opcion = ql.DividendVanillaOption(payoff, ejercicio, fechas_dividendos, valores_dividendos)

#establecer tamaño de malla para el motor de diferencias finitas
puntos_malla = pasos_tiempo - 1                                  

#crear motor
motor = ql.FDDividendAmericanEngine(proceso, pasos_tiempo, puntos_malla)
opcion.setPricingEngine(motor)
return opcion

#%%
def print_option_results(opcion):    
    print("NPV: ", opcion.NPV())
    print("Delta: ", opcion.delta())
    print("Gamma: ", opcion.gamma())
    return None   

Luego ejecuto el siguiente script, pero las salidas para NPV, Delta y Gamma son todos 0.0, lo cual es incorrecto. El NPV debería estar en el rango de 12 a 13, y Delta cerca de 0.50, mientras que Gamma es despreciable. No estoy seguro de qué está mal. Cualquier información sería muy apreciada. Gracias

import QuantLib as ql
from pricingfunctions import create_american_process
from pricingfunctions import american_px_greeks
from pricingfunctions import print_option_results

#%%
#parámetros
volatilidad = 0.25
precio_ejercicio = 100
spot = ql.SimpleQuote(100)
tasa_rf = ql.SimpleQuote(0.01)
ivol = ql.SimpleQuote(volatilidad)
tipo_call_o_put = 'call'
fechas_dividendos = [ql.Date(14, 5, 2014), ql.Date(14, 8, 2014), ql.Date(14, 11, 2014)]
valores_dividendos = [1.0, 1.0, 1.0]
vencimiento = ql.Date(15, 1, 2016)
fecha_valoracion = ql.Date(17, 4, 2014)
pasos_tiempo = 456 

proceso_test = create_american_process(fecha_valoracion, tasa_rf, spot, ivol)
opcion_test = american_px_greeks(fecha_valoracion, vencimiento, tipo_call_o_put, precio_ejercicio, fechas_dividendos, valores_dividendos, pasos_tiempo, proceso_test)
print_option_results(opcion_test)

1 votos

Es posible que desees borrar stackoverflow.com/questions/47660745/python-quantlib si estás haciendo la pregunta aquí.

2 votos

"Estoy usando Anaconda, Spyder, Python" ¡Estoy seguro de que la Víbora y la Tarántula están a la vuelta de la esquina!

0 votos

Recibo un error al usar esto AttributeError: No se ha definido ningún constructor No puedo llamar a ql.FDDividendAmericanEngine

8voto

Brad Tutterow Puntos 5628

No estás estableciendo la fecha de evaluación global. Si no lo haces, estarás en diciembre de 2017 y tu opción habrá vencido hace un buen tiempo.

Agregando

ql.Settings.instance().evaluationDate = valuation_date

antes de hacer los cálculos te dará los resultados esperados.

0 votos

Gracias muchas gracias. Me di cuenta del error. En lugar de usar evaluationDate, utilicé evaluation_date. Un error sutil pero malo. Aprecio la respuesta Luigi. ¡Saludos!

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