Une bibliothèque Python pour la finance mathématique.
https://pypi.org/project/QFin/
pip install qfin
QFin est en cours de reconstruction pour exploiter davantage de principes de programmation orientée objet. Plusieurs modules de cette version sont obsolètes ainsi que les solutions aux PDE/SDE (principalement dans le module d'options).
QFin contient désormais un module appelé « stochastique » qui sera en grande partie responsable de l'étalonnage du modèle et de la tarification des options. Un équivalent Cython/C++ de QFin est également en cours de construction, alors restez à l'écoute !
Les équations différentielles stochastiques qui modélisent la dynamique des actifs sous-jacents étendent la classe « StochasticModel » et possèdent une liste de paramètres et de fonctions de modèle pour la tarification des vanilles, le calibrage des surfaces de volatilité implicite et les simulations de Monte Carlo (particulièrement utiles après calibrage pour les options dépendantes du chemin de tarification).
Vous trouverez ci-dessous un exemple trivial utilisant ArithmeticBrownianMotion - importez d'abord le StochasticModel...
à partir de qfin.stochastics importer ArithmeticBrownianMotion
Initialisez ensuite l'objet de classe en paramétrant le modèle...
# abm paramétré par Bachelier vol = .3abm = ArithmeticBrownianMotion([.3])
L'abm peut désormais être utilisé pour fixer le prix d'une option call/put vanille (les prix par défaut sont "CALL") selon l'ensemble de paramètres donné...
# F0 = 101# X = 100# T = 1abm.vanilla_pricing(101, 100, 1, "CALL")# Prix d'appel : 1.0000336233656906
En utilisant la parité call-put, les prix de vente peuvent également être obtenus...
# F0 = 99# X = 100# T = 1abm.vanilla_pricing(99, 100, 1, "PUT")# Prix de vente : 1.0000336233656952
L'étalonnage et la simulation ultérieure du processus sont également disponibles. Notez que certains processus ont une volatilité statique et ne peuvent pas être calibrés sur une surface ivol.
Le mouvement brownien arithmétique peut être simulé comme suit...
# F0 = 100# n (étapes) = 10000# dt = 1/252# T = 1abm.simulate(100, 10000, 1/252, 1)
Les résultats de la simulation ainsi que les caractéristiques de la simulation sont stockés sous le tuple 'path_characteristics' : (paths, n, dt, T).
En utilisant les caractéristiques du chemin stocké, nous pouvons trouver le prix d'un appel comme avant en faisant la moyenne de chaque gain de chemin actualisé (en supposant un processus de stock) avec des taux nuls, nous pouvons éviter la remise comme suit et trouver la valeur de l'option comme suit...
# liste des gains de chemin payoffs = []# option strike priceX = 99# itération à travers les valeurs de chemin du terminal pour identifier le chemin de paiement dans abm.path_characteristics[0] : # ajout du paiement de CALL payoffs.append(max((path[-1] - X ), 0))# valeur de l'option aujourd'huinp.average(payoffs)# Prix d'appel : 1.0008974837343871
Nous pouvons voir ici que le prix simulé converge vers le prix sous forme proche.
La tarification théorique des options pour les actions ne versant pas de dividendes est disponible via les classes BlackScholesCall et BlackScholesPut.
from qfin.options import BlackScholesCallfrom qfin.options import BlackScholesPut# 100 - prix initial de l'actif sous-jacent# .3 - volatilité sous-jacente de l'actif# 100 - prix d'exercice de l'option# 1 - délai jusqu'à l'échéance (annuel)# .01 - taux d'intérêt sans risqueeuro_call = BlackScholesCall(100, .3, 100, 1, .01)euro_put = BlackScholesPut(100, .3, 100, 1, .01)
print('Prix du call : ', euro_call.price)print('Prix du put : ', euro_put.price)
Call price: 12.361726191532611 Put price: 11.366709566449416
Des dérivées partielles de premier ordre et certaines dérivées partielles de second ordre du modèle de tarification de Black-Scholes sont disponibles.
Dérivé partiel de premier ordre par rapport au prix de l'actif sous-jacent.
print('Delta d'appel : ', euro_call.delta)print('Delta de mise : ', euro_put.delta)
Call delta: 0.5596176923702425 Put delta: -0.4403823076297575
Dérivé partiel de second ordre par rapport au prix de l'actif sous-jacent.
print('Appeler gamma : ', euro_call.gamma)print('Put gamma : ', euro_put.gamma)
Call gamma: 0.018653923079008084 Put gamma: 0.018653923079008084
Dérivé partiel de premier ordre par rapport à la volatilité de l'actif sous-jacent.
print('Appeler vega : ', euro_call.vega)print('Mettre vega : ', euro_put.vega)
Call vega: 39.447933090788894 Put vega: 39.447933090788894
Dérivé partiel de premier ordre par rapport à la durée jusqu'à l'échéance.
print('Appeler theta : ', euro_call.theta)print('Put theta : ', euro_put.theta)
Call theta: -6.35319039407325 Put theta: -5.363140560324083
La simulation des chemins d’actifs est disponible à l’aide de processus stochastiques courants.
Modèle standard pour implémenter le mouvement brownien géométrique.
à partir de qfin.simulations import GeographicBrownianMotion# 100 - prix initial de l'actif sous-jacent# 0 - dérive de l'actif sous-jacent (mu)# .3 - volatilité de l'actif sous-jacent# 1/52 - pas de temps (dt)# 1 - délai jusqu'à l'échéance (annum)gbm = GéométriqueBrownianMotion(100, 0, .3, 1/52, 1)
print(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]
Modèle de volatilité stochastique basé sur l'article de Heston (1993).
à partir de qfin.simulations import StochasticVarianceModel# 100 - prix initial de l'actif sous-jacent# 0 - dérive de l'actif sous-jacent (mu)# .01 - taux d'intérêt sans risque# .05 - dividende continu# 2 - taux dans lequel la variance revient au long terme implicite variance# .25 - variance implicite à long terme lorsque le temps tend vers l'infini# -.7 - corrélation du mouvement généré# .3 - Volatilité de la variance# 1/52 - pas de temps (dt)# 1 - délai jusqu'à l'échéance (annum)svm = StochasticVarianceModel(100, 0, .01, .05, 2, .25, -.7, .3, .09, 1/52, 1)
print(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 tarification par simulation des options exotiques est disponible sous les hypothèses associées aux processus stochastiques respectifs. Le mouvement brownien géométrique est la base du processus stochastique utilisé dans chaque simulation de Monte Carlo. Cependant, si des paramètres supplémentaires sont fournis, le processus stochastique approprié sera utilisé pour générer chaque chemin d'échantillonnage.
from qfin.simulations import MonteCarloCallfrom qfin.simulations import MonteCarloPut# 100 - prix d'exercice# 1000 - nombre de trajectoires de prix simulées# .01 - taux d'intérêt sans risque# 100 - prix initial de l'actif sous-jacent# 0 - dérive de l'actif sous-jacent (mu)# .3 - volatilité des actifs sous-jacents# 1/52 - pas de temps (dt)# 1 - délai jusqu'à l'échéance (annum)call_option = MonteCarloCall(100, 1000, .01, 100, 0, .3, 1/52, 1)# Ces paramètres supplémentaires généreront un prix de Monte Carlo basé sur un processus de volatilité stochastique# 2 - taux dans lequel la variance revient au long implicite variance d'exécution# 0,25 - variance implicite à long terme lorsque le temps tend vers l'infini# -0,5 - corrélation du mouvement généré# 0,02 - dividende continu# .3 - Volatilité de la varianceput_option = MonteCarloPut(100, 1000, .01, 100, 0, .3, 1/52, 1, 2, .25, -.5, .02, .3)
imprimer(call_option.price)imprimer(put_option.price)
12.73812121792851 23.195814963576286
from qfin.simulations import MonteCarloBinaryCallfrom qfin.simulations import MonteCarloBinaryPut# 100 - prix d'exercice# 50 - paiement d'option binaire# 1000 - nombre de trajectoires de prix simulées# .01 - taux d'intérêt sans risque# 100 - prix initial de l'actif sous-jacent# 0 - sous-jacent dérive des actifs (mu)# .3 - volatilité des actifs sous-jacents # 1/52 - pas de temps (dt)# 1 - durée jusqu'à l'échéance (annuelle)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)
print(binary_call.price)print(binary_put.price)
22.42462873441866 27.869902820039087
from qfin.simulations import MonteCarloBarrierCallfrom qfin.simulations import MonteCarloBarrierPut# 100 - prix d'exercice# 50 - paiement d'option binaire# 1000 - nombre de trajectoires de prix simulées# .01 - taux d'intérêt sans risque# 100 - prix initial de l'actif sous-jacent# 0 - sous-jacent dérive des actifs (mu)# .3 - volatilité des actifs sous-jacents# 1/52 - pas de temps (dt)# 1 - temps pour maturité (annuelle)# Vrai/Faux - La barrière est haute ou basse# Vrai/Faux - La barrière est entrée ou Outbarrier_call = MonteCarloBarrierCall(100, 1000, 150, .01, 100, 0, .3, 1/52, 1, up =Vrai, out=Vrai)barrier_put = MonteCarloBarrierCall(100, 1000, 95, .01, 100, 0, .3, 1/52, 1, up=False, out=False)
print(binary_call.price)print(binary_put.price)
4.895841997908933 5.565856754630819
from qfin.simulations import MonteCarloAsianCallfrom qfin.simulations import MonteCarloAsianPut# 100 - prix d'exercice# 1000 - nombre de trajectoires de prix simulées# .01 - taux d'intérêt sans risque# 100 - prix initial de l'actif sous-jacent# 0 - dérive de l'actif sous-jacent (mu)# .3 - volatilité des actifs sous-jacents# 1/52 - pas de temps (dt)# 1 - délai jusqu'à l'échéance (annum)asian_call = MonteCarloAsianCall(100, 1000, .01, 100, 0, .3, 1/52, 1)asian_put = MonteCarloAsianPut(100, 1000, .01, 100, 0, .3, 1/52, 1 )
imprimer (asian_call.price) imprimer (asian_put.price)
6.688201154529573 7.123274528125894
from qfin.simulations import MonteCarloExtendibleCallfrom qfin.simulations import MontecarloExtendiblePut# 100 - prix d'exercice# 1000 - nombre de trajectoires de prix simulées# .01 - taux d'intérêt sans risque# 100 - prix initial de l'actif sous-jacent# 0 - dérive de l'actif sous-jacent (mu)# .3 - volatilité des actifs sous-jacents# 1/52 - pas de temps (dt)# 1 - délai jusqu'à l'échéance (annuel)# .5 - extension si hors de l'argent à l'expirationextendible_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)
imprimer (extendible_call.price) imprimer (extendible_put.price)
13.60274931789973 13.20330578685724