Una biblioteca de Python para finanzas matemáticas.
https://pypi.org/project/QFin/
pip install qfin
QFin se está reconstruyendo para aprovechar más principios de programación orientada a objetos. Varios módulos de esta versión están en desuso junto con las soluciones para PDE/SDE (principalmente en el módulo de opciones).
QFin ahora contiene un módulo llamado 'estocástico' que será en gran medida responsable de la calibración del modelo y el precio de las opciones. También se está construyendo un equivalente Cython/C++ a QFin, ¡así que estad atentos!
Las ecuaciones diferenciales estocásticas que modelan la dinámica de los activos subyacentes amplían la clase 'StochasticModel' y poseen una lista de parámetros y funciones del modelo para fijar precios, calibrar superficies de volatilidad implícita y simulaciones de Monte Carlo (particularmente útiles después de la calibración para opciones dependientes de la trayectoria de precios).
A continuación se muestra un ejemplo trivial que utiliza ArithmeticBrownianMotion: primero importe StochasticModel...
de qfin.stochastics importa ArithmeticBrownianMotion
Luego inicialice el objeto de clase parametrizando el modelo...
# abm parametrizado por Bachelier vol = .3abm = ArithmeticBrownianMotion([.3])
El abm ahora se puede usar para fijar el precio de una opción básica de compra/venta (los precios predeterminados son "CALL") bajo el conjunto de parámetros dado...
# F0 = 101# X = 100# T = 1abm.vanilla_pricing(101, 100, 1, "CALL")# Precio de compra: 1.0000336233656906
Utilizando paridad call-put también se pueden obtener precios de venta...
# F0 = 99# X = 100# T = 1abm.vanilla_pricing(99, 100, 1, "PUT")# Precio de venta: 1.0000336233656952
También está disponible la calibración y posterior simulación del proceso; tenga en cuenta que algunos procesos tienen una volatilidad estática y no se pueden calibrar en una superficie ivol.
El movimiento browniano aritmético se puede simular de la siguiente manera...
# F0 = 100# n (pasos) = 10000# dt = 1/252# T = 1abm.simulate(100, 10000, 1/252, 1)
Los resultados de la simulación junto con las características de la simulación se almacenan en la tupla 'path_characteristics': (rutas, n, dt, T).
Usando las características de la ruta almacenada, podemos encontrar el precio de una opción de compra como antes, promediando cada pago de la ruta descontada (suponiendo un proceso de acciones) con tasas cero, podemos evitar el descuento de la siguiente manera y encontrar el valor de la opción de la siguiente manera...
# lista de pagos de rutapayoffs = []# precio de ejercicio de la opciónX = 99# iteración a través de los valores de ruta del terminal para identificar el pago de la ruta en abm.path_characteristics[0]: # agregando el pago de CALL payoffs.append(max((path[-1] - X ), 0))# valor de la opción hoynp.average(pagos)# Precio de compra: 1.0008974837343871
Podemos ver aquí que el precio simulado está convergiendo al precio en forma cercana.
El precio de las opciones teóricas para acciones que no pagan dividendos está disponible a través de las clases BlackScholesCall y BlackScholesPut.
from qfin.options import BlackScholesCallfrom qfin.options import BlackScholesPut# 100 - precio inicial del activo subyacente# .3 - volatilidad subyacente del activo# 100 - precio de ejercicio de la opción# 1 - tiempo hasta el vencimiento (anual)# .01 - tasa de interés libre de riesgoeuro_call = BlackScholesCall(100, .3, 100, 1, .01)euro_put = NegroEscuelasPut(100, .3, 100, 1, .01)
print('Precio de llamada: ', euro_call.price)print('Precio de venta: ', euro_put.price)
Call price: 12.361726191532611 Put price: 11.366709566449416
Están disponibles las derivadas parciales de primer orden y algunas de segundo orden del modelo de fijación de precios de Black-Scholes.
Derivada parcial de primer orden respecto del precio del activo subyacente.
print('Llamar delta: ', euro_call.delta)print('Poner delta: ', euro_put.delta)
Call delta: 0.5596176923702425 Put delta: -0.4403823076297575
Derivada parcial de segundo orden respecto del precio del activo subyacente.
print('Llamar gamma: ', euro_call.gamma)print('Poner gamma: ', euro_put.gamma)
Call gamma: 0.018653923079008084 Put gamma: 0.018653923079008084
Derivada parcial de primer orden con respecto a la volatilidad del activo subyacente.
print('Llamar vega: ', euro_call.vega)print('Poner vega: ', euro_put.vega)
Call vega: 39.447933090788894 Put vega: 39.447933090788894
Derivada parcial de primer orden con respecto al plazo de vencimiento.
print('Llamar theta: ', euro_call.theta)print('Poner theta: ', euro_put.theta)
Call theta: -6.35319039407325 Put theta: -5.363140560324083
La simulación de trayectorias de activos está disponible mediante procesos estocásticos comunes.
Modelo estándar para implementar el movimiento browniano geométrico.
de qfin.simulaciones importar GeométricaBrownianMotion# 100 - precio inicial del activo subyacente# 0 - deriva del activo subyacente (mu)# .3 - volatilidad del activo subyacente# 1/52 - pasos de tiempo (dt)# 1 - tiempo hasta el vencimiento (anual)gbm = Movimiento browniano geométrico (100, 0, 0,3, 1/52, 1)
imprimir(gbm.simulated_path)
[107.0025048205179, 104.82320056538235, 102.53591127422398, 100.20213816642244, 102.04283245358256, 97.75115579923988, 95.19613943526382, 96.9876745495834, 97.46055174410736, 103.93032659279226, 107.36331603194304, 108.95104494118915, 112.42823319947456, 109.06981862825943, 109.10124426285238, 114.71465058375804, 120.00234814086286, 116.91730159923688, 118.67452601825876, 117.89233466917202, 118.93541257993591, 124.36106523035058, 121.26088015675688, 120.53641952983601, 113.73881043255554, 114.91724168548876, 112.94192281337791, 113.55773877160591, 107.49491796151044, 108.0715118831013, 113.01893111071472, 110.39204535739405, 108.63917240906524, 105.8520395233433, 116.2907247951675, 114.07340779267213, 111.06821275009212, 109.65530380775077, 105.78971667172465, 97.75385009989282, 97.84501925249452, 101.90695475825825, 106.0493833583297, 105.48266575656817, 106.62375752876223, 112.39829297429974, 111.22855058562658, 109.89796974828265, 112.78068777325248, 117.80550869036715, 118.4680557054793, 114.33258212280838]
Modelo de volatilidad estocástica basado en el artículo de Heston (1993).
de qfin.simulations import StochasticVarianceModel# 100 - precio inicial del activo subyacente# 0 - deriva del activo subyacente (mu)# .01 - tasa de interés libre de riesgo# .05 - dividendo continuo# 2 - tasa en la que la varianza se revierte al largo plazo implícito varianza# .25 - varianza implícita a largo plazo a medida que el tiempo tiende al infinito# -.7 - correlación del movimiento generado# .3 - Varianza volatilidad# 1/52 - pasos de tiempo (dt)# 1 - tiempo hasta el vencimiento (anual)svm = StochasticVarianceModel(100, 0, .01, .05, 2, .25, -.7, .3, .09, 1 /52, 1)
imprimir(svm.simulated_path)
[98.21311553503577, 100.4491317019877, 89.78475515902066, 89.0169762497475, 90.70468848525869, 86.00821802256675, 80.74984494892573, 89.05033807013137, 88.51410029337134, 78.69736798230346, 81.90948751054125, 83.02502248913251, 83.46375102829755, 85.39018282900138, 78.97401642238059, 78.93505221741903, 81.33268688455111, 85.12156706038515, 79.6351983987908, 84.2375291273571, 82.80206517176038, 89.63659376223292, 89.22438477640516, 89.13899271995662, 94.60123239511816, 91.200165507022, 96.0578905115345, 87.45399399599378, 97.908745925816, 97.93068975065052, 103.32091104292813, 110.58066464778392, 105.21520242908348, 99.4655106985056, 106.74882010453683, 112.0058519886151, 110.20930861932342, 105.11835510815085, 113.59852610881678, 107.13315204738092, 108.36549026977205, 113.49809943785571, 122.67910031073885, 137.70966794451425, 146.13877267735612, 132.9973784430374, 129.75750117504984, 128.7467891695649, 127.13115959080305, 130.47967713110302, 129.84273088908265, 129.6411527208744]
La simulación de precios para opciones exóticas está disponible bajo los supuestos asociados con los respectivos procesos estocásticos. El movimiento browniano geométrico es la base del proceso estocástico subyacente utilizado en cada simulación de Monte Carlo. Sin embargo, si se proporcionan parámetros adicionales, se utilizará el proceso estocástico apropiado para generar cada ruta de muestra.
de qfin.simulations import MonteCarloCallde qfin.simulations import MonteCarloPut# 100 - precio de ejercicio# 1000 - número de trayectorias de precios simuladas# .01 - tasa de interés libre de riesgo# 100 - precio inicial del activo subyacente# 0 - deriva del activo subyacente (mu)# .3 - volatilidad del activo subyacente# 1/52 - pasos de tiempo (dt)# 1 - tiempo hasta el vencimiento (annum)call_option = MonteCarloCall(100, 1000, .01, 100, 0, .3, 1/52, 1)# Estos parámetros adicionales generarán un precio de Monte Carlo basado en un proceso de volatilidad estocástica# 2 - tasa en la que varianza vuelve a la varianza implícita de largo plazo# .25 - varianza implícita de largo plazo cuando el tiempo tiende al infinito# -.5 - correlación de movimiento generado# .02 - dividendo continuo# .3 - Volatilidad de la varianzaput_option = MonteCarloPut(100, 1000, .01, 100, 0, .3, 1/52, 1, 2, .25, -.5, . 02, .3)
imprimir(opción_llamada.precio)imprimir(opción_poner.precio)
12.73812121792851 23.195814963576286
de qfin.simulations import MonteCarloBinaryCallfrom qfin.simulations import MonteCarloBinaryPut# 100 - precio de ejercicio# 50 - pago de opción binaria# 1000 - número de trayectorias de precios simuladas# .01 - tasa de interés libre de riesgo# 100 - precio inicial del activo subyacente# 0 - subyacente deriva de activos (mu)# .3 - volatilidad de los activos subyacentes # 1/52 - pasos de tiempo (dt)# 1 - tiempo hasta el vencimiento (anual)binary_call = MonteCarloBinaryCall(100, 50, 1000, .01, 100, 0, .3, 1/52, 1)binary_put = MonteCarloBinaryPut(100, 50, 1000, .01 , 100, 0, .3, 1/52, 1)
imprimir(binary_call.price)print(binary_put.precio)
22.42462873441866 27.869902820039087
de qfin.simulations import MonteCarloBarrierCallfrom qfin.simulations import MonteCarloBarrierPut# 100 - precio de ejercicio# 50 - pago de opción binaria# 1000 - número de trayectorias de precios simuladas# .01 - tasa de interés libre de riesgo# 100 - precio inicial del activo subyacente# 0 - subyacente deriva de activos (mu)# .3 - volatilidad de los activos subyacentes# 1/52 - pasos de tiempo (dt)# 1 - tiempo hasta el vencimiento (anual)# Verdadero/Falso - La barrera está arriba o abajo# Verdadero/Falso - La barrera está dentro o fuerabarrier_call = MonteCarloBarrierCall(100, 1000, 150, .01, 100, 0, .3 , 1/52, 1, arriba=Verdadero, fuera=Verdadero)barrera_put = MonteCarloBarrierCall(100, 1000, 95, .01, 100, 0, .3, 1/52, 1, arriba=Falso, fuera=Falso)
imprimir(binary_call.price)print(binary_put.precio)
4.895841997908933 5.565856754630819
de qfin.simulations import MonteCarloAsianCall de qfin.simulations import MonteCarloAsianPut# 100 - precio de ejercicio# 1000 - número de trayectorias de precios simuladas# .01 - tasa de interés libre de riesgo# 100 - precio inicial del activo subyacente# 0 - deriva del activo subyacente (mu)# .3 - volatilidad del activo subyacente# 1/52 - pasos de tiempo (dt)# 1 - tiempo hasta el vencimiento (anum)asian_call = MonteCarloAsianCall(100, 1000, .01, 100, 0, .3, 1/52, 1)asian_put = MonteCarloAsianPut(100, 1000, .01, 100, 0, .3, 1/52, 1 )
imprimir(asian_call.price)imprimir(asian_put.price)
6.688201154529573 7.123274528125894
from qfin.simulations import MonteCarloExtendibleCallfrom qfin.simulations import MontecarloExtendiblePut# 100 - precio de ejercicio# 1000 - número de trayectorias de precios simuladas# .01 - tasa de interés libre de riesgo# 100 - precio inicial del activo subyacente# 0 - deriva del activo subyacente (mu)# .3 - volatilidad del activo subyacente# 1/52 - pasos de tiempo (dt)# 1 - tiempo hasta el vencimiento (annum)# .5 - extensión si se queda sin dinero al vencimientoextendible_call = MonteCarloExtendibleCall(100, 1000, .01, 100, 0, .3, 1/52, 1, .5)extendible_put = MonteCarloExtendiblePut(100, 1000, . 01, 100, 0, .3, 1/52, 1, .5)
imprimir(precio_llamada_extendible.precio)imprimir(precio.put_extendible)
13.60274931789973 13.20330578685724