├── README.md
├── European Options
├── Merton Jump Diffusion
│ ├── merton_jump_mc.ipynb
│ ├── merton_jump_analytical.ipynb
│ └── merton_jump_fourier.ipynb
├── Heston
│ └── heston_analytical.ipynb
├── Black Scholes
│ └── bs_fourier_pricing.ipynb
└── Binomial model
│ └── binomial.ipynb
├── Implied Volatility
├── aapl_put_data.csv
├── aapl_call_data.csv
└── implied_vol_newton.ipynb
└── Exotics
└── barrier_pricing.ipynb
/README.md:
--------------------------------------------------------------------------------
1 | # Option-Pricing
2 |
3 | Pricing of options with various models (Black-Scholes, Heston, Merton jump diffusion, etc) and methods (Monte Carlo, finite difference, Fourier).
4 |
5 | # European Options
6 |
7 | This folder contains notebooks with for the pricing of European options with the following models:
8 |
9 | - Black-Scholes,
10 | - Merton jump diffusion.
11 |
12 | ## Black-Scholes
13 |
14 | Pricing of European options according to the Black-Scholes model using the following methods:
15 |
16 | - Analytical solution,
17 | - Monte Carlo,
18 | - Finite difference (explicit scheme),
19 | - Fourier transform.
20 |
21 | ## Merton Jump Diffusion
22 |
23 | Pricing of European options according to the Merton jump diffusion model using the following methods:
24 |
25 | - Analytical solution,
26 | - Monte Carlo,
27 | - Fourier transform.
28 |
29 | ## Heston model
30 |
31 | Pricing of European options according to the Heston stochastic volatility model using the following methods:
32 |
33 | - Analytical solution
34 | - Monte Carlo
35 |
36 | ## Binomial model
37 |
38 | Pricing of European options according to the binomial model (Cox, Ross, Rubinstein).
39 |
40 | # Exotics
41 |
42 | Pricing of the following exotic options:
43 |
44 | - Barrier (discrete and continuous monitoring, analytical and Monte Carlo).
45 |
46 | ## Barrier options
47 |
48 | Pricing of barrier options (discretely and continuously monitored) using the following methods:
49 |
50 | - Analytical solution,
51 | - Monte Carlo.
52 |
53 | # Implied Volatility
54 |
55 | Computation of implied volatility for European options using the Newton-Raphson method and the Black-Scholes model. Plotting of the volatility smile.
56 |
--------------------------------------------------------------------------------
/European Options/Merton Jump Diffusion/merton_jump_mc.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "numerical-mixer",
6 | "metadata": {},
7 | "source": [
8 | "# Merton Jump Diffusion: Option Pricing with Monte Carlo\n",
9 | "\n",
10 | "In this notebook, we show how to use Monte Carlo simulation to price european options with a Merton jump diffusion process. The implementation is very similar to the one using the Black-Scholes model and the Euler-Maruyama scheme. The key differences are the additional term added to the risk-neutral drift and the normal compound Poisson process added to the geometric Brownian motion."
11 | ]
12 | },
13 | {
14 | "cell_type": "code",
15 | "execution_count": 1,
16 | "id": "recent-pension",
17 | "metadata": {},
18 | "outputs": [
19 | {
20 | "name": "stdout",
21 | "output_type": "stream",
22 | "text": [
23 | "Call price: 0.1362\n",
24 | "Put price: 0.2023\n"
25 | ]
26 | }
27 | ],
28 | "source": [
29 | "import numpy as np\n",
30 | "\n",
31 | "# Market parameters\n",
32 | "T = 1 # maturity\n",
33 | "S0 = 1 # spot price\n",
34 | "K = 1.1 # strike price\n",
35 | "r = 0.05 # risk-free interest rate\n",
36 | "q = 0.02 # dividend rate\n",
37 | "\n",
38 | "# Model parameter\n",
39 | "sigma = 0.4 # volatility\n",
40 | "\n",
41 | "# Model parameters of the jump part (NCPP)\n",
42 | "mu_j = -0.1\n",
43 | "sigma_j = 0.15\n",
44 | "lmbda = 0.5\n",
45 | "\n",
46 | "# Risk-neutral measure\n",
47 | "muRN = r-q-0.5*sigma**2 - lmbda*(np.exp(mu_j+0.5*sigma_j**2)-1) # drift\n",
48 | "\n",
49 | "# Monte Carlo parameters; npaths = nblocks*nsample\n",
50 | "nblocks = 20000 # number of blocks\n",
51 | "nsample = 10000 # number of samples per block\n",
52 | "\n",
53 | "# Initialize arrays\n",
54 | "Vc_list = np.zeros(nblocks) # call array\n",
55 | "Vp_list = np.zeros(nblocks) # put array\n",
56 | "\n",
57 | "# Monte Carlo\n",
58 | "for i in range(nblocks):\n",
59 | " A = muRN*T + sigma*np.sqrt(T) * np.random.normal(size=(1, nsample))\n",
60 | " N = np.random.poisson(lmbda, size=(1, nsample))\n",
61 | " J = mu_j* N + sigma_j * np.sqrt(N) * np.random.normal(size=(1, nsample))\n",
62 | " X = A+J\n",
63 | " S = S0*np.exp(X)\n",
64 | " Vc_list[i] = np.exp(-r*T)*np.mean(np.maximum(S - K, 0))\n",
65 | " Vp_list[i] = np.exp(-r*T)*np.mean(np.maximum(K - S, 0))\n",
66 | "\n",
67 | "# Final call and put values\n",
68 | "Vc = np.mean(Vc_list)\n",
69 | "Vp = np.mean(Vp_list)\n",
70 | "\n",
71 | "print('Call price: ' + str(round(Vc, 4)))\n",
72 | "print('Put price: ' + str(round(Vp, 4)))"
73 | ]
74 | },
75 | {
76 | "cell_type": "code",
77 | "execution_count": null,
78 | "id": "subsequent-buffer",
79 | "metadata": {},
80 | "outputs": [],
81 | "source": []
82 | }
83 | ],
84 | "metadata": {
85 | "authors": [
86 | {
87 | "email": "robin.guilliou@gmail.com",
88 | "name": "Robin Guilliou"
89 | }
90 | ],
91 | "kernelspec": {
92 | "display_name": "Python 3 (ipykernel)",
93 | "language": "python",
94 | "name": "python3"
95 | },
96 | "language_info": {
97 | "codemirror_mode": {
98 | "name": "ipython",
99 | "version": 3
100 | },
101 | "file_extension": ".py",
102 | "mimetype": "text/x-python",
103 | "name": "python",
104 | "nbconvert_exporter": "python",
105 | "pygments_lexer": "ipython3",
106 | "version": "3.7.11"
107 | },
108 | "latex_envs": {
109 | "LaTeX_envs_menu_present": true,
110 | "autoclose": false,
111 | "autocomplete": true,
112 | "bibliofile": "biblio.bib",
113 | "cite_by": "apalike",
114 | "current_citInitial": 1,
115 | "eqLabelWithNumbers": true,
116 | "eqNumInitial": 1,
117 | "hotkeys": {
118 | "equation": "Ctrl-E",
119 | "itemize": "Ctrl-I"
120 | },
121 | "labels_anchors": false,
122 | "latex_user_defs": false,
123 | "report_style_numbering": false,
124 | "user_envs_cfg": false
125 | },
126 | "toc": {
127 | "base_numbering": 1,
128 | "nav_menu": {},
129 | "number_sections": true,
130 | "sideBar": true,
131 | "skip_h1_title": false,
132 | "title_cell": "Table of Contents",
133 | "title_sidebar": "Contents",
134 | "toc_cell": false,
135 | "toc_position": {},
136 | "toc_section_display": true,
137 | "toc_window_display": false
138 | },
139 | "varInspector": {
140 | "cols": {
141 | "lenName": 16,
142 | "lenType": 16,
143 | "lenVar": 40
144 | },
145 | "kernels_config": {
146 | "python": {
147 | "delete_cmd_postfix": "",
148 | "delete_cmd_prefix": "del ",
149 | "library": "var_list.py",
150 | "varRefreshCmd": "print(var_dic_list())"
151 | },
152 | "r": {
153 | "delete_cmd_postfix": ") ",
154 | "delete_cmd_prefix": "rm(",
155 | "library": "var_list.r",
156 | "varRefreshCmd": "cat(var_dic_list()) "
157 | }
158 | },
159 | "types_to_exclude": [
160 | "module",
161 | "function",
162 | "builtin_function_or_method",
163 | "instance",
164 | "_Feature"
165 | ],
166 | "window_display": false
167 | }
168 | },
169 | "nbformat": 4,
170 | "nbformat_minor": 5
171 | }
172 |
--------------------------------------------------------------------------------
/European Options/Merton Jump Diffusion/merton_jump_analytical.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "4195a462",
6 | "metadata": {},
7 | "source": [
8 | "# Merton Jump Diffusion: Analytical solution\n",
9 | "\n",
10 | "In this notebook, we show how to price European options with the analytical solution of the Merton jump diffusion model.\n",
11 | "\n",
12 | "The value of an European option under the Merton jump diffusion model is given by\n",
13 | "\n",
14 | "\\begin{equation}\n",
15 | " V_{MJD} = \\sum_{k = 1}^{\\infty} \\frac{\\exp \\left(- \\lambda T e^{\\mu_j + \\frac{1}{2}\\sigma_j^2} \\right) \\left( \\lambda T e^{\\mu_j + \\frac{1}{2}\\sigma_j^2} \\right)^k }{k!} V_{BS}(S, K, T, \\sigma_k, r_k, q)\n",
16 | "\\end{equation}\n",
17 | "\n",
18 | "where $S$ is the stock price, $K$ is the strike price, $T$ is the time to maturity, $q$ is the dividend rate, $V_{BS}(\\Theta)$ is the value of the option under the Black-Scoles model with parameters $\\Theta$, $\\lambda$ is the rate of arrival of the jumps, $\\mu_j$ is the mean of the jumps and $\\sigma_j$ is the standard deviation of the jumps. The volatility to plug in the Black-Scholes model at each $k$, $\\sigma_k$, is given by\n",
19 | "\n",
20 | "\\begin{equation}\n",
21 | " \\sigma_k = \\sqrt{\\sigma^2 + k \\frac{\\sigma_j^2}{T}}\n",
22 | "\\end{equation}\n",
23 | "\n",
24 | "where $\\sigma$ is the stock volatility. The risk-free rate to plug in the Black-Scholes model at each $k$, $r_k$, is given by\n",
25 | "\n",
26 | "\\begin{equation}\n",
27 | " r_k = r - \\lambda(e^{\\mu_j + \\frac{1}{2}\\sigma_j^2} - 1) + \\frac{k \\left( \\mu_j + \\frac{1}{2}\\sigma_j^2 \\right)}{T} \n",
28 | "\\end{equation}\n",
29 | "\n",
30 | "where $r$ is the risk-free rate.\n",
31 | "\n",
32 | "Of course, when implementing the solution, we truncate the infinite summation. As $k$ increases, the components to be added become smaller and smaller (with the factorial in the denominator). Therefore, we can use a maximum value of $k$ high enough for the additional components to be negligible. Alternatively, we can select a threshold below which additional components of the sum are not added. \n",
33 | "\n",
34 | "Let's implement the function."
35 | ]
36 | },
37 | {
38 | "cell_type": "code",
39 | "execution_count": 1,
40 | "id": "bd2409fb",
41 | "metadata": {},
42 | "outputs": [],
43 | "source": [
44 | "import numpy as np\n",
45 | "from scipy.stats import norm\n",
46 | "\n",
47 | "# Function for analytical Black-Scholes price\n",
48 | "def bs_price(S, K, T, r, q, sigma, call=True):\n",
49 | " d1 = (np.log(S/K) + (r - q + sigma**2/2)*T) / (sigma*np.sqrt(T))\n",
50 | " d2 = d1 - sigma * np.sqrt(T)\n",
51 | " if call:\n",
52 | " return S * np.exp(-q*T) * norm.cdf(d1) - K * np.exp(-r*T)* norm.cdf(d2)\n",
53 | " else:\n",
54 | " return K * np.exp(-r*T) * norm.cdf(-d2) - S * np.exp(-q*T) * norm.cdf(-d1) \n",
55 | "\n",
56 | "# Function for analytical Merton jump diffusion price\n",
57 | "def merton_jump_analytical(S, K, T, r, q, sigma, mu_j , sigma_j, lam, call=True, max_iter=100, stop_cond=1e-15):\n",
58 | " V = 0\n",
59 | " for k in range(max_iter):\n",
60 | " r_k = r - lam*(np.exp(mu_j + 0.5*sigma_j**2)-1) + (k*(mu_j + 0.5*sigma_j**2)) / T\n",
61 | " sigma_k = np.sqrt( sigma**2 + (k* sigma_j**2) / T)\n",
62 | " sum_k = (np.exp(-(np.exp(mu_j + 0.5*sigma_j**2))*lam*T) \\\n",
63 | " * ((np.exp(mu_j + 0.5*sigma_j**2))*lam*T)**k / (np.math.factorial(k))) \\\n",
64 | " * bs_price(S, K, T, r_k, q, sigma_k, call)\n",
65 | " V += sum_k\n",
66 | " if sum_k < stop_cond: # if the last added component is below the threshold, return the current sum\n",
67 | " return V\n",
68 | " return V # return the value of the option when the maximum value of k is reached"
69 | ]
70 | },
71 | {
72 | "cell_type": "markdown",
73 | "id": "5ac0a2c4",
74 | "metadata": {},
75 | "source": [
76 | "Now, let's define some parameters and compute the call and put values."
77 | ]
78 | },
79 | {
80 | "cell_type": "code",
81 | "execution_count": 2,
82 | "id": "e63b74e9",
83 | "metadata": {},
84 | "outputs": [
85 | {
86 | "name": "stdout",
87 | "output_type": "stream",
88 | "text": [
89 | "Call price: 0.1362\n",
90 | "Put price: 0.2023\n"
91 | ]
92 | }
93 | ],
94 | "source": [
95 | "# Market parameters\n",
96 | "T = 1 # maturity\n",
97 | "S0 = 1 # spot price\n",
98 | "K = 1.1 # strike price\n",
99 | "r = 0.05 # risk-free interest rate\n",
100 | "q = 0.02 # dividend rate\n",
101 | "\n",
102 | "# Model parameter\n",
103 | "sigma = 0.4 # volatility\n",
104 | "\n",
105 | "# Model parameters for the jump part\n",
106 | "mu_j = -0.1\n",
107 | "sigma_j = 0.15\n",
108 | "lmbda = 0.5\n",
109 | "\n",
110 | "# Call value\n",
111 | "Vc = merton_jump_analytical(S0, K, T, r, q, sigma, mu_j, sigma_j, lmbda, call=True, max_iter=100, stop_cond=1e-15)\n",
112 | "\n",
113 | "# Put value\n",
114 | "Vp = merton_jump_analytical(S0, K, T, r, q, sigma, mu_j, sigma_j, lmbda, call=False, max_iter=100, stop_cond=1e-15)\n",
115 | "\n",
116 | "print('Call price: ' + str(round(Vc, 4)))\n",
117 | "print('Put price: ' + str(round(Vp, 4)))"
118 | ]
119 | },
120 | {
121 | "cell_type": "code",
122 | "execution_count": null,
123 | "id": "0409092b",
124 | "metadata": {},
125 | "outputs": [],
126 | "source": []
127 | }
128 | ],
129 | "metadata": {
130 | "authors": [
131 | {
132 | "email": "robin.guilliou@gmail.com",
133 | "name": "Robin Guilliou"
134 | }
135 | ],
136 | "kernelspec": {
137 | "display_name": "Python 3 (ipykernel)",
138 | "language": "python",
139 | "name": "python3"
140 | },
141 | "language_info": {
142 | "codemirror_mode": {
143 | "name": "ipython",
144 | "version": 3
145 | },
146 | "file_extension": ".py",
147 | "mimetype": "text/x-python",
148 | "name": "python",
149 | "nbconvert_exporter": "python",
150 | "pygments_lexer": "ipython3",
151 | "version": "3.7.11"
152 | },
153 | "latex_envs": {
154 | "LaTeX_envs_menu_present": true,
155 | "autoclose": false,
156 | "autocomplete": true,
157 | "bibliofile": "biblio.bib",
158 | "cite_by": "apalike",
159 | "current_citInitial": 1,
160 | "eqLabelWithNumbers": true,
161 | "eqNumInitial": 1,
162 | "hotkeys": {
163 | "equation": "Ctrl-E",
164 | "itemize": "Ctrl-I"
165 | },
166 | "labels_anchors": false,
167 | "latex_user_defs": false,
168 | "report_style_numbering": false,
169 | "user_envs_cfg": false
170 | },
171 | "toc": {
172 | "base_numbering": 1,
173 | "nav_menu": {},
174 | "number_sections": true,
175 | "sideBar": true,
176 | "skip_h1_title": true,
177 | "title_cell": "Table of Contents",
178 | "title_sidebar": "Contents",
179 | "toc_cell": false,
180 | "toc_position": {},
181 | "toc_section_display": true,
182 | "toc_window_display": false
183 | }
184 | },
185 | "nbformat": 4,
186 | "nbformat_minor": 5
187 | }
188 |
--------------------------------------------------------------------------------
/European Options/Heston/heston_analytical.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "fae42e73",
6 | "metadata": {},
7 | "source": [
8 | "# Heston model: Analytical solution\n",
9 | "\n",
10 | "In this notebook, we show how to price European options with the Heston stochastic volatility model.\n",
11 | "\n",
12 | "The Heston model is defined by the following system of stochastic differential equations where the stock price follows a geometric Brownian motion and its variance follows a Cox-Ingersoll-Ross (CIR) process,\n",
13 | "\n",
14 | "\\begin{align}\n",
15 | "\t&dS_t = \\mu S_t dt + \\sqrt{v_t} S_t dW_t^{(1)} \\\\\n",
16 | "\t&dv_t = \\kappa ( \\theta - v_t ) dt + \\sigma \\sqrt{v_t} dW_t^{(2)} \\\\\n",
17 | "\t&dW_t^{(1)} dW_t^{(2)} = \\rho dt\n",
18 | "\\end{align}\n",
19 | "\n",
20 | "where $S_t$ is the underlying stock price, $v_t$ is its variance, $\\mu$ is the expected return, $\\kappa$ is the mean-reversion rate, $\\theta$ is the long-term variance, $\\sigma$ is the volatility of volatility, $W_t$ is a Wiener process and $\\rho$ is the correlation coefficient between the Brownian motions. There are also two initial parameters, $S_0$ and $v_0$ which are non-negative.\n",
21 | "\n",
22 | "The process $v_t$ is strictly positive if the Feller condition is satisfied. It is given by\n",
23 | "\n",
24 | "\\begin{equation}\n",
25 | " 2 \\kappa \\theta > \\sigma^2.\n",
26 | "\\end{equation}\n",
27 | "\n",
28 | "The Heston model yields a semi-closed form solution for pricing European equity options. The price for a European call option, $C(S, v, t)$, at time $t$ with time to maturity $\\tau = T - t$ and strike $K$ is given by\n",
29 | "\n",
30 | "\\begin{equation}\n",
31 | "\tC(S, v, t) = S_t e^{-q \\tau} P_1 - K e^{-r \\tau} P_2 \n",
32 | "\\end{equation}\n",
33 | "\n",
34 | "where $q$ is the dividend rate and $r$ is the interest rate and $P_j, j = \\{1, 2\\}$ are risk-neutral probabilities obtained by inverting the characteristic function $f_j$ (given below). Hence,\n",
35 | "\n",
36 | "\\begin{equation}\n",
37 | " P_j = \\frac{1}{2} + \\frac{1}{\\pi} \\int_0^{\\infty} \\operatorname{Re} \\left[ \\frac{e^{-i \\phi \\ln(K)}f_j}{i \\phi} \\right] d\\phi\n",
38 | "\\end{equation}\n",
39 | "\n",
40 | "where\n",
41 | "\n",
42 | "\\begin{align}\n",
43 | "\t&f_j = \\exp(C_j + D_j v_t + i \\phi \\ln S_t) \\\\\n",
44 | "\t&C_j = (r - q) \\phi i \\tau + \\frac{\\kappa \\theta}{\\sigma^2} \\left[ (b_j - \\rho \\sigma \\phi i + d_j) \\tau - 2 \\ln \\left( \\frac{1 - g_j e^{d_j \\tau}}{1 - g_j} \t\\right) \\right] \\\\[5pt]\n",
45 | "\t&D_j = \\frac{b_j - \\rho \\sigma \\phi i + d_j}{\\sigma^2} \\left( \\frac{1 - e^{d_j \\tau}}{1 - g_j e^{d_j \\tau}} \\right) \\\\\n",
46 | "\t&g_j = \\frac{b_j - \\rho \\sigma \\phi i + d_j}{b_j - \\rho \\sigma \\phi i - d_j} \\\\\n",
47 | "\t&d_j = \\sqrt{(\\rho \\sigma \\phi i)^2 - \\sigma^2 ( 2 u_j \\phi i - \\phi^2 )}\n",
48 | "\\end{align}\n",
49 | "\n",
50 | "In the above expressions, $i = \\sqrt{-1}$ is the imaginary unit, $u_1 = \\frac{1}{2}$, $u_2 = - \\frac{1}{2}$, $b_1 = \\kappa + \\lambda - \\rho \\sigma$ and $b_2 = \\kappa + \\lambda$. The parameter $\\lambda$ is the market price of volatility risk. \n",
51 | "\n",
52 | "First, let's implement the function to price call options. Note that we price the option at time $t = 0$, therefore, $\\tau = T$."
53 | ]
54 | },
55 | {
56 | "cell_type": "code",
57 | "execution_count": 1,
58 | "id": "9ee566ed",
59 | "metadata": {},
60 | "outputs": [],
61 | "source": [
62 | "import numpy as np\n",
63 | "from scipy.integrate import quad\n",
64 | "\n",
65 | "# Heston call price\n",
66 | "def Heston_call_price(S0, v0, K, T, r, q, kappa, theta, sigma, rho, lmbda):\n",
67 | " p1 = p_Heston(S0, v0, K, r, q, T, kappa, theta, sigma, rho, lmbda, 1)\n",
68 | " p2 = p_Heston(S0, v0, K, r, q, T, kappa, theta, sigma, rho, lmbda, 2)\n",
69 | " return S0 * np.exp(-q*T) * p1 - K * np.exp(-r*T) * p2\n",
70 | "\n",
71 | "# Heston probability\n",
72 | "def p_Heston(S0, v0, K, r, q, T, kappa, theta, sigma, rho, lmbda, j):\n",
73 | " integrand = lambda phi: np.real(np.exp(-1j * phi * np.log(K)) \\\n",
74 | " * f_Heston(phi, S0, v0, T, r, q, kappa, theta, sigma, rho, lmbda, j) \\\n",
75 | " / (1j * phi)) \n",
76 | " integral = quad(integrand, 0, 100)[0]\n",
77 | " return 0.5 + (1 / np.pi) * integral\n",
78 | "\n",
79 | "# Heston characteristic function\n",
80 | "def f_Heston(phi, S0, v0, T, r, q, kappa, theta, sigma, rho, lmbda, j):\n",
81 | " \n",
82 | " if j == 1:\n",
83 | " u = 0.5\n",
84 | " b = kappa + lmbda - rho * sigma\n",
85 | " else:\n",
86 | " u = -0.5\n",
87 | " b = kappa + lmbda\n",
88 | " \n",
89 | " a = kappa * theta\n",
90 | " d = np.sqrt((rho * sigma * phi * 1j - b)**2 - sigma**2 * (2 * u * phi * 1j - phi**2))\n",
91 | " g = (b - rho * sigma * phi * 1j + d) / (b - rho * sigma * phi * 1j - d)\n",
92 | " C = (r - q) * phi * 1j * T + (a / sigma**2) \\\n",
93 | " * ((b - rho * sigma * phi * 1j + d) * T - 2 * np.log((1 - g * np.exp(d * T))/(1 - g)))\n",
94 | " D = (b - rho * sigma * phi * 1j + d) / sigma**2 * ((1 - np.exp(d * T)) / (1 - g * np.exp(d * T)))\n",
95 | " \n",
96 | " return np.exp(C + D * v0 + 1j * phi * np.log(S0))"
97 | ]
98 | },
99 | {
100 | "cell_type": "markdown",
101 | "id": "a51aeca1",
102 | "metadata": {},
103 | "source": [
104 | "Now, let's define some parameters and price a call option. We also price the corresponding put using the put-call parity, i.e.,\n",
105 | "\n",
106 | "\\begin{equation}\n",
107 | " V_p = V_c + Ke^{-rT} - S_0e^{-qT}\n",
108 | "\\end{equation}\n",
109 | "\n",
110 | "where $V_p$ is the price of the put option and $V_c$ is the price of the call option."
111 | ]
112 | },
113 | {
114 | "cell_type": "code",
115 | "execution_count": 2,
116 | "id": "c85ce861",
117 | "metadata": {},
118 | "outputs": [
119 | {
120 | "name": "stdout",
121 | "output_type": "stream",
122 | "text": [
123 | "Call price: 7.78614\n",
124 | "Put price: 1.91469\n"
125 | ]
126 | }
127 | ],
128 | "source": [
129 | "# Parameters\n",
130 | "T = 1 # maturity\n",
131 | "S0 = 55 # spot price\n",
132 | "K = 50 # strike price\n",
133 | "r = 0.04 # risk-free interest rate\n",
134 | "q = 0.02 # dividend rate\n",
135 | "v0 = 0.04 # initial variance\n",
136 | "rho = -0.7 # correlation between Brownian motions\n",
137 | "kappa = 2 # mean reversion rate\n",
138 | "theta = 0.04 # Long term mean of variance\n",
139 | "sigma = 0.3 # volatility of volatility\n",
140 | "lmbda = 0 # market price of volatility risk\n",
141 | "\n",
142 | "# Option values\n",
143 | "Vc = Heston_call_price(S0, v0, K, T, r, q, kappa, theta, sigma, rho, lmbda) # call\n",
144 | "Vp = Vc + K*np.exp(-r*T) - S0*np.exp(-q*T) # put with put-call parity\n",
145 | "\n",
146 | "print('Call price: ' + str(round(Vc, 5)))\n",
147 | "print('Put price: ' + str(round(Vp, 5)))"
148 | ]
149 | },
150 | {
151 | "cell_type": "code",
152 | "execution_count": null,
153 | "id": "b1bb2579",
154 | "metadata": {},
155 | "outputs": [],
156 | "source": []
157 | }
158 | ],
159 | "metadata": {
160 | "authors": [
161 | {
162 | "email": "robin.guilliou@gmail.com",
163 | "name": "Robin Guilliou"
164 | }
165 | ],
166 | "kernelspec": {
167 | "display_name": "Python 3 (ipykernel)",
168 | "language": "python",
169 | "name": "python3"
170 | },
171 | "language_info": {
172 | "codemirror_mode": {
173 | "name": "ipython",
174 | "version": 3
175 | },
176 | "file_extension": ".py",
177 | "mimetype": "text/x-python",
178 | "name": "python",
179 | "nbconvert_exporter": "python",
180 | "pygments_lexer": "ipython3",
181 | "version": "3.7.11"
182 | },
183 | "latex_envs": {
184 | "LaTeX_envs_menu_present": true,
185 | "autoclose": false,
186 | "autocomplete": true,
187 | "bibliofile": "biblio.bib",
188 | "cite_by": "apalike",
189 | "current_citInitial": 1,
190 | "eqLabelWithNumbers": true,
191 | "eqNumInitial": 1,
192 | "hotkeys": {
193 | "equation": "Ctrl-E",
194 | "itemize": "Ctrl-I"
195 | },
196 | "labels_anchors": false,
197 | "latex_user_defs": false,
198 | "report_style_numbering": false,
199 | "user_envs_cfg": false
200 | },
201 | "toc": {
202 | "base_numbering": 1,
203 | "nav_menu": {},
204 | "number_sections": true,
205 | "sideBar": true,
206 | "skip_h1_title": true,
207 | "title_cell": "Table of Contents",
208 | "title_sidebar": "Contents",
209 | "toc_cell": false,
210 | "toc_position": {},
211 | "toc_section_display": true,
212 | "toc_window_display": false
213 | },
214 | "varInspector": {
215 | "cols": {
216 | "lenName": 16,
217 | "lenType": 16,
218 | "lenVar": 40
219 | },
220 | "kernels_config": {
221 | "python": {
222 | "delete_cmd_postfix": "",
223 | "delete_cmd_prefix": "del ",
224 | "library": "var_list.py",
225 | "varRefreshCmd": "print(var_dic_list())"
226 | },
227 | "r": {
228 | "delete_cmd_postfix": ") ",
229 | "delete_cmd_prefix": "rm(",
230 | "library": "var_list.r",
231 | "varRefreshCmd": "cat(var_dic_list()) "
232 | }
233 | },
234 | "types_to_exclude": [
235 | "module",
236 | "function",
237 | "builtin_function_or_method",
238 | "instance",
239 | "_Feature"
240 | ],
241 | "window_display": false
242 | }
243 | },
244 | "nbformat": 4,
245 | "nbformat_minor": 5
246 | }
247 |
--------------------------------------------------------------------------------
/Implied Volatility/aapl_put_data.csv:
--------------------------------------------------------------------------------
1 | ,contractSymbol,lastTradeDate,strike,lastPrice,bid,ask,change,percentChange,volume,openInterest,impliedVolatility,inTheMoney,contractSize,currency
2 | 0,AAPL220916P00040000,2021-10-26 18:06:03,40.0,0.11,0.09,0.13,0.0,0.0,1.0,1041.0,0.5937540625000001,False,REGULAR,USD
3 | 1,AAPL220916P00041250,2021-10-27 18:46:40,41.25,0.15,0.06,0.17,0.0,0.0,2.0,319.0,0.5839885351562499,False,REGULAR,USD
4 | 2,AAPL220916P00042500,2021-11-03 13:48:56,42.5,0.15,0.09,0.16,0.0,0.0,4.0,0.0,0.57617611328125,False,REGULAR,USD
5 | 3,AAPL220916P00043750,2021-10-18 13:30:21,43.75,0.22,0.09,0.2,0.0,0.0,2.0,276.0,0.5742230078125,False,REGULAR,USD
6 | 4,AAPL220916P00045000,2021-10-20 19:18:32,45.0,0.22,0.11,0.21,0.0,0.0,1.0,1418.0,0.569340244140625,False,REGULAR,USD
7 | 5,AAPL220916P00046250,2021-10-27 14:50:34,46.25,0.2,0.12,0.23,0.0,0.0,2.0,5106.0,0.5634809277343751,False,REGULAR,USD
8 | 6,AAPL220916P00047500,2021-10-27 14:49:55,47.5,0.18,0.14,0.25,0.0,0.0,1.0,4001.0,0.559574716796875,False,REGULAR,USD
9 | 7,AAPL220916P00048750,2021-10-27 14:49:50,48.75,0.25,0.16,0.26,0.0,0.0,4.0,173.0,0.5537154003906251,False,REGULAR,USD
10 | 8,AAPL220916P00050000,2021-10-28 13:58:21,50.0,0.21,0.17,0.27,0.0,0.0,30.0,1233.0,0.5449264257812501,False,REGULAR,USD
11 | 9,AAPL220916P00052500,2021-11-02 15:11:08,52.5,0.27,0.21,0.0,0.0,0.0,4.0,1641.0,0.2500075,False,REGULAR,USD
12 | 10,AAPL220916P00055000,2021-10-22 19:54:20,55.0,0.38,0.25,0.35,0.0,0.0,49.0,1331.0,0.5239305419921875,False,REGULAR,USD
13 | 11,AAPL220916P00057500,2021-11-02 14:19:25,57.5,0.33,0.29,0.39,0.0,0.0,8.0,696.0,0.5122119091796875,False,REGULAR,USD
14 | 12,AAPL220916P00060000,2021-10-22 18:35:22,60.0,0.49,0.33,0.43,0.0,0.0,7.0,491.0,0.500005,False,REGULAR,USD
15 | 13,AAPL220916P00062500,2021-10-28 14:07:01,62.5,0.49,0.38,0.48,0.0,0.0,4.0,1573.0,0.4985401708984375,False,REGULAR,USD
16 | 14,AAPL220916P00065000,2021-11-01 18:28:27,65.0,0.51,0.44,0.5,0.0,0.0,2.0,581.0,0.4819387744140625,False,REGULAR,USD
17 | 15,AAPL220916P00067500,2021-10-18 14:35:42,67.5,0.73,0.5,0.57,0.0,0.0,22.0,594.0,0.47290566162109376,False,REGULAR,USD
18 | 16,AAPL220916P00070000,2021-10-28 15:15:45,70.0,0.62,0.56,0.64,0.0,0.0,5.0,1656.0,0.4633842724609375,False,REGULAR,USD
19 | 17,AAPL220916P00072500,2021-11-03 17:46:42,72.5,0.64,0.62,0.7,0.0,0.0,8.0,840.0,0.4519097778320313,False,REGULAR,USD
20 | 18,AAPL220916P00075000,2021-11-03 19:29:03,75.0,0.72,0.69,0.77,0.0,0.0,4.0,1775.0,0.44165597412109375,False,REGULAR,USD
21 | 19,AAPL220916P00076250,2021-10-25 16:24:13,76.25,0.98,0.73,0.81,0.0,0.0,1.0,303.0,0.43677321044921874,False,REGULAR,USD
22 | 20,AAPL220916P00077500,2021-10-26 19:08:12,77.5,1.0,0.77,0.85,0.0,0.0,18.0,3415.0,0.4317683776855469,False,REGULAR,USD
23 | 21,AAPL220916P00078750,2021-10-26 13:47:29,78.75,1.05,0.81,0.89,0.0,0.0,1.0,389.0,0.42676354492187507,False,REGULAR,USD
24 | 22,AAPL220916P00080000,2021-11-04 19:49:17,80.0,0.9,0.85,0.93,0.0,0.0,35.0,6805.0,0.42163664306640625,False,REGULAR,USD
25 | 23,AAPL220916P00081250,2021-10-27 19:30:16,81.25,1.16,0.9,0.98,0.0,0.0,4.0,405.0,0.4172421557617187,False,REGULAR,USD
26 | 24,AAPL220916P00082500,2021-10-27 19:33:53,82.5,1.22,0.95,1.03,0.0,0.0,3.0,516.0,0.41272559936523434,False,REGULAR,USD
27 | 25,AAPL220916P00083750,2021-10-28 19:24:40,83.75,1.07,1.0,1.08,0.0,0.0,1.0,531.0,0.40820904296875,False,REGULAR,USD
28 | 26,AAPL220916P00085000,2021-11-02 17:39:45,85.0,1.1,1.05,1.13,0.0,0.0,387.0,1101.0,0.40344834838867194,False,REGULAR,USD
29 | 27,AAPL220916P00086250,2021-11-04 18:35:13,86.25,1.16,1.09,1.18,0.0,0.0,4.0,591.0,0.39856558471679693,False,REGULAR,USD
30 | 28,AAPL220916P00087500,2021-11-04 16:36:12,87.5,1.19,1.16,1.24,0.0,0.0,6.0,771.0,0.39441523559570313,False,REGULAR,USD
31 | 29,AAPL220916P00090000,2021-11-04 19:39:09,90.0,1.32,1.28,1.36,0.0,0.0,7.0,3819.0,0.385626260986328,False,REGULAR,USD
32 | 30,AAPL220916P00092500,2021-11-04 17:59:21,92.5,1.46,1.43,1.52,0.0,0.0,3.0,1063.0,0.37879039184570307,False,REGULAR,USD
33 | 31,AAPL220916P00095000,2021-11-04 16:37:05,95.0,1.6,1.57,1.66,0.0,0.0,2.0,10123.0,0.370123486328125,False,REGULAR,USD
34 | 32,AAPL220916P00097500,2021-11-01 18:23:00,97.5,1.77,1.75,1.83,0.0,0.0,12.0,1978.0,0.36249416809082036,False,REGULAR,USD
35 | 33,AAPL220916P00100000,2021-11-04 17:25:45,100.0,2.0,1.93,2.04,0.0,0.0,152.0,10587.0,0.3562686444091796,False,REGULAR,USD
36 | 34,AAPL220916P00102500,2021-11-01 16:04:23,102.5,2.17,2.14,2.23,0.0,0.0,2.0,1845.0,0.3482731188964844,False,REGULAR,USD
37 | 35,AAPL220916P00105000,2021-11-04 18:40:49,105.0,2.46,2.36,2.46,0.0,0.0,171.0,8278.0,0.34149828430175777,False,REGULAR,USD
38 | 36,AAPL220916P00107500,2021-11-04 15:25:22,107.5,2.72,2.63,2.73,0.0,0.0,383.0,2561.0,0.3355779333496094,False,REGULAR,USD
39 | 37,AAPL220916P00110000,2021-11-04 19:41:29,110.0,3.05,2.93,3.05,0.0,0.0,371.0,11991.0,0.3305731005859375,False,REGULAR,USD
40 | 38,AAPL220916P00112500,2021-11-04 19:43:11,112.5,3.4,3.25,3.35,0.0,0.0,370.0,2366.0,0.32398136962890617,False,REGULAR,USD
41 | 39,AAPL220916P00115000,2021-11-04 19:46:44,115.0,3.75,3.55,3.7,0.0,0.0,182.0,8375.0,0.31830515686035155,False,REGULAR,USD
42 | 40,AAPL220916P00117500,2021-11-04 19:54:40,117.5,4.2,4.0,4.15,0.0,0.0,18.0,2763.0,0.3147041186523437,False,REGULAR,USD
43 | 41,AAPL220916P00120000,2021-11-03 19:25:05,120.0,4.62,4.45,4.55,0.0,0.0,6.0,7412.0,0.3086006640625,False,REGULAR,USD
44 | 42,AAPL220916P00122500,2021-11-04 16:18:51,122.5,5.0,4.9,5.05,0.0,0.0,66.0,5017.0,0.3043587631225586,False,REGULAR,USD
45 | 43,AAPL220916P00125000,2021-11-04 17:46:15,125.0,5.65,0.0,5.65,0.0,0.0,28.0,12536.0,0.30158169128417966,False,REGULAR,USD
46 | 44,AAPL220916P00130000,2021-11-04 17:47:13,130.0,6.9,6.75,6.9,0.0,0.0,167.0,8599.0,0.29386082122802726,False,REGULAR,USD
47 | 45,AAPL220916P00135000,2021-11-05 13:30:00,135.0,8.3,8.2,8.35,-0.010000229,-0.12033969,1.0,10575.0,0.28626202026367187,False,REGULAR,USD
48 | 46,AAPL220916P00140000,2021-11-04 19:25:30,140.0,10.28,10.0,10.15,0.0,0.0,25.0,6566.0,0.2814097738647461,False,REGULAR,USD
49 | 47,AAPL220916P00145000,2021-11-05 13:30:00,145.0,12.15,12.1,12.25,-0.35000038,-2.800003,1.0,5580.0,0.27768666656494134,False,REGULAR,USD
50 | 48,AAPL220916P00150000,2021-11-04 19:55:03,150.0,15.0,14.4,14.5,0.0,0.0,676.0,11622.0,0.2721630401611328,False,REGULAR,USD
51 | 49,AAPL220916P00155000,2021-11-04 19:37:29,155.0,17.55,17.1,17.3,0.0,0.0,135.0,2259.0,0.27201045379638666,True,REGULAR,USD
52 | 50,AAPL220916P00160000,2021-11-04 17:46:10,160.0,20.55,20.1,20.3,0.0,0.0,36.0,3777.0,0.2710033837890625,True,REGULAR,USD
53 | 51,AAPL220916P00165000,2021-11-04 15:17:33,165.0,23.9,23.25,23.5,0.0,0.0,31.0,957.0,0.26938596832275385,True,REGULAR,USD
54 | 52,AAPL220916P00170000,2021-11-04 19:24:08,170.0,27.2,26.65,26.85,0.0,0.0,2.0,971.0,0.26642579284667967,True,REGULAR,USD
55 | 53,AAPL220916P00175000,2021-11-04 17:01:34,175.0,30.99,30.4,30.6,0.0,0.0,2.0,460.0,0.2671887246704102,True,REGULAR,USD
56 | 54,AAPL220916P00180000,2021-11-04 19:42:50,180.0,35.05,34.1,34.3,0.0,0.0,106.0,404.0,0.263251996459961,True,REGULAR,USD
57 | 55,AAPL220916P00185000,2021-11-01 19:57:50,185.0,39.75,38.25,38.5,0.0,0.0,7.0,379.0,0.26642579284667967,True,REGULAR,USD
58 | 56,AAPL220916P00190000,2021-11-03 16:18:46,190.0,42.8,42.5,42.7,0.0,0.0,27.0,810.0,0.2666699310302735,True,REGULAR,USD
59 | 57,AAPL220916P00195000,2021-11-03 18:30:57,195.0,47.25,46.7,47.0,0.0,0.0,64.0,633.0,0.26636475830078127,True,REGULAR,USD
60 | 58,AAPL220916P00200000,2021-11-04 19:23:37,200.0,52.1,51.2,51.45,0.0,0.0,204.0,956.0,0.2672192419433594,True,REGULAR,USD
61 | 59,AAPL220916P00210000,2021-11-04 19:00:04,210.0,61.2,60.3,60.6,0.0,0.0,11.0,272.0,0.268989243774414,True,REGULAR,USD
62 | 60,AAPL220916P00220000,2021-11-04 18:58:46,220.0,70.4,69.8,70.2,0.0,0.0,6.0,410.0,0.27936511657714835,True,REGULAR,USD
63 | 61,AAPL220916P00225000,2021-10-13 18:36:08,225.0,75.34,74.35,74.75,0.0,0.0,1.0,542.0,0.270515107421875,True,REGULAR,USD
64 | 62,AAPL220916P00230000,2021-11-04 19:10:15,230.0,80.0,90.5,90.8,0.0,0.0,305.0,396.0,0.5731243859863282,True,REGULAR,USD
65 | 63,AAPL220916P00240000,2021-10-29 13:30:00,240.0,93.9,88.85,89.25,0.0,0.0,1.0,141.0,0.27136959106445313,True,REGULAR,USD
66 | 64,AAPL220916P00250000,2021-11-04 19:06:12,250.0,99.5,98.4,98.8,0.0,0.0,5.0,678.0,0.241218525390625,True,REGULAR,USD
67 | 65,AAPL220916P00260000,2021-10-21 16:04:15,260.0,111.47,108.6,109.0,0.0,0.0,1.0,238.0,0.28443098388671867,True,REGULAR,USD
68 | 66,AAPL220916P00270000,2020-08-25 18:09:01,270.0,17.32,17.15,18.4,0.020000458,0.115609586,1.0,148.0,1.0000000000000003e-05,True,REGULAR,USD
69 | 67,AAPL220916P00280000,2020-08-28 19:54:42,280.0,19.65,19.1,20.05,0.54999924,2.8795772,1.0,0.0,1.0000000000000003e-05,True,REGULAR,USD
70 | 68,AAPL220916P00290000,2020-08-28 17:27:04,290.0,22.0,21.2,22.55,1.2999992,6.280189,1.0,233.0,1.0000000000000003e-05,True,REGULAR,USD
71 | 69,AAPL220916P00300000,2020-08-28 19:57:19,300.0,23.93,23.55,24.65,1.0500011,4.589166,25.0,334.0,1.0000000000000003e-05,True,REGULAR,USD
72 | 70,AAPL220916P00305000,2020-08-11 17:33:32,305.0,29.52,24.75,26.15,0.0,0.0,1.0,67.0,1.0000000000000003e-05,True,REGULAR,USD
73 | 71,AAPL220916P00310000,2020-08-24 17:31:36,310.0,25.4,26.4,27.35,0.0,0.0,12.0,785.0,1.0000000000000003e-05,True,REGULAR,USD
74 | 72,AAPL220916P00315000,2020-08-27 18:09:47,315.0,27.92,27.3,28.65,0.020000458,0.07168622,1.0,52.0,1.0000000000000003e-05,True,REGULAR,USD
75 | 73,AAPL220916P00320000,2020-08-27 17:48:35,320.0,29.72,28.65,30.1,0.01999855,0.06733519,2.0,90.0,1.0000000000000003e-05,True,REGULAR,USD
76 | 74,AAPL220916P00325000,2020-08-24 14:38:13,325.0,29.48,30.0,31.5,-0.010000229,-0.033910576,1.0,50.0,1.0000000000000003e-05,True,REGULAR,USD
77 | 75,AAPL220916P00330000,2020-08-27 15:10:03,330.0,31.08,31.45,32.95,0.020000458,0.06439298,2.0,30.0,1.0000000000000003e-05,True,REGULAR,USD
78 | 76,AAPL220916P00335000,2020-08-28 17:17:44,335.0,33.4,32.9,34.45,1.5000019,4.7022004,1.0,48.0,1.0000000000000003e-05,True,REGULAR,USD
79 | 77,AAPL220916P00340000,2020-08-24 14:34:43,340.0,33.6,34.45,35.95,0.0,0.0,2.0,0.0,1.0000000000000003e-05,True,REGULAR,USD
80 | 78,AAPL220916P00345000,2020-08-25 19:11:18,345.0,35.52,36.0,37.55,0.020000458,0.056339316,1.0,0.0,1.0000000000000003e-05,True,REGULAR,USD
81 | 79,AAPL220916P00350000,2020-08-28 15:31:55,350.0,38.75,37.6,39.2,1.0499992,2.7851439,6.0,119.0,1.0000000000000003e-05,True,REGULAR,USD
82 | 80,AAPL220916P00360000,2020-08-28 17:29:48,360.0,42.2,41.0,42.6,2.2400017,5.60561,2.0,460.0,1.0000000000000003e-05,True,REGULAR,USD
83 | 81,AAPL220916P00370000,2020-08-26 13:55:49,370.0,42.84,44.5,46.2,-0.0099983215,-0.023333305,2.0,90.0,1.0000000000000003e-05,True,REGULAR,USD
84 | 82,AAPL220916P00380000,2020-08-28 15:56:58,380.0,48.64,48.25,49.95,0.23999786,0.49586332,1.0,127.0,1.0000000000000003e-05,True,REGULAR,USD
85 | 83,AAPL220916P00390000,2020-08-28 19:11:56,390.0,52.72,52.25,53.95,1.1500015,2.2299817,1.0,47.0,1.0000000000000003e-05,True,REGULAR,USD
86 | 84,AAPL220916P00400000,2020-08-28 18:41:14,400.0,56.85,56.3,58.1,0.019996643,0.03518677,6.0,817.0,1.0000000000000003e-05,True,REGULAR,USD
87 | 85,AAPL220916P00410000,2020-08-28 15:54:18,410.0,60.75,60.6,62.45,-0.29999924,-0.49139923,2.0,68.0,1.0000000000000003e-05,True,REGULAR,USD
88 | 86,AAPL220916P00420000,2020-08-28 17:29:48,420.0,65.4,65.05,67.0,1.2200012,1.9009056,4.0,60.0,1.0000000000000003e-05,True,REGULAR,USD
89 | 87,AAPL220916P00430000,2020-08-28 16:56:43,430.0,69.05,69.75,71.75,-0.33999634,-0.48997885,1.0,114.0,1.0000000000000003e-05,True,REGULAR,USD
90 | 88,AAPL220916P00440000,2020-08-27 14:40:05,440.0,73.29,74.55,76.65,0.0,0.0,12.0,177.0,1.0000000000000003e-05,True,REGULAR,USD
91 | 89,AAPL220916P00450000,2020-08-28 18:09:55,450.0,80.0,79.6,81.75,-0.76000214,-0.9410625,1.0,123.0,1.0000000000000003e-05,True,REGULAR,USD
92 | 90,AAPL220916P00460000,2020-08-27 14:40:05,460.0,83.19,84.8,87.0,0.0,0.0,1.0,39.0,1.0000000000000003e-05,True,REGULAR,USD
93 | 91,AAPL220916P00470000,2020-08-27 15:14:28,470.0,87.15,90.15,92.45,0.0,0.0,10.0,0.0,1.0000000000000003e-05,True,REGULAR,USD
94 | 92,AAPL220916P00480000,2020-08-27 16:28:32,480.0,95.45,95.7,98.05,0.0,0.0,2.0,7.0,1.0000000000000003e-05,True,REGULAR,USD
95 | 93,AAPL220916P00490000,2020-08-27 18:29:46,490.0,101.2,101.45,103.85,0.0,0.0,8.0,0.0,1.0000000000000003e-05,True,REGULAR,USD
96 | 94,AAPL220916P00500000,2020-08-28 19:56:47,500.0,108.5,107.3,109.0,2.800003,2.6490097,11.0,318.0,1.0000000000000003e-05,True,REGULAR,USD
97 | 95,AAPL220916P00520000,2020-08-28 17:11:15,520.0,122.0,119.45,122.2,6.25,5.399568,18.0,19.0,1.0000000000000003e-05,True,REGULAR,USD
98 | 96,AAPL220916P00540000,2020-08-27 13:31:06,540.0,126.4,132.2,135.2,0.0,0.0,1.0,48.0,1.0000000000000003e-05,True,REGULAR,USD
99 | 97,AAPL220916P00560000,2020-08-27 14:45:00,560.0,143.3,145.5,147.5,0.0,0.0,33.0,18.0,1.0000000000000003e-05,True,REGULAR,USD
100 | 98,AAPL220916P00600000,2020-08-28 15:27:40,600.0,172.0,173.65,177.0,-0.1000061,-0.058109295,1.0,19.0,1.0000000000000003e-05,True,REGULAR,USD
101 | 99,AAPL220916P00640000,2020-08-04 16:01:27,640.0,226.35,203.55,207.0,0.0,0.0,,2.0,1.0000000000000003e-05,True,REGULAR,USD
102 | 100,AAPL220916P00660000,2020-08-18 17:21:59,660.0,236.4,219.35,222.5,0.0,0.0,1.0,3.0,1.0000000000000003e-05,True,REGULAR,USD
103 | 101,AAPL220916P00680000,2020-08-27 14:01:35,680.0,23.2,4.8,5.85,-205.13,-89.839264,2.0,16.0,1.0000000000000003e-05,True,REGULAR,USD
104 | 102,AAPL220916P00700000,2020-08-27 19:44:48,700.0,22.2,5.2,6.25,-227.8,-91.119995,23.0,7.0,1.0000000000000003e-05,True,REGULAR,USD
105 | 103,AAPL220916P00720000,2020-08-25 19:59:35,720.0,6.0,5.6,6.65,-258.1,-97.728134,10.0,113.0,1.0000000000000003e-05,True,REGULAR,USD
106 | 104,AAPL220916P00740000,2020-08-26 18:55:57,740.0,26.8,6.45,7.1,-252.49998,-90.40458,,1322.0,1.0000000000000003e-05,True,REGULAR,USD
107 | 105,AAPL220916P00900000,2020-08-27 18:51:13,900.0,424.83,425.5,429.5,0.0,0.0,,3.0,1.0000000000000003e-05,True,REGULAR,USD
108 | 106,AAPL220916P01000000,2020-08-28 17:27:35,1000.0,521.65,519.0,523.0,3.8600464,0.74548495,17.0,,1.0000000000000003e-05,True,REGULAR,USD
109 |
--------------------------------------------------------------------------------
/Implied Volatility/aapl_call_data.csv:
--------------------------------------------------------------------------------
1 | ,contractSymbol,lastTradeDate,strike,lastPrice,bid,ask,change,percentChange,volume,openInterest,impliedVolatility,inTheMoney,contractSize,currency
2 | 0,AAPL220916C00040000,2021-11-04 19:21:52,40.0,111.2,111.75,112.05,0.0,0.0,225,87.0,0.7417018017578124,True,REGULAR,USD
3 | 1,AAPL220916C00041250,2021-10-21 16:07:50,41.25,109.95,110.4,110.75,0.0,0.0,108,16.0,0.7070341796875,True,REGULAR,USD
4 | 2,AAPL220916C00042500,2021-10-25 16:29:45,42.5,108.7,109.3,109.6,0.0,0.0,14,4.0,0.7202176416015625,True,REGULAR,USD
5 | 3,AAPL220916C00043750,2021-10-28 15:26:06,43.75,107.25,107.95,108.35,0.0,0.0,200,11.0,0.6938507177734375,True,REGULAR,USD
6 | 4,AAPL220916C00045000,2021-10-25 16:32:22,45.0,103.69,106.85,107.25,0.0,0.0,71,4.0,0.70898728515625,True,REGULAR,USD
7 | 5,AAPL220916C00046250,2021-10-29 15:19:06,46.25,101.15,105.55,105.85,0.0,0.0,54,0.0,0.6748079394531252,True,REGULAR,USD
8 | 6,AAPL220916C00047500,2021-11-04 18:42:51,47.5,103.7,104.25,104.6,0.0,0.0,19,0.0,0.6555210229492189,True,REGULAR,USD
9 | 7,AAPL220916C00048750,2021-11-04 14:48:52,48.75,103.1,103.0,103.3,0.0,0.0,36,0.0,0.6367223828125,True,REGULAR,USD
10 | 8,AAPL220916C00050000,2021-11-04 16:31:57,50.0,101.3,101.9,102.25,0.0,0.0,54,199.0,0.6552768847656252,True,REGULAR,USD
11 | 9,AAPL220916C00052500,2021-11-04 19:14:39,52.5,98.98,99.2,99.6,0.0,0.0,420,401.0,0.5976602734375001,True,REGULAR,USD
12 | 10,AAPL220916C00055000,2021-11-04 15:57:36,55.0,96.47,96.75,97.15,0.0,0.0,290,50.0,0.5820354296875,True,REGULAR,USD
13 | 11,AAPL220916C00057500,2021-11-04 17:40:33,57.5,93.95,94.6,95.0,0.0,0.0,307,315.0,0.6098671826171876,True,REGULAR,USD
14 | 12,AAPL220916C00060000,2021-10-28 14:32:29,60.0,91.39,91.1,92.4,0.0,0.0,158,1729.0,0.5974161352539062,True,REGULAR,USD
15 | 13,AAPL220916C00062500,2021-11-04 18:04:23,62.5,89.09,89.55,89.85,0.0,0.0,102,773.0,0.5495650512695314,True,REGULAR,USD
16 | 14,AAPL220916C00065000,2021-11-04 19:36:51,65.0,86.54,87.05,87.45,0.0,0.0,302,2447.0,0.5336960693359375,True,REGULAR,USD
17 | 15,AAPL220916C00067500,2021-11-04 19:17:17,67.5,84.09,84.55,85.0,0.0,0.0,230,1214.0,0.5151415673828125,True,REGULAR,USD
18 | 16,AAPL220916C00070000,2021-11-04 17:41:08,70.0,81.6,82.2,82.6,0.0,0.0,54,1204.0,0.5075732836914062,True,REGULAR,USD
19 | 17,AAPL220916C00072500,2021-11-04 19:37:12,72.5,79.26,79.65,80.05,0.0,0.0,68,581.0,0.5014698291015626,True,REGULAR,USD
20 | 18,AAPL220916C00075000,2021-11-04 19:37:12,75.0,76.86,77.35,77.75,0.0,0.0,63,2110.0,0.4982960327148438,True,REGULAR,USD
21 | 19,AAPL220916C00076250,2021-10-18 15:43:24,76.25,69.82,76.1,76.6,0.0,0.0,5,337.0,0.49609878906250005,True,REGULAR,USD
22 | 20,AAPL220916C00077500,2021-11-04 13:43:47,77.5,74.35,74.9,75.25,0.0,0.0,297,598.0,0.47827670166015623,True,REGULAR,USD
23 | 21,AAPL220916C00078750,2021-11-04 18:53:33,78.75,73.15,72.4,75.4,0.0,0.0,1,0.0,0.5592085095214845,True,REGULAR,USD
24 | 22,AAPL220916C00080000,2021-11-04 15:45:14,80.0,71.79,72.3,72.7,0.0,0.0,6,856.0,0.4549615051269531,True,REGULAR,USD
25 | 23,AAPL220916C00081250,2021-10-20 13:42:43,81.25,69.05,71.2,71.55,0.0,0.0,4,383.0,0.45300839965820316,True,REGULAR,USD
26 | 24,AAPL220916C00082500,2021-11-04 19:49:38,82.5,69.52,70.0,70.35,0.0,0.0,3,402.0,0.44727115234375,True,REGULAR,USD
27 | 25,AAPL220916C00083750,2021-11-05 13:30:04,83.75,68.92,68.95,69.3,0.55999756,0.81918895,50,405.0,0.4514215014648438,True,REGULAR,USD
28 | 26,AAPL220916C00085000,2021-10-29 18:36:07,85.0,65.11,67.7,68.1,0.0,0.0,14,489.0,0.4451959777832031,True,REGULAR,USD
29 | 27,AAPL220916C00086250,2021-11-03 17:04:56,86.25,65.0,66.55,66.9,0.0,0.0,1,534.0,0.43897045410156255,True,REGULAR,USD
30 | 28,AAPL220916C00087500,2021-11-05 13:30:02,87.5,65.25,65.15,65.6,3.4199982,5.5312924,4,2260.0,0.42664147583007817,True,REGULAR,USD
31 | 29,AAPL220916C00090000,2021-11-03 18:54:54,90.0,62.5,62.85,63.25,0.0,0.0,8,6785.0,0.4173031903076171,True,REGULAR,USD
32 | 30,AAPL220916C00092500,2021-10-28 16:48:57,92.5,61.45,60.5,60.85,0.0,0.0,10,1252.0,0.4048521429443359,True,REGULAR,USD
33 | 31,AAPL220916C00095000,2021-10-29 13:58:48,95.0,57.9,58.25,58.55,0.0,0.0,1,1725.0,0.397466962890625,True,REGULAR,USD
34 | 32,AAPL220916C00097500,2021-11-02 17:22:08,97.5,56.3,55.85,56.2,0.0,0.0,2,848.0,0.3870300555419921,True,REGULAR,USD
35 | 33,AAPL220916C00100000,2021-11-04 15:29:18,100.0,53.25,53.6,53.95,0.0,0.0,31,5361.0,0.38080453186035157,True,REGULAR,USD
36 | 34,AAPL220916C00102500,2021-10-29 14:31:56,102.5,49.8,51.3,51.6,0.0,0.0,2,686.0,0.36963520996093746,True,REGULAR,USD
37 | 35,AAPL220916C00105000,2021-11-02 19:44:48,105.0,48.54,49.25,49.5,0.0,0.0,4,2030.0,0.3679872772216797,True,REGULAR,USD
38 | 36,AAPL220916C00107500,2021-11-04 17:06:26,107.5,46.05,46.8,47.15,0.0,0.0,39,2630.0,0.355902437133789,True,REGULAR,USD
39 | 37,AAPL220916C00110000,2021-11-04 18:14:51,110.0,44.02,44.65,45.0,0.0,0.0,7,3069.0,0.3505924316406249,True,REGULAR,USD
40 | 38,AAPL220916C00112500,2021-11-04 17:44:44,112.5,42.08,42.65,42.95,0.0,0.0,41,2972.0,0.34766277343749996,True,REGULAR,USD
41 | 39,AAPL220916C00115000,2021-11-04 18:47:48,115.0,39.7,40.5,40.75,0.0,0.0,1,3692.0,0.33899586791992187,True,REGULAR,USD
42 | 40,AAPL220916C00117500,2021-11-03 19:48:51,117.5,38.02,38.2,38.5,0.0,0.0,1,3613.0,0.3284368914794922,True,REGULAR,USD
43 | 41,AAPL220916C00120000,2021-11-04 17:35:21,120.0,35.79,36.15,36.45,0.0,0.0,165,3948.0,0.32294378234863275,True,REGULAR,USD
44 | 42,AAPL220916C00122500,2021-11-04 17:32:51,122.5,33.76,34.25,34.5,0.0,0.0,4,3019.0,0.319220675048828,True,REGULAR,USD
45 | 43,AAPL220916C00125000,2021-11-04 18:53:40,125.0,31.85,32.25,32.55,0.0,0.0,33,23439.0,0.31445998046874996,True,REGULAR,USD
46 | 44,AAPL220916C00130000,2021-11-04 14:44:33,130.0,28.2,28.65,28.95,0.0,0.0,32,15055.0,0.3089058367919921,True,REGULAR,USD
47 | 45,AAPL220916C00135000,2021-11-04 17:38:22,135.0,24.65,25.2,25.45,0.0,0.0,32,4932.0,0.30118496673583983,True,REGULAR,USD
48 | 46,AAPL220916C00140000,2021-11-04 19:52:22,140.0,21.3,21.85,22.1,0.0,0.0,33,12389.0,0.2924875439453124,True,REGULAR,USD
49 | 47,AAPL220916C00145000,2021-11-04 18:44:45,145.0,18.6,19.0,19.2,0.0,0.0,58,6053.0,0.2882151257324218,True,REGULAR,USD
50 | 48,AAPL220916C00150000,2021-11-05 13:38:07,150.0,16.55,16.45,16.6,0.74999905,4.7468295,84,18959.0,0.2851023638916015,True,REGULAR,USD
51 | 49,AAPL220916C00155000,2021-11-04 19:56:56,155.0,13.6,14.1,14.3,0.0,0.0,397,7746.0,0.2829966720581054,False,REGULAR,USD
52 | 50,AAPL220916C00160000,2021-11-04 18:58:33,160.0,11.85,12.0,12.2,0.0,0.0,129,22432.0,0.2802196002197265,False,REGULAR,USD
53 | 51,AAPL220916C00165000,2021-11-05 13:32:08,165.0,10.5,10.3,10.45,0.32999992,3.244837,10,7929.0,0.27967028930664056,False,REGULAR,USD
54 | 52,AAPL220916C00170000,2021-11-04 15:10:52,170.0,8.55,8.7,8.9,0.0,0.0,147,12016.0,0.27893787475585935,False,REGULAR,USD
55 | 53,AAPL220916C00175000,2021-11-04 19:55:09,175.0,7.14,7.45,7.6,0.0,0.0,38,9078.0,0.2792735647583008,False,REGULAR,USD
56 | 54,AAPL220916C00180000,2021-11-04 19:55:55,180.0,6.1,6.3,6.5,0.0,0.0,30,15897.0,0.28018908294677725,False,REGULAR,USD
57 | 55,AAPL220916C00185000,2021-11-04 19:46:34,185.0,5.26,5.35,5.5,0.0,0.0,34,4035.0,0.28003649658203117,False,REGULAR,USD
58 | 56,AAPL220916C00190000,2021-11-04 19:23:54,190.0,4.6,4.55,4.7,0.0,0.0,4,5520.0,0.2813182220458984,False,REGULAR,USD
59 | 57,AAPL220916C00195000,2021-11-03 19:51:45,195.0,3.86,3.9,4.05,0.0,0.0,1,2223.0,0.2834544311523437,False,REGULAR,USD
60 | 58,AAPL220916C00200000,2021-11-05 13:32:08,200.0,3.5,3.35,3.45,0.17000008,5.1051073,11,11345.0,0.28443098388671867,False,REGULAR,USD
61 | 59,AAPL220916C00210000,2021-11-04 16:10:03,210.0,2.47,2.47,2.55,0.0,0.0,322,3456.0,0.28803202209472645,False,REGULAR,USD
62 | 60,AAPL220916C00220000,2021-11-04 17:48:36,220.0,1.88,1.87,1.95,0.0,0.0,411,1140.0,0.2937082348632812,False,REGULAR,USD
63 | 61,AAPL220916C00225000,2021-11-04 16:05:54,225.0,1.64,1.65,1.7,0.0,0.0,145,4111.0,0.29608858215332035,False,REGULAR,USD
64 | 62,AAPL220916C00230000,2021-11-03 16:06:42,230.0,1.4,1.45,1.5,0.0,0.0,2,2488.0,0.2990792749023437,False,REGULAR,USD
65 | 63,AAPL220916C00240000,2021-10-29 16:00:41,240.0,1.17,1.15,1.2,0.0,0.0,77,622.0,0.30609824768066407,False,REGULAR,USD
66 | 64,AAPL220916C00250000,2021-11-04 19:18:01,250.0,0.93,0.92,0.97,0.0,0.0,31,34196.0,0.31287308227539057,False,REGULAR,USD
67 | 65,AAPL220916C00260000,2021-11-04 19:55:56,260.0,0.78,0.0,0.81,0.0,0.0,251,2415.0,0.3205634350585937,False,REGULAR,USD
68 | 66,AAPL220916C00270000,2020-08-27 14:10:43,270.0,250.0,243.35,247.5,0.0,0.0,2,226.0,0.0,False,REGULAR,USD
69 | 67,AAPL220916C00280000,2020-08-27 19:58:42,280.0,238.0,235.45,239.5,0.0,0.0,33,133.0,0.0,False,REGULAR,USD
70 | 68,AAPL220916C00290000,2020-08-28 17:51:01,290.0,230.57,227.45,232.0,0.0,0.0,2,0.0,0.0,False,REGULAR,USD
71 | 69,AAPL220916C00300000,2020-08-28 19:11:26,300.0,224.74,219.95,224.5,-0.83999634,-0.3723718,15,792.0,0.0,False,REGULAR,USD
72 | 70,AAPL220916C00305000,2020-08-24 14:05:41,305.0,218.0,216.15,220.5,0.0,0.0,1,142.0,0.0,False,REGULAR,USD
73 | 71,AAPL220916C00310000,2020-08-28 18:00:15,310.0,215.66,212.75,217.0,-2.399994,-1.1006117,4,127.0,0.0,False,REGULAR,USD
74 | 72,AAPL220916C00315000,2020-08-24 13:47:53,315.0,219.4,209.1,213.5,-0.010009766,-0.004562128,2,49.0,0.0,False,REGULAR,USD
75 | 73,AAPL220916C00320000,2020-08-28 17:30:21,320.0,208.0,205.3,209.5,-0.020004272,-0.009616514,1,207.0,0.0,False,REGULAR,USD
76 | 74,AAPL220916C00325000,2020-08-27 13:33:46,325.0,210.4,202.0,206.0,0.019989014,0.009501385,1,112.0,0.0,False,REGULAR,USD
77 | 75,AAPL220916C00330000,2020-08-28 19:11:26,330.0,202.86,201.0,203.45,-1.449997,-0.70970434,4,138.0,0.0,False,REGULAR,USD
78 | 76,AAPL220916C00335000,2020-08-25 15:27:46,335.0,195.0,194.8,199.0,0.0,0.0,1,87.0,0.0,False,REGULAR,USD
79 | 77,AAPL220916C00340000,2020-08-28 17:43:52,340.0,196.5,191.4,195.5,-3.5,-1.75,3,170.0,0.0,False,REGULAR,USD
80 | 78,AAPL220916C00345000,2020-08-25 14:07:38,345.0,186.52,188.05,192.5,0.020004272,0.010726151,1,93.0,0.0,False,REGULAR,USD
81 | 79,AAPL220916C00350000,2020-08-27 17:27:34,350.0,188.15,184.85,189.0,-0.8700104,-0.46027425,3,721.0,0.0,False,REGULAR,USD
82 | 80,AAPL220916C00360000,2020-08-28 19:12:38,360.0,182.7,178.35,182.5,0.22000122,0.12056182,27,837.0,0.0,False,REGULAR,USD
83 | 81,AAPL220916C00370000,2020-08-28 16:56:36,370.0,177.0,172.05,176.5,4.300003,2.4898686,3,359.0,0.0,False,REGULAR,USD
84 | 82,AAPL220916C00380000,2020-08-28 19:00:57,380.0,169.34,165.95,170.0,0.48999023,0.2901926,6,594.0,0.0,False,REGULAR,USD
85 | 83,AAPL220916C00390000,2020-08-28 14:36:10,390.0,163.9,160.2,164.0,0.44999695,0.27531168,12,261.0,0.0,False,REGULAR,USD
86 | 84,AAPL220916C00400000,2020-08-28 19:44:42,400.0,157.0,157.0,158.5,-1.2200012,-0.771079,44,0.0,0.0,False,REGULAR,USD
87 | 85,AAPL220916C00410000,2020-08-28 17:33:32,410.0,150.44,150.15,152.85,-1.1100006,-0.73243195,12,194.0,0.0,False,REGULAR,USD
88 | 86,AAPL220916C00420000,2020-08-28 19:46:20,420.0,149.34,143.35,146.35,0.73999023,0.49797454,22,570.0,4.772709112243652,False,REGULAR,USD
89 | 87,AAPL220916C00430000,2020-08-28 19:53:24,430.0,143.8,138.6,141.15,1.050003,0.7355538,10,882.0,4.284672612915039,False,REGULAR,USD
90 | 88,AAPL220916C00440000,2020-08-28 18:38:18,440.0,137.44,133.25,137.0,-0.1499939,-0.109015115,6,353.0,3.968139728088379,False,REGULAR,USD
91 | 89,AAPL220916C00450000,2020-08-28 19:40:28,450.0,132.8,128.45,132.0,0.68000793,0.5146896,4,926.0,3.7154548129272458,False,REGULAR,USD
92 | 90,AAPL220916C00460000,2020-08-28 15:57:39,460.0,128.25,123.95,127.3,0.44999695,0.35211027,1,595.0,3.520142801208496,False,REGULAR,USD
93 | 91,AAPL220916C00470000,2020-08-28 18:13:46,470.0,122.5,120.7,122.7,-0.69000244,-0.5601124,22,932.0,3.3765884725952144,False,REGULAR,USD
94 | 92,AAPL220916C00480000,2020-08-28 17:33:20,480.0,118.8,115.2,118.4,-0.08999634,-0.07569715,131,366.0,3.2155170979309076,False,REGULAR,USD
95 | 93,AAPL220916C00490000,2020-08-28 18:55:32,490.0,114.0,111.05,114.15,-0.41999817,-0.3670671,30,0.0,3.092775705566406,False,REGULAR,USD
96 | 94,AAPL220916C00500000,2020-08-28 19:59:59,500.0,108.5,107.85,110.4,-3.0,-2.690583,169,6512.0,3.000612850036621,False,REGULAR,USD
97 | 95,AAPL220916C00520000,2020-08-28 19:58:09,520.0,101.43,100.0,102.45,0.16000366,0.1579971,194,1339.0,2.808657763519287,False,REGULAR,USD
98 | 96,AAPL220916C00540000,2020-08-28 18:19:52,540.0,95.17,92.65,95.45,0.48999786,0.5175305,29,1205.0,2.654544379272461,False,REGULAR,USD
99 | 97,AAPL220916C00560000,2020-08-28 19:56:36,560.0,88.4,86.15,88.9,0.7000046,0.7981809,81,1958.0,2.5273474316406244,False,REGULAR,USD
100 | 98,AAPL220916C00580000,2020-08-28 19:54:42,580.0,79.25,80.4,83.1,-3.3499985,-4.0556884,23,1568.0,2.4236794779205324,False,REGULAR,USD
101 | 99,AAPL220916C00600000,2020-08-28 19:59:03,600.0,76.55,75.0,77.45,-0.049995422,-0.065268174,57,1016.0,2.3298686772918695,False,REGULAR,USD
102 | 100,AAPL220916C00620000,2020-08-28 19:51:45,620.0,73.7,70.05,72.55,2.0499954,2.861124,130,216.0,2.2510419700622553,False,REGULAR,USD
103 | 101,AAPL220916C00640000,2020-08-28 19:08:40,640.0,1386.0,339.15,344.0,1320.05,2001.5923,3,102.0,0.0,False,REGULAR,USD
104 | 102,AAPL220916C00660000,2020-08-28 19:46:18,660.0,1200.0,334.5,339.0,1138.87,1863.0295,28,10.0,0.0,False,REGULAR,USD
105 | 103,AAPL220916C00680000,2020-08-28 19:53:39,680.0,1338.4,330.0,334.5,1281.9,2268.8496,111,6.0,0.0,False,REGULAR,USD
106 | 104,AAPL220916C00700000,2020-08-28 18:32:59,700.0,1089.4,325.15,330.0,1032.9,1828.1416,9,4.0,0.0,False,REGULAR,USD
107 | 105,AAPL220916C00720000,2020-08-28 19:57:38,720.0,324.69,320.5,325.0,273.19,530.466,30,26.0,0.0,False,REGULAR,USD
108 | 106,AAPL220916C00740000,2020-08-28 19:48:09,740.0,1262.6,316.0,320.5,1215.1,2558.1052,17,1.0,0.0,False,REGULAR,USD
109 | 107,AAPL220916C00800000,2020-08-28 19:31:51,800.0,306.89,302.25,307.0,266.99002,669.1479,16,197.0,0.0,False,REGULAR,USD
110 | 108,AAPL220916C00900000,2020-08-28 19:46:07,900.0,31.47,30.4,32.2,1.1700001,3.8613863,172,1.0,1.7063918489074705,False,REGULAR,USD
111 | 109,AAPL220916C01000000,2020-08-28 19:59:03,1000.0,24.75,24.5,24.75,1.1000004,4.6511645,1315,,1.6255511886596676,False,REGULAR,USD
112 |
--------------------------------------------------------------------------------
/European Options/Black Scholes/bs_fourier_pricing.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "ruled-oracle",
6 | "metadata": {},
7 | "source": [
8 | "# Black-Scholes: Option pricing with Fourier transform\n",
9 | "\n",
10 | "## Mathematics\n",
11 | "\n",
12 | "\n",
13 | "In order to use the Fourier method for option pricing, we need the characteristic function of the process we consider and the characteristic function of the payoff.\n",
14 | "\n",
15 | "The characteristic function is available analytically for all Lévy processes (including Brownian motion which is a special case) even when the PDF is not. We consider a log-normal process such that\n",
16 | "\n",
17 | "\\begin{equation}\n",
18 | " \\log \\frac{S_{t + \\Delta t}}{S_t} \\sim \\mathcal{N} \\left( \\Big(r - q - \\frac{1}{2} \\sigma^2 \\Big)\\Delta t, \\sigma^2 \\Delta t \\right)\n",
19 | "\\end{equation}\n",
20 | "\n",
21 | "where $S_t$ is the stock price at time $t$, $\\sigma$ is the stock price volatility, $r$ is the risk-free interest rate and $q$ is the dividend rate.\n",
22 | "\n",
23 | "The characteristic function is given by \n",
24 | "\n",
25 | "\\begin{equation}\n",
26 | " \\psi(\\xi) = \\exp \\left[ i \\xi \\left(r - q - \\frac{1}{2} \\sigma^2 \\right) \\Delta t - \\frac{1}{2} \\xi^2 \\sigma^2 \\Delta t \\right]\n",
27 | "\\end{equation}\n",
28 | "\n",
29 | "where $i$ is the imaginary unit such that $i = \\sqrt{-1}$.\n",
30 | "\n",
31 | "The characteristic function of the payoff is also available analytically. The payoff of a vanilla European option, $g$, is defined as\n",
32 | "\n",
33 | "\\begin{equation}\n",
34 | " g(S_T) = \\max \\big(\\theta(S_T - K), 0 \\big) = \\big(\\theta(S_T - K) \\big)^+\n",
35 | "\\end{equation}\n",
36 | "\n",
37 | "where $S_T$ is the stock price at maturity $T$, $K$ is the strike price and $\\theta$ is equal to 1 for a call and -1 for a put. \n",
38 | "\n",
39 | "Because the payoff function diverges in the limits (i.e. $g(S_T) \\to \\infty$ as $S_T \\to \\infty$ for a call), we introduce a damping factor $e^{\\alpha S_T}$ with $\\alpha \\in \\mathbb{R}$. Multiplying the payoff by this factor, with $\\alpha < 0$ for a call and $\\alpha > 0$ for a put, makes the function square integrable. \n",
40 | "\n",
41 | "The payoff is expressed as a function of the log-price \n",
42 | "\n",
43 | "\\begin{equation}\n",
44 | " x = \\log \\frac{S_T}{S_0},\n",
45 | "\\end{equation}\n",
46 | "\n",
47 | "the log-strike\n",
48 | "\n",
49 | "\\begin{equation}\n",
50 | " k = \\log \\frac{K}{S_0},\n",
51 | "\\end{equation}\n",
52 | "\n",
53 | "and (potentially) the upper log-barrier\n",
54 | "\n",
55 | "\\begin{equation}\n",
56 | " u = \\log \\frac{U}{S_0},\n",
57 | "\\end{equation}\n",
58 | "\n",
59 | "and the lower log-barrier\n",
60 | "\n",
61 | "\\begin{equation}\n",
62 | " l = \\log \\frac{L}{S_0}.\n",
63 | "\\end{equation}\n",
64 | "\n",
65 | "Our damped payoff function becomes\n",
66 | "\n",
67 | "\\begin{equation}\n",
68 | " g(x) = e^{\\alpha x} S_0 \\big(\\theta (e^x - e^k) \\big)^+ \\mathbb{1}_{[l, u]}(x)\n",
69 | "\\end{equation}\n",
70 | "\n",
71 | "where $l$ and $u$ are set equal to the upper and lower truncation limits for vanilla options. Also, note that the damping factor is slightly changed (i.e. $e^{\\alpha x} \\neq e^{\\alpha S_T}$) but this is not a problem because damping is just a technical trick which is undone at the end.\n",
72 | "\n",
73 | "The Fourier transform of the damped payoff is given by\n",
74 | "\n",
75 | "\\begin{align}\n",
76 | " \\hat{g}(\\xi) = \\mathscr{F}_{x \\to \\xi} [g(x)] &= \\int_{\\mathbb{R}} e^{i \\xi x} e^{\\alpha x} S_0 \\big(\\theta (e^x - e^k) \\big)^+ \\mathbb{1}_{[l, u]}(x) dx \\notag \\\\\n",
77 | " &= S_0 \\int_l^u e^{(i \\xi + \\alpha)x} \\big(\\theta (e^x - e^k) \\big)^+ dx \\notag \\\\\n",
78 | " &= S_0 \\int_{\\nu}^{\\eta} e^{(i \\xi + \\alpha)x} \\big(e^x - e^k \\big) dx \\notag \\\\\n",
79 | " &= S_0 \\int_{\\nu}^{\\eta} e^{(1 + i \\xi + \\alpha)x} dx - S_0 \\int_{\\nu}^{\\eta} e^{k + (i \\xi + \\alpha)x} dx \\notag \\\\\n",
80 | " &= S_0 \\left( \\frac{e^{(1 + i\\xi + \\alpha)\\eta} - e^{(1 + i\\xi + \\alpha)\\nu}}{1 + i\\xi + \\alpha} - \\frac{e^{k + (i\\xi + \\alpha)\\eta} - e^{k + (i\\xi + \\alpha)\\nu}}{i\\xi + \\alpha} \\right)\n",
81 | "\\end{align}\n",
82 | "\n",
83 | "where\n",
84 | "\n",
85 | "\\begin{equation}\n",
86 | " \\eta = \\begin{cases} \n",
87 | " u & \\text{for a call} \\\\\n",
88 | " l & \\text{for a put} \n",
89 | " \\end{cases},\n",
90 | "\\end{equation}\n",
91 | "\n",
92 | "and \n",
93 | "\n",
94 | "\\begin{equation}\n",
95 | " \\nu = \\begin{cases} \n",
96 | " \\max(k, l) & \\text{for a call} \\\\\n",
97 | " \\min(k, u) & \\text{for a put} \n",
98 | " \\end{cases}.\n",
99 | "\\end{equation}\n",
100 | "\n",
101 | "In order to find the option value, $V$, we need to discount the expected payoff\n",
102 | "\n",
103 | "\\begin{align}\n",
104 | " V &= e^{-rT} \\mathbb{E} \\left[ g(X_T) e^{- \\alpha X_T} \\, \\middle| \\; X_0 = 0 \\right] \\notag \\\\\n",
105 | " &= e^{-rT} \\int_{\\mathbb{R}} g(X_T) e^{- \\alpha X_T} f_X(x, T) dx\n",
106 | "\\end{align}\n",
107 | "\n",
108 | "where $e^{-\\alpha X_T}$ is the undamping factor and $f$ is the PDF of $X_t$.\n",
109 | "\n",
110 | "Thanks to the [Parseval-Plancherel theorem](#plancherel), this integral can be computed in Fourier space. Hence, we have\n",
111 | "\n",
112 | "\\begin{equation}\n",
113 | " V = \\frac{e^{-rT}}{2 \\pi} \\int_{\\mathbb{R}} \\hat{g}(\\xi) \\psi^*(\\xi + i \\alpha, T) d\\xi\n",
114 | "\\end{equation}\n",
115 | "\n",
116 | "where $\\psi(\\xi, t) = \\hat{f}_X(x, t)$ is the characteristic function of $X_t$ and * denotes the complex conjugate. Note that we can include the undamping factor in $\\psi^*(\\xi + i \\alpha, T)$ thanks to the [Shift theorem](#shift).\n",
117 | "\n",
118 | "## Implementation\n",
119 | "\n",
120 | "First, let's import some useful libraries."
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": 1,
126 | "id": "adequate-pillow",
127 | "metadata": {},
128 | "outputs": [],
129 | "source": [
130 | "import numpy as np\n",
131 | "from scipy.interpolate import interp1d"
132 | ]
133 | },
134 | {
135 | "cell_type": "markdown",
136 | "id": "enhanced-roommate",
137 | "metadata": {},
138 | "source": [
139 | "Let's implement a function which returns the damped payoff and its Fourier transform."
140 | ]
141 | },
142 | {
143 | "cell_type": "code",
144 | "execution_count": 2,
145 | "id": "fantastic-record",
146 | "metadata": {},
147 | "outputs": [],
148 | "source": [
149 | "# Function for the Fourier transform of the payoff\n",
150 | "def payoff(x, xi, alpha, K, L, U, C, call=1):\n",
151 | " \n",
152 | " # scale\n",
153 | " S = C*np.exp(x) \n",
154 | " \n",
155 | " # payoff\n",
156 | " if call == 1: # call\n",
157 | " g = np.exp(alpha*x) * np.maximum(S - K, 0) * (S>=L).astype(int) * (S<=U).astype(int)\n",
158 | " else: # put\n",
159 | " g = np.exp(alpha*x) * np.maximum(K - S, 0) * (S>=L).astype(int) * (S<=U).astype(int)\n",
160 | " \n",
161 | " # Analitical Fourier transform of the payoff\n",
162 | " l = np.log(L/C) # lower log barrier\n",
163 | " k = np.log(K/C) # log strike\n",
164 | " u = np.log(U/C) # upper log barrier\n",
165 | " \n",
166 | " # Integration bounds\n",
167 | " if call == 1:\n",
168 | " a = max(l, k)\n",
169 | " b = u\n",
170 | " else:\n",
171 | " a = min(k, u)\n",
172 | " b = l\n",
173 | " \n",
174 | " xi_2 = alpha + 1j*xi\n",
175 | " \n",
176 | " # Fourier transform of damped payoff\n",
177 | " with np.errstate(divide='ignore', invalid='ignore'): # disable warning for when alpha = 0\n",
178 | " G = C*((np.exp(b * (1 + xi_2)) - np.exp(a * (1 + xi_2))) / (1 + xi_2) \\\n",
179 | " - (np.exp(k + b*xi_2) - np.exp(k + a*xi_2)) / xi_2)\n",
180 | " \n",
181 | " # Eliminable discontinuities for xi = 0, otherwise 0/0 = NaN\n",
182 | " if alpha == 0:\n",
183 | " G[int(np.floor(len(G)/2))] = C*(np.exp(b)-np.exp(a)-np.exp(k)*(b-a))\n",
184 | " elif alpha == -1:\n",
185 | " G[int(np.floor(len(G)/2))] = C*(b-a+np.exp(k-b)-np.exp(k-a))\n",
186 | " \n",
187 | " return g, G, S"
188 | ]
189 | },
190 | {
191 | "cell_type": "markdown",
192 | "id": "significant-supply",
193 | "metadata": {},
194 | "source": [
195 | "Now, let's create a function which returns the call and put options prices using the Fourier transform method."
196 | ]
197 | },
198 | {
199 | "cell_type": "code",
200 | "execution_count": 3,
201 | "id": "incorporated-seller",
202 | "metadata": {},
203 | "outputs": [],
204 | "source": [
205 | "def fourier_pricing(S0, K, T, r, q, sigma, alpha, xwidth, ngrid):\n",
206 | " \n",
207 | " # Risk-neutral measure\n",
208 | " muRN = r-q-0.5*sigma**2 # drift\n",
209 | "\n",
210 | " # Fourier parameters\n",
211 | " xwidth = 6 # width of the support in real space\n",
212 | " ngrid = 2**8 # number of grid points\n",
213 | " alpha = -10 # damping factor for a call\n",
214 | "\n",
215 | " # Grids in real and Fourier space\n",
216 | " N = int(ngrid/2)\n",
217 | " b = xwidth/2 # upper bound of the support in real space\n",
218 | " dx = xwidth/ngrid\n",
219 | " x = dx * np.linspace(-N, N-1, 2*N)\n",
220 | " dxi = 2*np.pi/xwidth # Nyquist relation\n",
221 | " xi = dxi * np.linspace(-N, N-1, 2*N)\n",
222 | "\n",
223 | " # Characteristic function at time T for a call\n",
224 | " xia = xi + 1j*alpha \n",
225 | " psi = 1j*muRN*xia -0.5*(sigma*xia)**2 # characteristic exponent\n",
226 | " psi_c = np.exp(psi*T) # characteristic function\n",
227 | " \n",
228 | " # Characteristic function at time T for a put\n",
229 | " xia = xi - 1j*alpha # put\n",
230 | " psi = 1j*muRN*xia -0.5*(sigma*xia)**2 # characteristic exponent\n",
231 | " psi_p = np.exp(psi*T) # characteristic function\n",
232 | " \n",
233 | " # Fourier transform of the payoff\n",
234 | " U = S0 * np.exp(b)\n",
235 | " L = S0 * np.exp(-b)\n",
236 | " gc, Gc, S = payoff(x, xi, alpha, K, L, U, S0, 1) # call\n",
237 | " gp, Gp, S = payoff(x, xi, -alpha, K, L, U, S0, 0) # put\n",
238 | "\n",
239 | " # Discounted expected payoff computed with the Plancherel theorem \n",
240 | " c = np.exp(-r*T)*np.real(np.fft.fftshift(np.fft.fft(np.fft.ifftshift(Gc*np.conj(psi_c)))))/xwidth \n",
241 | " Vc = interp1d(S, c, kind='slinear')(S0) # Call value\n",
242 | " p = np.exp(-r*T)*np.real(np.fft.fftshift(np.fft.fft(np.fft.ifftshift(Gp*np.conj(psi_p)))))/xwidth \n",
243 | " Vp = interp1d(S, p, kind='slinear')(S0) # Put value\n",
244 | " \n",
245 | " return Vc, Vp"
246 | ]
247 | },
248 | {
249 | "cell_type": "markdown",
250 | "id": "opponent-reputation",
251 | "metadata": {},
252 | "source": [
253 | "Let's try the function with some parameters and print the prices of the call and the put."
254 | ]
255 | },
256 | {
257 | "cell_type": "code",
258 | "execution_count": 4,
259 | "id": "athletic-shark",
260 | "metadata": {},
261 | "outputs": [
262 | {
263 | "name": "stdout",
264 | "output_type": "stream",
265 | "text": [
266 | "The value of the call is 0.12965.\n",
267 | "The value of the put is 0.19581.\n"
268 | ]
269 | }
270 | ],
271 | "source": [
272 | "# Market parameters\n",
273 | "T = 1 # maturity\n",
274 | "S0 = 1 # spot price\n",
275 | "K = 1.1 # strike price\n",
276 | "r = 0.05 # risk-free interest rate\n",
277 | "q = 0.02 # dividend rate\n",
278 | "\n",
279 | "# Model parameter\n",
280 | "sigma = 0.4 # volatility\n",
281 | "\n",
282 | "# Fourier parameters\n",
283 | "xwidth = 6 # width of the support in real space\n",
284 | "ngrid = 2**8 # number of grid points\n",
285 | "alpha = -10 # damping factor for a call\n",
286 | "\n",
287 | "Vc, Vp = fourier_pricing(S0, K, T, r, q, sigma, alpha, xwidth, ngrid)\n",
288 | "\n",
289 | "print('The value of the call is ' + str(np.round(Vc, 5)) + '.')\n",
290 | "print('The value of the put is ' + str(np.round(Vp, 5)) + '.')\n"
291 | ]
292 | },
293 | {
294 | "cell_type": "markdown",
295 | "id": "correct-option",
296 | "metadata": {},
297 | "source": [
298 | "## Theorems\n",
299 | "\n",
300 | "### Parseval-Plancherel theorem\n",
301 | "\n",
302 | "\n",
303 | "\n",
304 | "The Parseval-Plancherel theorem states that\n",
305 | "\n",
306 | "\\begin{equation}\n",
307 | " \\int_{\\mathbb{R}} f(x)g^*(x) dx = \\frac{1}{2 \\pi} \\int_{\\mathbb{R}} \\hat{f}(\\xi)\\hat{g}^*(\\xi) d\\xi.\n",
308 | "\\end{equation}\n",
309 | "\n",
310 | "To prove the statement, we start by substituting in the LHS. We have\n",
311 | "\n",
312 | "\\begin{equation}\n",
313 | " f(x) = \\mathscr{F}_{\\xi \\to x}^{-1} [\\hat{f}(\\xi)] = \\frac{1}{2 \\pi} \\int_{\\mathbb{R}} e^{-i x \\xi} \\hat{f}(\\xi) d\\xi,\n",
314 | "\\end{equation}\n",
315 | "\n",
316 | "\\begin{equation}\n",
317 | " g(x) = \\mathscr{F}_{\\xi \\to x}^{-1} [\\hat{g}(\\xi)] = \\frac{1}{2 \\pi} \\int_{\\mathbb{R}} e^{-i x \\xi} \\hat{g}(\\xi) d\\xi.\n",
318 | "\\end{equation}\n",
319 | "\n",
320 | "Using the fact that $(ab)^* = a^*b^*$, $(e^{-i x \\xi})^* = e^{+i x \\xi}$ and we have\n",
321 | "\n",
322 | "\\begin{equation}\n",
323 | " g^*(x) = \\frac{1}{2 \\pi} \\int_{\\mathbb{R}} e^{i x \\xi} \\hat{g}^*(\\xi) d\\xi.\n",
324 | "\\end{equation}\n",
325 | "\n",
326 | "Therefore,\n",
327 | "\n",
328 | "\\begin{align}\n",
329 | " \\int_{\\mathbb{R}} f(x)g^*(x) dx &= \\frac{1}{(2 \\pi)^2} \\int_{\\mathbb{R}} \\left( \\int_{\\mathbb{R}} e^{-i x \\xi} \\hat{f}(\\xi) d\\xi \\right) \\left( \\int_{\\mathbb{R}} e^{i x \\xi'} \\hat{g}^*(\\xi') d\\xi' \\right) dx \\\\\n",
330 | " & = \\frac{1}{2 \\pi} \\int_{\\mathbb{R}} \\int_{\\mathbb{R}} \\hat{f}(\\xi) \\hat{g}^*(\\xi') \\frac{1}{2 \\pi} \\int_{\\mathbb{R}} e^{-i (\\xi - \\xi') x} dx d\\xi' d\\xi.\n",
331 | "\\end{align}\n",
332 | "\n",
333 | "Because\n",
334 | "\n",
335 | "\\begin{equation}\n",
336 | " \\frac{1}{2 \\pi} \\int_{\\mathbb{R}} e^{-i (\\xi - \\xi') x} dx = \\delta(\\xi - \\xi')\n",
337 | "\\end{equation}\n",
338 | "\n",
339 | "where $\\delta(.)$ is Dirac's delta function, we have\n",
340 | "\n",
341 | "\\begin{equation}\n",
342 | " \\int_{\\mathbb{R}} f(x)g^*(x) dx = \\frac{1}{2 \\pi} \\int_{\\mathbb{R}} \\hat{f}(\\xi) \\int_{\\mathbb{R}} \\hat{g}^*(\\xi') \\delta(\\xi - \\xi') d\\xi' d\\xi.\n",
343 | "\\end{equation}\n",
344 | "\n",
345 | "Finally, because \n",
346 | "\n",
347 | "\\begin{equation}\n",
348 | " \\int_{\\mathbb{R}} \\hat{g}^*(\\xi') \\delta(\\xi - \\xi') d\\xi' = \\hat{g}^*(\\xi),\n",
349 | "\\end{equation}\n",
350 | "\n",
351 | "we obtain \n",
352 | "\n",
353 | "\\begin{equation}\n",
354 | " \\int_{\\mathbb{R}} f(x)g^*(x) dx = \\frac{1}{2 \\pi} \\int_{\\mathbb{R}} \\hat{f}(\\xi)\\hat{g}^*(\\xi) d\\xi.\n",
355 | "\\end{equation}\n",
356 | "\n",
357 | "### Shift theorem\n",
358 | "\n",
359 | "\n",
360 | "\n",
361 | "The shift theorem states that \n",
362 | "\n",
363 | "\\begin{equation}\n",
364 | " \\mathscr{F}_{x \\to \\xi} [f(x)e^{- \\alpha x}] = \\hat{f} (\\xi + i \\alpha).\n",
365 | "\\end{equation}\n",
366 | "\n",
367 | "The proof is\n",
368 | "\n",
369 | "\\begin{equation}\n",
370 | " \\mathscr{F}_{x \\to \\xi} [f(x)e^{- \\alpha x}] = \\int_{\\mathbb{R}} e^{i \\xi x} e^{- \\alpha x} f(x) dx = \\int_{\\mathbb{R}} e^{i (\\xi + i \\alpha) x} f(x) dx = \\hat{f} (\\xi + i \\alpha)\n",
371 | "\\end{equation}\n",
372 | "\n",
373 | "where we used the fact that $-1 = i^2$.\n",
374 | "\n",
375 | "It can also be proved using the inverse Fourier tranform as\n",
376 | "\n",
377 | "\\begin{equation}\n",
378 | " \\mathscr{F}_{\\xi \\to x}^{-1} [\\hat{f} (\\xi + i \\alpha)] = \\frac{1}{2 \\pi} \\int_{\\mathbb{R}} e^{-i x \\xi} \\hat{f} (\\xi + i \\alpha) d\\xi = \\frac{e^{- \\alpha x}}{2 \\pi} \\int_{\\mathbb{R}} e^{-i x (\\xi + i \\alpha)} \\hat{f} (\\xi + i \\alpha) d(\\xi + i \\alpha) = \\frac{e^{- \\alpha x}}{2 \\pi} \\int_{\\mathbb{R}} e^{-i x \\xi'} \\hat{f} (\\xi') d\\xi' = f(x)e^{- \\alpha x}\n",
379 | "\\end{equation}\n",
380 | "\n",
381 | "where we used a change of variable."
382 | ]
383 | },
384 | {
385 | "cell_type": "code",
386 | "execution_count": null,
387 | "id": "verified-salmon",
388 | "metadata": {},
389 | "outputs": [],
390 | "source": []
391 | }
392 | ],
393 | "metadata": {
394 | "authors": [
395 | {
396 | "email": "robin.guilliou@gmail.com",
397 | "name": "Robin Guilliou"
398 | }
399 | ],
400 | "kernelspec": {
401 | "display_name": "Python 3",
402 | "language": "python",
403 | "name": "python3"
404 | },
405 | "language_info": {
406 | "codemirror_mode": {
407 | "name": "ipython",
408 | "version": 3
409 | },
410 | "file_extension": ".py",
411 | "mimetype": "text/x-python",
412 | "name": "python",
413 | "nbconvert_exporter": "python",
414 | "pygments_lexer": "ipython3",
415 | "version": "3.8.5"
416 | },
417 | "latex_envs": {
418 | "LaTeX_envs_menu_present": true,
419 | "autoclose": false,
420 | "autocomplete": true,
421 | "bibliofile": "biblio.bib",
422 | "cite_by": "apalike",
423 | "current_citInitial": 1,
424 | "eqLabelWithNumbers": true,
425 | "eqNumInitial": 1,
426 | "hotkeys": {
427 | "equation": "Ctrl-E",
428 | "itemize": "Ctrl-I"
429 | },
430 | "labels_anchors": false,
431 | "latex_user_defs": false,
432 | "report_style_numbering": false,
433 | "user_envs_cfg": false
434 | },
435 | "toc": {
436 | "base_numbering": 1,
437 | "nav_menu": {},
438 | "number_sections": true,
439 | "sideBar": true,
440 | "skip_h1_title": true,
441 | "title_cell": "Table of Contents",
442 | "title_sidebar": "Contents",
443 | "toc_cell": false,
444 | "toc_position": {},
445 | "toc_section_display": true,
446 | "toc_window_display": false
447 | },
448 | "varInspector": {
449 | "cols": {
450 | "lenName": 16,
451 | "lenType": 16,
452 | "lenVar": 40
453 | },
454 | "kernels_config": {
455 | "python": {
456 | "delete_cmd_postfix": "",
457 | "delete_cmd_prefix": "del ",
458 | "library": "var_list.py",
459 | "varRefreshCmd": "print(var_dic_list())"
460 | },
461 | "r": {
462 | "delete_cmd_postfix": ") ",
463 | "delete_cmd_prefix": "rm(",
464 | "library": "var_list.r",
465 | "varRefreshCmd": "cat(var_dic_list()) "
466 | }
467 | },
468 | "types_to_exclude": [
469 | "module",
470 | "function",
471 | "builtin_function_or_method",
472 | "instance",
473 | "_Feature"
474 | ],
475 | "window_display": false
476 | }
477 | },
478 | "nbformat": 4,
479 | "nbformat_minor": 5
480 | }
481 |
--------------------------------------------------------------------------------
/Exotics/barrier_pricing.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "sustained-filter",
6 | "metadata": {},
7 | "source": [
8 | "# Barrier options pricing\n",
9 | "\n",
10 | "## Analytical solutions\n",
11 | "\n",
12 | "### Vanilla options\n",
13 | "\n",
14 | "Assuming that the asset price at a future time follows a lognormal distribution, the price of vanilla European options is given by the Black-Scholes formulas as\n",
15 | "\n",
16 | "\\begin{align}\n",
17 | " &C = S_te^{-q\\tau} N(d_1) - Ke^{-r\\tau} N(d_2) \\\\\n",
18 | " &P = Ke^{-r\\tau} N(-d_2) - S_te^{-q\\tau} N(-d_1)\n",
19 | "\\end{align}\n",
20 | "\n",
21 | "where\n",
22 | "\n",
23 | "\\begin{align}\n",
24 | " d_1 &= \\frac{\\log \\frac{S_t}{K} + (r - q + \\frac{1}{2} \\sigma^2)\\tau}{\\sigma \\sqrt{\\tau}}, \\\\\n",
25 | " d_2 &= d_1 - \\sigma \\sqrt{\\tau},\n",
26 | "\\end{align}\n",
27 | "\n",
28 | "$C$ is the price of a call, $P$ is the price of a put, $K$ is the strike price, $r$ is the continuous risk-free rate, $q$ is the continuous dividend rate, $\\sigma$ is the volatility, $\\tau = T - t$ is the time to maturity and $N(x)$ is the cumulative standard normal distribution function defined as\n",
29 | "\n",
30 | "\\begin{equation}\n",
31 | " N(x) = \\frac{1}{\\sqrt{2\\pi}} \\int_{-\\infty}^x e^{-\\frac{1}{2} \\phi^2} d\\phi.\n",
32 | "\\end{equation}\n",
33 | "\n",
34 | "### Barrier options with continuous monitoring\n",
35 | "\n",
36 | "Barrier options are path dependent options whose payoff depends on whether the underlying asset's price has reached a barrier during the life of the contract. Knock-out options expire worthless if the barrier has been reached while knock-in options come into existence only if the barrier has been reached. Down options have a barrier level that is below the underlying price while up options have a barrier level above the underlying price. \n",
37 | "\n",
38 | "The following analytical formulas assume that the underlying price is observed continuously. Single barrier European options are considered.\n",
39 | "\n",
40 | "#### Call options\n",
41 | "\n",
42 | "When the barrier price, $H$, is lower than or equal to the strike price, $K$, a down and in call can be priced as\n",
43 | "\n",
44 | "\\begin{equation}\n",
45 | " C_{di} = S_t e^{-q \\tau} \\left( \\frac{H}{S_t} \\right)^{2 \\gamma} N(\\eta) - K e^{-r \\tau} \\left( \\frac{H}{S_t} \\right)^{2 \\gamma - 2} N \\left(\\eta - \\sigma \\sqrt{\\tau}\\right)\n",
46 | "\\end{equation}\n",
47 | "\n",
48 | "where\n",
49 | "\n",
50 | "\\begin{equation}\n",
51 | " \\gamma = \\frac{r - q + \\frac{1}{2} \\sigma^2}{\\sigma^2}\n",
52 | "\\end{equation}\n",
53 | "\n",
54 | "and\n",
55 | "\n",
56 | "\\begin{equation}\n",
57 | " \\eta = \\frac{\\log \\left(\\frac{H^2}{S_tK} \\right)}{\\sigma \\sqrt{\\tau}} + \\gamma \\sigma \\sqrt{\\tau}.\n",
58 | "\\end{equation}\n",
59 | "\n",
60 | "The value of a vanilla call is equal to the value of a down-and-in call plus the value of a down-and-out call. Therefore, we can price the corresponding down-and-out call as\n",
61 | "\n",
62 | "\\begin{equation}\n",
63 | " C_{do} = C - C_{di}. \n",
64 | "\\end{equation}\n",
65 | "\n",
66 | "If $H \\geq K$, the value of the down-and-out call is calculated as\n",
67 | "\n",
68 | "\\begin{equation}\n",
69 | " C_{do} = S_t e^{-q\\tau} N(\\nu) - Ke^{-r\\tau} N \\left(\\nu - \\sigma \\sqrt{\\tau}\\right) - S_t e^{-q\\tau} \\left( \\frac{H}{S_t} \\right)^{2 \\gamma} N(\\lambda) + K e^{-r\\tau} \\left( \\frac{H}{S_t} \\right)^{2 \\gamma - 2} N\\left( \\lambda - \\sigma \\sqrt{\\tau} \\right)\n",
70 | "\\end{equation}\n",
71 | "\n",
72 | "where \n",
73 | "\n",
74 | "\\begin{equation}\n",
75 | " \\nu = \\frac{\\log \\left( \\frac{S_t}{H} \\right)}{\\sigma \\sqrt{\\tau}} + \\gamma \\sigma \\sqrt{\\tau}\n",
76 | "\\end{equation}\n",
77 | "\n",
78 | "and \n",
79 | "\n",
80 | "\\begin{equation}\n",
81 | " \\lambda = \\frac{\\log \\left( \\frac{H}{S_t} \\right)}{\\sigma \\sqrt{\\tau}} + \\gamma \\sigma \\sqrt{\\tau}.\n",
82 | "\\end{equation}\n",
83 | "\n",
84 | "We can price the corresponding down-and-in call as\n",
85 | "\n",
86 | "\\begin{equation}\n",
87 | " C_{di} = C - C_{do}. \n",
88 | "\\end{equation}\n",
89 | "\n",
90 | "When $H \\leq K$, pricing up-and-in and up-and-out calls is trivial. We have\n",
91 | "\n",
92 | "\\begin{align}\n",
93 | " C_{uo} = 0, \\\\\n",
94 | " C_{ui} = C.\n",
95 | "\\end{align}\n",
96 | "\n",
97 | "When $H \\geq K$, we have\n",
98 | "\n",
99 | "\\begin{equation}\n",
100 | " C_{ui} = S_t e^{-q\\tau} N(\\nu) - K e^{-r\\tau} N \\left( \\nu - \\sigma \\sqrt{\\tau} \\right) - S_t e^{-q\\tau} \\left( \\frac{H}{S_t} \\right)^{2 \\gamma} [N(-\\eta) - N(-\\lambda) ] + K e^{-r\\tau} \\left( \\frac{H}{S_t} \\right)^{2 \\gamma - 2} [N(-\\eta + \\sigma \\sqrt{\\tau}) - N(-\\lambda + \\sigma \\sqrt{\\tau})] \n",
101 | "\\end{equation}\n",
102 | "\n",
103 | "and\n",
104 | "\n",
105 | "\\begin{equation}\n",
106 | " C_{uo} = C - C_{ui}.\n",
107 | "\\end{equation}\n",
108 | "\n",
109 | "#### Put options\n",
110 | "\n",
111 | "When $H \\geq K$, \n",
112 | "\n",
113 | "\\begin{equation}\n",
114 | " P_{ui} = -S_t e^{-q\\tau} \\left( \\frac{H}{S_t} \\right)^{2 \\gamma} N(-\\eta) + K e^{-r\\tau} \\left( \\frac{H}{S_t} \\right)^{2 \\gamma - 2} N(- \\eta + \\sigma \\sqrt{\\tau})\n",
115 | "\\end{equation}\n",
116 | "\n",
117 | "and \n",
118 | "\n",
119 | "\\begin{equation}\n",
120 | " P_{uo} = P - P_{ui}.\n",
121 | "\\end{equation}\n",
122 | "\n",
123 | "When $H \\leq K$, \n",
124 | "\n",
125 | "\\begin{equation}\n",
126 | " P_{uo} = -S_t e^{-q \\tau} N(-\\nu) + K e^{-r\\tau} N(- \\nu + \\sigma \\sqrt{\\tau}) + S_t e^{-q\\tau} \\left( \\frac{H}{S_t} \\right)^{2 \\gamma} N(-\\lambda) - K e^{-r\\tau} \\left( \\frac{H}{S_t} \\right)^{2 \\gamma - 2} N(-\\lambda + \\sigma \\sqrt{\\tau})\n",
127 | "\\end{equation}\n",
128 | "\n",
129 | "and \n",
130 | "\n",
131 | "\\begin{equation}\n",
132 | " P_{ui} = P - P_{uo}.\n",
133 | "\\end{equation}\n",
134 | "\n",
135 | "When $H \\geq K$,\n",
136 | "\n",
137 | "\\begin{align}\n",
138 | " P_{di} = P, \\\\\n",
139 | " P_{do} = 0.\n",
140 | "\\end{align}\n",
141 | "\n",
142 | "When $H \\leq K$, \n",
143 | "\n",
144 | "\\begin{equation}\n",
145 | " P_{di} = -S_t e^{-q\\tau} N(-\\nu) + K e^{-r\\tau} N(-\\nu + \\sigma \\sqrt{\\tau}) + S_t e^{-q \\tau} \\left( \\frac{H}{S_t} \\right)^{2 \\gamma} [N(\\eta) - N(\\lambda)] - K e^{-r\\tau} \\left( \\frac{H}{S_t} \\right)^{2 \\gamma - 2} [N(\\eta - \\sigma \\sqrt{\\tau}) - N(\\lambda - \\sigma \\sqrt{\\tau})]\n",
146 | "\\end{equation}\n",
147 | "\n",
148 | "and \n",
149 | "\n",
150 | "\\begin{equation}\n",
151 | " P_{do} = P - P_{di}.\n",
152 | "\\end{equation}\n",
153 | "\n",
154 | "Of course, at $t=0$, when $H \\leq S_t$, the value of $C_{ui} = C$ and the value of $C_{uo} = 0$. This is because the barrier is already reached. Likewise, when $H \\geq S_t$, $P_{di} = P$ and $P_{do} = 0$.\n",
155 | "\n",
156 | "### Barrier options with discrete monitoring\n",
157 | "\n",
158 | "Often, the price observation (checking whether the barrier has been reached) is done periodically, i.e., once a day. In [This paper](http://www.columbia.edu/~sk75/mfBGK.pdf), Broadie, Glasserman, and Kou propose a method to adjust the formulas. Instead of using the barrier $H$, an adjusted barrier is used. The adjusted barrier, $H_{adj}$, is given by\n",
159 | "\n",
160 | "\\begin{equation}\n",
161 | " H_{adj} = H \\exp \\left(\\text{sign}(H - S_t) \\beta \\sigma \\sqrt{\\frac{T}{m}} \\right)\n",
162 | "\\end{equation}\n",
163 | "\n",
164 | "where $m$ (```n_obs``` in the code) is the number of observations (i.e., 250 for daily observations assuming 250 trading days per year and $T$ is one year) and\n",
165 | "\n",
166 | "\\begin{equation}\n",
167 | " \\beta = - \\frac{\\zeta \\left(\\frac{1}{2} \\right)}{\\sqrt{2 \\pi}} \\approx 0.5826\n",
168 | "\\end{equation}\n",
169 | "\n",
170 | "with $\\zeta(\\,.)$ being the Riemann Zeta function."
171 | ]
172 | },
173 | {
174 | "cell_type": "code",
175 | "execution_count": 3,
176 | "id": "worst-legislature",
177 | "metadata": {},
178 | "outputs": [
179 | {
180 | "name": "stdout",
181 | "output_type": "stream",
182 | "text": [
183 | "Down-and-in call: 2.9394\n",
184 | "Down-and-out call: 0\n",
185 | "Up-and-in call: 2.7636\n",
186 | "Up-and-out call: 0.1758\n",
187 | "Down-and-in put: 11.5768\n",
188 | "Down-and-out put: 0\n",
189 | "Up-and-in put: 0.3341\n",
190 | "Up-and-out put: 11.2427\n"
191 | ]
192 | }
193 | ],
194 | "source": [
195 | "import numpy as np\n",
196 | "from scipy.stats import norm\n",
197 | "\n",
198 | "# Function to price continuously monitored barrier options with closed-form solutions.\n",
199 | "def barrier_analytical(S, K, H, T, r, q, sigma, t=0, n_obs=-1):\n",
200 | " \n",
201 | " \"\"\" Use n_obs=-1 for continuous monitoring \"\"\"\n",
202 | " \n",
203 | " tau = T - t\n",
204 | " # Black Scholes call and put prices\n",
205 | " d1 = (np.log(S/K) + (r-q + 0.5 * sigma**2) * tau) / (sigma * np.sqrt(tau))\n",
206 | " d2 = (np.log(S/K) + (r-q - 0.5 * sigma**2) * tau) / (sigma * np.sqrt(tau))\n",
207 | " C = S * np.exp(-q*tau) * norm.cdf(d1) - K * np.exp(-r*tau) * norm.cdf(d2)\n",
208 | " P = K * np.exp(-r*tau) * norm.cdf(-d2) - S * np.exp(-q*tau) * norm.cdf(-d1)\n",
209 | " \n",
210 | " # Adjustment to barrier for discrete monitoring\n",
211 | " if n_obs > 0:\n",
212 | " H = H*np.exp(np.sign(H-S0)*0.5826*sigma*np.sqrt(T/n_obs))\n",
213 | " \n",
214 | " # Parameters\n",
215 | " gamma = (r - q + 0.5*sigma**2) / sigma**2\n",
216 | " eta = np.log((H**2)/(S*K)) / (sigma*np.sqrt(tau)) + gamma*sigma*np.sqrt(tau)\n",
217 | " nu = np.log(S/H) / (sigma*np.sqrt(tau)) + gamma*sigma*np.sqrt(tau)\n",
218 | " lmbda = np.log(H/S) / (sigma*np.sqrt(tau)) + gamma*sigma*np.sqrt(tau)\n",
219 | " \n",
220 | " if H < K:\n",
221 | " # calls\n",
222 | " C_di = S*np.exp(-q*tau) * (H/S)**(2*gamma) * norm.cdf(eta) \\\n",
223 | " - K*np.exp(-r*tau) * (H/S)**(2*gamma-2) * norm.cdf(eta - sigma*np.sqrt(tau))\n",
224 | " C_do = C - C_di\n",
225 | " C_uo = 0\n",
226 | " C_ui = C\n",
227 | " # puts\n",
228 | " if H <= S:\n",
229 | " P_ui = P\n",
230 | " P_uo = 0\n",
231 | " else:\n",
232 | " P_uo = - S*np.exp(-q*tau) * norm.cdf(-nu) + K*np.exp(-r*tau) * norm.cdf(-nu + sigma*np.sqrt(tau)) \\\n",
233 | " + S*np.exp(-q*tau) * (H/S)**(2*gamma) * norm.cdf(-lmbda) \\\n",
234 | " - K*np.exp(-r*tau) * (H/S)**(2*gamma-2) * norm.cdf(-lmbda + sigma*np.sqrt(tau))\n",
235 | " P_ui = P - P_uo\n",
236 | " P_di = - S*np.exp(-q*tau) * norm.cdf(-nu) + K*np.exp(-r*tau) * norm.cdf(-nu + sigma*np.sqrt(tau)) \\\n",
237 | " + S*np.exp(-q*tau) * (H/S)**(2*gamma) * (norm.cdf(eta)-norm.cdf(lmbda)) \\\n",
238 | " - K*np.exp(-r*tau) * (H/S)**(2*gamma-2) * (norm.cdf(eta-sigma*np.sqrt(tau))-norm.cdf(lmbda-sigma*np.sqrt(tau)))\n",
239 | " P_do = P - P_di\n",
240 | " elif H >= K:\n",
241 | " # calls\n",
242 | " if H >= S:\n",
243 | " C_di = C\n",
244 | " C_do = 0\n",
245 | " else:\n",
246 | " C_do = S*np.exp(-q*tau) * norm.cdf(nu) - K*np.exp(-r*tau) * norm.cdf(nu-sigma*np.sqrt(tau)) \\\n",
247 | " - S*np.exp(-q*tau) * (H/S)**(2*gamma) * norm.cdf(lmbda) \\\n",
248 | " + K*np.exp(-r*tau) * (H/S)**(2*gamma-2) * norm.cdf(lmbda-sigma*np.sqrt(tau))\n",
249 | " C_di = C - C_do\n",
250 | " C_ui = S*np.exp(-q*tau) * norm.cdf(nu) - K*np.exp(-r*tau) * norm.cdf(nu-sigma*np.sqrt(tau)) \\\n",
251 | " - S*np.exp(-q*tau) * (H/S)**(2*gamma) * (norm.cdf(-eta)-norm.cdf(-lmbda)) \\\n",
252 | " + K*np.exp(-r*tau) * (H/S)**(2*gamma-2) * (norm.cdf(-eta+sigma*np.sqrt(tau))-norm.cdf(-lmbda+sigma*np.sqrt(tau))) \n",
253 | " C_uo = C - C_ui\n",
254 | " # puts\n",
255 | " P_ui = - S*np.exp(-q*tau) * (H/S)**(2*gamma) * norm.cdf(-eta) \\\n",
256 | " + K*np.exp(-r*tau) * (H/S)**(2*gamma-2) * norm.cdf(-eta + sigma*np.sqrt(tau))\n",
257 | " P_uo = P - P_ui\n",
258 | " P_di = P\n",
259 | " P_do = 0\n",
260 | " \n",
261 | " return C_di, C_do, C_ui, C_uo, P_di, P_do, P_ui, P_uo \n",
262 | " \n",
263 | "# Parameters\n",
264 | "T = 1 # maturity (years)\n",
265 | "S0 = 50 # spot price\n",
266 | "K = 60 # strike price\n",
267 | "H = 70 # Barrier\n",
268 | "r = 0.04 # risk-free interest rate\n",
269 | "q = 0.02 # dividend rate\n",
270 | "sigma = 0.3 # volatility\n",
271 | "\n",
272 | "# Option prices\n",
273 | "C_di, C_do, C_ui, C_uo, P_di, P_do, P_ui, P_uo = barrier_analytical(S0, K, H, T, r, q, sigma, 0, n_obs=-1)\n",
274 | "\n",
275 | "print('Down-and-in call: ' + str(round(C_di, 4)))\n",
276 | "print('Down-and-out call: ' + str(round(C_do, 4)))\n",
277 | "print('Up-and-in call: ' + str(round(C_ui, 4)))\n",
278 | "print('Up-and-out call: ' + str(round(C_uo, 4)))\n",
279 | "print('Down-and-in put: ' + str(round(P_di, 4)))\n",
280 | "print('Down-and-out put: ' + str(round(P_do, 4)))\n",
281 | "print('Up-and-in put: ' + str(round(P_ui, 4)))\n",
282 | "print('Up-and-out put: ' + str(round(P_uo, 4)))"
283 | ]
284 | },
285 | {
286 | "cell_type": "markdown",
287 | "id": "architectural-twins",
288 | "metadata": {},
289 | "source": [
290 | "## Monte Carlo\n",
291 | "\n",
292 | "The value of an option is the discounted value of the expected payoff under a risk-neutral measure. Therefore, we can price the option by simulating many sample price paths, and taking the average of the discounted payoff for each path. The drawback of this method is that it is relatively slow as many paths need to be simulated to get accurate results. Moreover, as barrier options are path-dependent, the whole path needs to be simulated (not just the terminal value).\n",
293 | "\n",
294 | "To sample paths are generated using the Euler-Maruyama scheme. The stock price at time the next time step, $S_{t + dt}$, is given by\n",
295 | "\n",
296 | "\\begin{equation}\n",
297 | " S_{t + dt} = S_t \\exp \\left( \\Big(r - q - \\frac{1}{2} \\sigma^2 \\Big)dt + \\sigma \\phi \\sqrt{dt}\\right)\n",
298 | "\\end{equation}\n",
299 | "\n",
300 | "where $\\phi \\sim \\mathcal{N}(0, 1)$ is a standard normal random variable and $dt$ is the time step.\n",
301 | "\n",
302 | "Depending on whether the barrier is reached during the life of the option and the option type (knock-in, knock-out...), we adjust the payoff at time $T$. Then, we simply average and discount these sample payoffs to get the option price.\n",
303 | "\n",
304 | "Because the stock prices are simulated at discrete time intervals, the monitoring is not continuous. There is a non-zero probability that the barrier is reached between the observation times. The resulting option price is therefore the price of a discretely monitored barrier option. The price is monitored at time intervals $dt = \\frac{T}{m}$. \n",
305 | "\n",
306 | "The barrier adjustment for continuous monitoring is\n",
307 | "\n",
308 | "\\begin{equation}\n",
309 | " H_{adj} = H \\exp \\left(-\\text{sign}(H - S_0) \\beta \\sigma \\sqrt{dt} \\right).\n",
310 | "\\end{equation}\n"
311 | ]
312 | },
313 | {
314 | "cell_type": "code",
315 | "execution_count": 4,
316 | "id": "passive-tunisia",
317 | "metadata": {},
318 | "outputs": [
319 | {
320 | "name": "stdout",
321 | "output_type": "stream",
322 | "text": [
323 | "Down-and-in call: 2.9367\n",
324 | "Down-and-out call: 0.0\n",
325 | "Up-and-in call: 2.7633\n",
326 | "Up-and-out call: 0.1734\n",
327 | "Down-and-in put: 11.5821\n",
328 | "Down-and-out put: 0.0\n",
329 | "Up-and-in put: 0.3337\n",
330 | "Up-and-out put: 11.2484\n"
331 | ]
332 | }
333 | ],
334 | "source": [
335 | "def barrier_mc(S, K, H, T, r, q, sigma, nblocks, nsample, nsteps, cts=False):\n",
336 | " \n",
337 | " \"\"\" Set cts=True for continous monitoring \"\"\"\n",
338 | " \n",
339 | " # Time step\n",
340 | " dt = T/nsteps\n",
341 | " \n",
342 | " # Initialize arrays\n",
343 | " C_ui = np.zeros(nblocks)\n",
344 | " C_uo = np.zeros(nblocks)\n",
345 | " C_di = np.zeros(nblocks)\n",
346 | " C_do = np.zeros(nblocks)\n",
347 | " P_ui = np.zeros(nblocks)\n",
348 | " P_uo = np.zeros(nblocks)\n",
349 | " P_di = np.zeros(nblocks)\n",
350 | " P_do = np.zeros(nblocks)\n",
351 | " \n",
352 | " # Adjustment to barrier for continuous monitoring\n",
353 | " if cts == True:\n",
354 | " H = H*np.exp(-np.sign(H-S0)*0.5826*sigma*np.sqrt(dt))\n",
355 | " \n",
356 | " # Monte carlo\n",
357 | " for i in range(nblocks):\n",
358 | " # Compute the increments of the arithmetic brownian motion X = log(S/S0)\n",
359 | " dX = (r-q - 0.5*sigma**2)*dt + sigma*np.sqrt(dt)*np.random.normal(size=(nsample, nsteps))\n",
360 | " \n",
361 | " # Accumulate the increments starting at 0\n",
362 | " X = np.concatenate((np.zeros((nsample, 1)), np.cumsum(dX, axis=1)), axis=1)\n",
363 | " \n",
364 | " # Transform to geometric Brownian motion\n",
365 | " S = S0*np.exp(X)\n",
366 | " \n",
367 | " # Check if barrier has been reached\n",
368 | " mask_u = np.sum(S >= H, axis=1)\n",
369 | " mask_u[mask_u > 0] = 1\n",
370 | " mask_d = np.sum(S <= H, axis=1)\n",
371 | " mask_d[mask_d > 0] = 1\n",
372 | " \n",
373 | " # Compute prices for each block\n",
374 | " C_ui[i] = np.exp(-r*T) * np.mean(np.maximum(S[:,-1] - K, 0) * mask_u)\n",
375 | " C_uo[i] = np.exp(-r*T) * np.mean(np.maximum(S[:,-1] - K, 0) * (1 - mask_u))\n",
376 | " C_di[i] = np.exp(-r*T) * np.mean(np.maximum(S[:,-1] - K, 0) * mask_d)\n",
377 | " C_do[i] = np.exp(-r*T) * np.mean(np.maximum(S[:,-1] - K, 0) * (1 - mask_d))\n",
378 | " P_ui[i] = np.exp(-r*T) * np.mean(np.maximum(K - S[:,-1], 0) * mask_u)\n",
379 | " P_uo[i] = np.exp(-r*T) * np.mean(np.maximum(K - S[:,-1], 0) * (1 - mask_u))\n",
380 | " P_di[i] = np.exp(-r*T) * np.mean(np.maximum(K - S[:,-1], 0) * mask_d)\n",
381 | " P_do[i] = np.exp(-r*T) * np.mean(np.maximum(K - S[:,-1], 0) * (1 - mask_d))\n",
382 | " \n",
383 | " # Compute prices (average of all block) \n",
384 | " C_ui = np.mean(C_ui)\n",
385 | " C_uo = np.mean(C_uo)\n",
386 | " C_di = np.mean(C_di)\n",
387 | " C_do = np.mean(C_do)\n",
388 | " P_ui = np.mean(P_ui)\n",
389 | " P_uo = np.mean(P_uo)\n",
390 | " P_di = np.mean(P_di)\n",
391 | " P_do = np.mean(P_do)\n",
392 | " \n",
393 | " return C_di, C_do, C_ui, C_uo, P_di, P_do, P_ui, P_uo\n",
394 | "\n",
395 | "# Parameters\n",
396 | "T = 1 # maturity\n",
397 | "S0 = 50 # spot price\n",
398 | "K = 60 # strike price\n",
399 | "H = 70 # Barrier\n",
400 | "r = 0.04 # risk-free interest rate\n",
401 | "q = 0.02 # dividend rate\n",
402 | "sigma = 0.3 # volatility\n",
403 | "nblocks = 500 # number of blocks\n",
404 | "nsample = 10000 # number of samples per block\n",
405 | "nsteps = 250 # number of time steps\n",
406 | "\n",
407 | "# Compute the barrier options prices\n",
408 | "C_di_mc, C_do_mc, C_ui_mc, C_uo_mc, P_di_mc, \\\n",
409 | "P_do_mc, P_ui_mc, P_uo_mc = barrier_mc(S0, K, H, T, r, q, sigma, nblocks, nsample, nsteps, cts=True)\n",
410 | "\n",
411 | "print('Down-and-in call: ' + str(round(C_di_mc, 4)))\n",
412 | "print('Down-and-out call: ' + str(round(C_do_mc, 4)))\n",
413 | "print('Up-and-in call: ' + str(round(C_ui_mc, 4)))\n",
414 | "print('Up-and-out call: ' + str(round(C_uo_mc, 4)))\n",
415 | "print('Down-and-in put: ' + str(round(P_di_mc, 4)))\n",
416 | "print('Down-and-out put: ' + str(round(P_do_mc, 4)))\n",
417 | "print('Up-and-in put: ' + str(round(P_ui_mc, 4)))\n",
418 | "print('Up-and-out put: ' + str(round(P_uo_mc, 4)))"
419 | ]
420 | },
421 | {
422 | "cell_type": "markdown",
423 | "id": "social-sailing",
424 | "metadata": {},
425 | "source": [
426 | "The accuracy of the Monte Carlo simulation can be improved by increasing the number of paths (```nblocks``` $\\times$ ```nsample```) or by using variance reduction techniques (e.g., antithetic variates)."
427 | ]
428 | },
429 | {
430 | "cell_type": "code",
431 | "execution_count": null,
432 | "id": "potential-newark",
433 | "metadata": {},
434 | "outputs": [],
435 | "source": []
436 | }
437 | ],
438 | "metadata": {
439 | "authors": [
440 | {
441 | "email": "robin.guilliou@gmail.com",
442 | "name": "Robin Guilliou"
443 | }
444 | ],
445 | "kernelspec": {
446 | "display_name": "Python 3 (ipykernel)",
447 | "language": "python",
448 | "name": "python3"
449 | },
450 | "language_info": {
451 | "codemirror_mode": {
452 | "name": "ipython",
453 | "version": 3
454 | },
455 | "file_extension": ".py",
456 | "mimetype": "text/x-python",
457 | "name": "python",
458 | "nbconvert_exporter": "python",
459 | "pygments_lexer": "ipython3",
460 | "version": "3.7.11"
461 | },
462 | "latex_envs": {
463 | "LaTeX_envs_menu_present": true,
464 | "autoclose": false,
465 | "autocomplete": true,
466 | "bibliofile": "biblio.bib",
467 | "cite_by": "apalike",
468 | "current_citInitial": 1,
469 | "eqLabelWithNumbers": true,
470 | "eqNumInitial": 1,
471 | "hotkeys": {
472 | "equation": "Ctrl-E",
473 | "itemize": "Ctrl-I"
474 | },
475 | "labels_anchors": false,
476 | "latex_user_defs": false,
477 | "report_style_numbering": false,
478 | "user_envs_cfg": false
479 | },
480 | "toc": {
481 | "base_numbering": 1,
482 | "nav_menu": {},
483 | "number_sections": true,
484 | "sideBar": true,
485 | "skip_h1_title": true,
486 | "title_cell": "Table of Contents",
487 | "title_sidebar": "Contents",
488 | "toc_cell": false,
489 | "toc_position": {},
490 | "toc_section_display": true,
491 | "toc_window_display": false
492 | },
493 | "varInspector": {
494 | "cols": {
495 | "lenName": 16,
496 | "lenType": 16,
497 | "lenVar": 40
498 | },
499 | "kernels_config": {
500 | "python": {
501 | "delete_cmd_postfix": "",
502 | "delete_cmd_prefix": "del ",
503 | "library": "var_list.py",
504 | "varRefreshCmd": "print(var_dic_list())"
505 | },
506 | "r": {
507 | "delete_cmd_postfix": ") ",
508 | "delete_cmd_prefix": "rm(",
509 | "library": "var_list.r",
510 | "varRefreshCmd": "cat(var_dic_list()) "
511 | }
512 | },
513 | "types_to_exclude": [
514 | "module",
515 | "function",
516 | "builtin_function_or_method",
517 | "instance",
518 | "_Feature"
519 | ],
520 | "window_display": false
521 | }
522 | },
523 | "nbformat": 4,
524 | "nbformat_minor": 5
525 | }
526 |
--------------------------------------------------------------------------------
/European Options/Merton Jump Diffusion/merton_jump_fourier.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "polish-twist",
6 | "metadata": {},
7 | "source": [
8 | "# Merton Jump Diffusion: Option pricing with Fourier transform\n",
9 | "\n",
10 | "## Mathematics\n",
11 | "\n",
12 | "The mathematics behind option pricing using the Fourier transform method are detailed in the notebook on Fourier transform pricing with the Black-Scholes model. Because the method is very similar with a Merton jump diffusion model, we will only explain the key differences here and you can refer to the other notebook for detailed mathematics. \n",
13 | "\n",
14 | "The main difference is the characteristic function of the process. The Merton jump diffusion process is obtained by adding a normal compound Poisson process to the geometric Brownian motion. The resulting characteristic function is given by\n",
15 | "\n",
16 | "\\begin{equation}\n",
17 | " \\psi(\\xi) = \\exp \\left[ i \\xi \\left(r - q - \\frac{1}{2} \\sigma^2 - \\lambda \\left(e^{i \\xi \\mu_J + \\frac{1}{2} \\xi^2 \\sigma_J^2} - 1 \\right) \\right) \\Delta t - \\frac{1}{2} \\xi^2 \\sigma^2 \\Delta t + \\lambda \\left(e^{i \\xi \\mu_J - \\frac{1}{2} \\xi^2 \\sigma_J^2} - 1 \\right) \\Delta t \\right]\n",
18 | "\\end{equation}\n",
19 | "\n",
20 | "where $\\sigma$ is the stock price volatility, $r$ is the risk-free interest rate, $q$ is the dividend rate, $\\lambda$ is the rate of arrival of the jumps, $\\mu_J$ is the mean of the jump sizes, $\\sigma_J$ is the volatility of the jump sizes and $i$ is the imaginary unit such that $i = \\sqrt{-1}$.\n",
21 | "\n",
22 | "## Implementation\n",
23 | "\n",
24 | "First, let's import some useful libraries."
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": 1,
30 | "id": "seven-attendance",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "import numpy as np\n",
35 | "import matplotlib.pyplot as plt\n",
36 | "from scipy.interpolate import interp1d"
37 | ]
38 | },
39 | {
40 | "cell_type": "markdown",
41 | "id": "musical-healthcare",
42 | "metadata": {},
43 | "source": [
44 | "Let's implement a function which returns the damped payoff and its Fourier transform."
45 | ]
46 | },
47 | {
48 | "cell_type": "code",
49 | "execution_count": 2,
50 | "id": "endless-edition",
51 | "metadata": {},
52 | "outputs": [],
53 | "source": [
54 | "# Function for the Fourier transform of the payoff\n",
55 | "def payoff(x, xi, alpha, K, L, U, C, call=1):\n",
56 | " \n",
57 | " # scale\n",
58 | " S = C*np.exp(x) \n",
59 | " \n",
60 | " # payoff\n",
61 | " if call == 1: # call\n",
62 | " g = np.exp(alpha*x) * np.maximum(S - K, 0) * (S>=L).astype(int) * (S<=U).astype(int)\n",
63 | " else: # put\n",
64 | " g = np.exp(alpha*x) * np.maximum(K - S, 0) * (S>=L).astype(int) * (S<=U).astype(int)\n",
65 | " \n",
66 | " # Analitical Fourier transform of the payoff\n",
67 | " l = np.log(L/C) # lower log barrier\n",
68 | " k = np.log(K/C) # log strike\n",
69 | " u = np.log(U/C) # upper log barrier\n",
70 | " \n",
71 | " # Integration bounds\n",
72 | " if call == 1:\n",
73 | " a = max(l, k)\n",
74 | " b = u\n",
75 | " else:\n",
76 | " a = min(k, u)\n",
77 | " b = l\n",
78 | " \n",
79 | " xi_2 = alpha + 1j*xi\n",
80 | " \n",
81 | " # Fourier transform of damped payoff\n",
82 | " with np.errstate(divide='ignore', invalid='ignore'): # disable warning for when alpha = 0\n",
83 | " G = C*((np.exp(b * (1 + xi_2)) - np.exp(a * (1 + xi_2))) / (1 + xi_2) \\\n",
84 | " - (np.exp(k + b*xi_2) - np.exp(k + a*xi_2)) / xi_2)\n",
85 | " \n",
86 | " # Eliminable discontinuities for xi = 0, otherwise 0/0 = NaN\n",
87 | " if alpha == 0:\n",
88 | " G[int(np.floor(len(G)/2))] = C*(np.exp(b)-np.exp(a)-np.exp(k)*(b-a))\n",
89 | " elif alpha == -1:\n",
90 | " G[int(np.floor(len(G)/2))] = C*(b-a+np.exp(k-b)-np.exp(k-a))\n",
91 | " \n",
92 | " return g, G, S"
93 | ]
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "id": "median-harris",
98 | "metadata": {},
99 | "source": [
100 | "Now, let's define some parameters and compute the call and put prices."
101 | ]
102 | },
103 | {
104 | "cell_type": "code",
105 | "execution_count": 3,
106 | "id": "democratic-lease",
107 | "metadata": {},
108 | "outputs": [
109 | {
110 | "name": "stdout",
111 | "output_type": "stream",
112 | "text": [
113 | "The value of the call is 0.13617.\n",
114 | "The value of the put is 0.20232.\n"
115 | ]
116 | }
117 | ],
118 | "source": [
119 | "# Market parameters\n",
120 | "T = 1 # maturity\n",
121 | "S0 = 1 # spot price\n",
122 | "K = 1.1 # strike price\n",
123 | "r = 0.05 # risk-free interest rate\n",
124 | "q = 0.02 # dividend rate\n",
125 | "\n",
126 | "# Model parameter\n",
127 | "sigma = 0.4 # volatility\n",
128 | "\n",
129 | "# Model parameters for the jump part\n",
130 | "mu_j = -0.1\n",
131 | "sigma_j = 0.15\n",
132 | "lmbda = 0.5\n",
133 | "\n",
134 | "# Risk-neutral measure\n",
135 | "muRN = r-q-0.5*sigma**2 - lmbda*(np.exp(mu_j + 0.5*sigma_j**2) - 1) # drift\n",
136 | "\n",
137 | "# Fourier parameters\n",
138 | "xwidth = 6 # width of the support in real space\n",
139 | "ngrid = 2**8 # number of grid points\n",
140 | "alpha = -1 # damping factor for a call\n",
141 | "\n",
142 | "# Grids in real and Fourier space\n",
143 | "N = int(ngrid/2)\n",
144 | "b = xwidth/2 # upper bound of the support in real space\n",
145 | "dx = xwidth/ngrid\n",
146 | "x = dx * np.linspace(-N, N-1, 2*N)\n",
147 | "dxi = 2*np.pi/xwidth # Nyquist relation\n",
148 | "xi = dxi * np.linspace(-N, N-1, 2*N)\n",
149 | "\n",
150 | "# Characteristic function at time T\n",
151 | "xia = xi + 1j*alpha # call\n",
152 | "psi = 1j*muRN*xia - 0.5*(sigma*xia)**2 + lmbda*(np.exp(1j*mu_j*xia - 0.5*(sigma_j*xia)**2) - 1) # characteristic exponent\n",
153 | "psi_c = np.exp(psi*T) # characteristic function\n",
154 | "\n",
155 | "xia = xi - 1j*alpha # put\n",
156 | "psi = 1j*muRN*xia - 0.5*(sigma*xia)**2 + lmbda*(np.exp(1j*mu_j*xia - 0.5*(sigma_j*xia)**2) - 1) # characteristic exponent\n",
157 | "psi_p = np.exp(psi*T) # characteristic function\n",
158 | "\n",
159 | "# Fourier transform of the payoff\n",
160 | "U = S0 * np.exp(b)\n",
161 | "L = S0 * np.exp(-b)\n",
162 | "gc, Gc, S = payoff(x, xi, alpha, K, L, U, S0, 1)\n",
163 | "gp, Gp, S = payoff(x, xi, -alpha, K, L, U, S0, 0)\n",
164 | " \n",
165 | "# Discounted expected payoff computed with the Plancherel theorem \n",
166 | "c = np.exp(-r*T)*np.real(np.fft.fftshift(np.fft.fft(np.fft.ifftshift(Gc*np.conj(psi_c)))))/xwidth \n",
167 | "Vc = interp1d(S, c, kind='slinear')(S0) # Call value\n",
168 | "p = np.exp(-r*T)*np.real(np.fft.fftshift(np.fft.fft(np.fft.ifftshift(Gp*np.conj(psi_p)))))/xwidth \n",
169 | "Vp = interp1d(S, p, kind='slinear')(S0) # Put value\n",
170 | "\n",
171 | "print('The value of the call is ' + str(np.round(Vc, 5)) + '.')\n",
172 | "print('The value of the put is ' + str(np.round(Vp, 5)) + '.')"
173 | ]
174 | },
175 | {
176 | "cell_type": "markdown",
177 | "id": "productive-picture",
178 | "metadata": {},
179 | "source": [
180 | "Comparing these option prices with those obtained in the Black-Scholes notebook with the same parameters, we see that Merton jump diffusion yields slightly higher prices. This is due to the increased volatility resulting from the jump component.\n",
181 | "\n",
182 | "Because $V$ is a real number, taking its complex conjugate does not change and the integrand in Fourier space can also be written as $\\hat{g}^*(\\xi) \\psi (\\xi + i \\alpha, T)$ (i.e. we take the complex conjugate of the payoff instead of the characteristic function)."
183 | ]
184 | },
185 | {
186 | "cell_type": "code",
187 | "execution_count": 4,
188 | "id": "adopted-roulette",
189 | "metadata": {},
190 | "outputs": [
191 | {
192 | "name": "stdout",
193 | "output_type": "stream",
194 | "text": [
195 | "The value of the call is 0.13617.\n",
196 | "The value of the put is 0.20232.\n"
197 | ]
198 | }
199 | ],
200 | "source": [
201 | "# Discounted expected payoff computed with the Plancherel theorem \n",
202 | "c = np.exp(-r*T)*np.real(np.fft.fftshift(np.fft.fft(np.fft.ifftshift(np.conj(Gc)*psi_c))))/xwidth \n",
203 | "Vc = interp1d(S, c, kind='slinear')(S0) # Call value\n",
204 | "p = np.exp(-r*T)*np.real(np.fft.fftshift(np.fft.fft(np.fft.ifftshift(np.conj(Gp)*psi_p))))/xwidth \n",
205 | "Vp = interp1d(S, p, kind='slinear')(S0) # Put value\n",
206 | "\n",
207 | "print('The value of the call is ' + str(np.round(Vc, 5)) + '.')\n",
208 | "print('The value of the put is ' + str(np.round(Vp, 5)) + '.')"
209 | ]
210 | },
211 | {
212 | "cell_type": "markdown",
213 | "id": "bizarre-employee",
214 | "metadata": {},
215 | "source": [
216 | "Also note that the integration in Fourier space is overengineered by taking the zero-frequency value of an FFT. We could obtain the same result using other integration techniques such as the trapezoidal integration rule."
217 | ]
218 | },
219 | {
220 | "cell_type": "code",
221 | "execution_count": 5,
222 | "id": "advance-technician",
223 | "metadata": {},
224 | "outputs": [
225 | {
226 | "name": "stdout",
227 | "output_type": "stream",
228 | "text": [
229 | "The value of the call is 0.13617.\n",
230 | "The value of the put is 0.20232.\n"
231 | ]
232 | }
233 | ],
234 | "source": [
235 | "# Discounted expected payoff computed with the Plancherel theorem \n",
236 | "Vc = np.exp(-r*T)*np.real(np.trapz(np.conj(Gc)*psi_c))/xwidth \n",
237 | "Vp = np.exp(-r*T)*np.real(np.trapz(np.conj(Gp)*psi_p))/xwidth \n",
238 | "\n",
239 | "print('The value of the call is ' + str(np.round(Vc, 5)) + '.')\n",
240 | "print('The value of the put is ' + str(np.round(Vp, 5)) + '.')"
241 | ]
242 | },
243 | {
244 | "cell_type": "markdown",
245 | "id": "musical-immune",
246 | "metadata": {},
247 | "source": [
248 | "We can also compute the integral in log-price space by multiplying the undampened payoff by the one-time probability density function at maturity obtained with an inverse FFT of the characteristic function. "
249 | ]
250 | },
251 | {
252 | "cell_type": "code",
253 | "execution_count": 6,
254 | "id": "waiting-seller",
255 | "metadata": {},
256 | "outputs": [
257 | {
258 | "name": "stdout",
259 | "output_type": "stream",
260 | "text": [
261 | "The value of the call is 0.13614.\n",
262 | "The value of the put is 0.20229.\n"
263 | ]
264 | }
265 | ],
266 | "source": [
267 | "# characteristic function\n",
268 | "psi = 1j*muRN*xi - 0.5*(sigma*xi)**2 + lmbda*(np.exp(1j*mu_j*xi - 0.5*(sigma_j*xi)**2) - 1) # characteristic exponent\n",
269 | "psi = np.exp(psi*T) # characteristic function\n",
270 | "\n",
271 | "# PDF\n",
272 | "f = np.real(np.fft.fftshift(np.fft.fft(np.fft.ifftshift(psi))))/xwidth\n",
273 | "\n",
274 | "# Payoff\n",
275 | "gc = np.maximum(S0*np.exp(x) - K, 0)\n",
276 | "gp = np.maximum(K - S0*np.exp(x), 0)\n",
277 | "\n",
278 | "# Integrate and discount to get option values\n",
279 | "Vc = np.exp(-r*T)*np.trapz(gc*f*dx)\n",
280 | "Vp = np.exp(-r*T)*np.trapz(gp*f*dx)\n",
281 | "\n",
282 | "print('The value of the call is ' + str(np.round(Vc, 5)) + '.')\n",
283 | "print('The value of the put is ' + str(np.round(Vp, 5)) + '.')"
284 | ]
285 | },
286 | {
287 | "cell_type": "markdown",
288 | "id": "legitimate-compatibility",
289 | "metadata": {},
290 | "source": [
291 | "Finally, let's plot the PDF obtained at the previous step."
292 | ]
293 | },
294 | {
295 | "cell_type": "code",
296 | "execution_count": 7,
297 | "id": "functioning-resolution",
298 | "metadata": {},
299 | "outputs": [
300 | {
301 | "data": {
302 | "image/png": "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\n",
303 | "text/plain": [
304 | ""
305 | ]
306 | },
307 | "metadata": {
308 | "needs_background": "light"
309 | },
310 | "output_type": "display_data"
311 | }
312 | ],
313 | "source": [
314 | "fig = plt.figure(figsize=(10, 5))\n",
315 | "ax = fig.add_subplot(111)\n",
316 | "ax.plot(x, f)\n",
317 | "ax.set_xlabel(r'$x$')\n",
318 | "ax.set_ylabel(r'$f_X(x, T)$')\n",
319 | "ax.set_title('PDF at maturity');"
320 | ]
321 | },
322 | {
323 | "cell_type": "code",
324 | "execution_count": null,
325 | "id": "unusual-billion",
326 | "metadata": {},
327 | "outputs": [],
328 | "source": []
329 | }
330 | ],
331 | "metadata": {
332 | "authors": [
333 | {
334 | "email": "robin.guilliou@gmail.com",
335 | "name": "Robin Guilliou"
336 | }
337 | ],
338 | "kernelspec": {
339 | "display_name": "Python 3 (ipykernel)",
340 | "language": "python",
341 | "name": "python3"
342 | },
343 | "language_info": {
344 | "codemirror_mode": {
345 | "name": "ipython",
346 | "version": 3
347 | },
348 | "file_extension": ".py",
349 | "mimetype": "text/x-python",
350 | "name": "python",
351 | "nbconvert_exporter": "python",
352 | "pygments_lexer": "ipython3",
353 | "version": "3.7.11"
354 | },
355 | "latex_envs": {
356 | "LaTeX_envs_menu_present": true,
357 | "autoclose": false,
358 | "autocomplete": true,
359 | "bibliofile": "biblio.bib",
360 | "cite_by": "apalike",
361 | "current_citInitial": 1,
362 | "eqLabelWithNumbers": true,
363 | "eqNumInitial": 1,
364 | "hotkeys": {
365 | "equation": "Ctrl-E",
366 | "itemize": "Ctrl-I"
367 | },
368 | "labels_anchors": false,
369 | "latex_user_defs": false,
370 | "report_style_numbering": false,
371 | "user_envs_cfg": false
372 | },
373 | "toc": {
374 | "base_numbering": 1,
375 | "nav_menu": {},
376 | "number_sections": true,
377 | "sideBar": true,
378 | "skip_h1_title": true,
379 | "title_cell": "Table of Contents",
380 | "title_sidebar": "Contents",
381 | "toc_cell": false,
382 | "toc_position": {},
383 | "toc_section_display": true,
384 | "toc_window_display": false
385 | },
386 | "varInspector": {
387 | "cols": {
388 | "lenName": 16,
389 | "lenType": 16,
390 | "lenVar": 40
391 | },
392 | "kernels_config": {
393 | "python": {
394 | "delete_cmd_postfix": "",
395 | "delete_cmd_prefix": "del ",
396 | "library": "var_list.py",
397 | "varRefreshCmd": "print(var_dic_list())"
398 | },
399 | "r": {
400 | "delete_cmd_postfix": ") ",
401 | "delete_cmd_prefix": "rm(",
402 | "library": "var_list.r",
403 | "varRefreshCmd": "cat(var_dic_list()) "
404 | }
405 | },
406 | "types_to_exclude": [
407 | "module",
408 | "function",
409 | "builtin_function_or_method",
410 | "instance",
411 | "_Feature"
412 | ],
413 | "window_display": false
414 | }
415 | },
416 | "nbformat": 4,
417 | "nbformat_minor": 5
418 | }
419 |
--------------------------------------------------------------------------------
/European Options/Binomial model/binomial.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "b61c3868",
6 | "metadata": {},
7 | "source": [
8 | "# Binomial model: Option pricing\n",
9 | "\n",
10 | "In this notebook, we show how to price European options with the binomial model.\n",
11 | "\n",
12 | "## Delta-hedging\n",
13 | "\n",
14 | "Assume that stock prices only change at discrete time intervals. Further assume that at each time step, the stock price can change to one of two possible outcomes. After a time step $\\delta t$, the stock price goes to either $S_u = uS$ or $S_d = dS$ where\n",
15 | "\n",
16 | "\\begin{align}\n",
17 | " u &= e^{\\sigma \\sqrt{\\delta t}}, \\\\\n",
18 | " d &= e^{-\\sigma \\sqrt{\\delta t}}.\n",
19 | "\\end{align}\n",
20 | "\n",
21 | "Consider a portfolio $\\Pi$, long an option ($V$) and short $\\Delta$ stocks ($S$). If the price goes to $S_u$, the option price goes to $V_u$ and if the prices goes to $S_d$, the option price goes to $V_d$. At time $T$, there are two possible outcomes:\n",
22 | "\n",
23 | "\\begin{align}\n",
24 | " \\Pi_u &= V_u - \\Delta S_u, \\\\\n",
25 | " \\Pi_d &= V_d - \\Delta S_d.\n",
26 | "\\end{align}\n",
27 | "\n",
28 | "Choosing $\\Delta$ so that $\\Pi_u = \\Pi_d$ gives\n",
29 | "\n",
30 | "\\begin{equation}\n",
31 | " \\Delta = \\frac{V_u - V_d}{S_u - S_d}.\n",
32 | "\\end{equation}\n",
33 | "\n",
34 | "This choice makes the portfolio risk-free. No arbitrage suggests that the return on the portfolio should equal the risk-free rate. Therefore, assuming the risk-free rate, $r$, is continuous,\n",
35 | "\n",
36 | "\\begin{align}\n",
37 | " e^{rT} \\Pi &= \\Pi_u = \\Pi_d = V_d - \\Delta S_d = V_d - \\left(\\frac{V_u - V_d}{S_u - S_d}\\right) S_d \\notag \\\\\n",
38 | " &= \\frac{V_d(S_u - S_d) - S_d(V_u - V_d)}{S_u - S_d} \\notag \\\\\n",
39 | " &= \\frac{V_dS_u - S_dV_u}{S_u - S_d}.\n",
40 | "\\end{align}\n",
41 | "\n",
42 | "Replacing $\\Pi$ by $V - \\Delta S$, we obtain\n",
43 | "\n",
44 | "\\begin{equation}\n",
45 | " e^{rT}(V - \\Delta S) = \\frac{V_dS_u - S_dV_u}{S_u - S_d}.\n",
46 | "\\end{equation}\n",
47 | "\n",
48 | "Therefore,\n",
49 | "\n",
50 | "\\begin{align}\n",
51 | " e^{rT}V &= \\frac{V_dS_u - S_dV_u}{S_u - S_d} - \\left( \\frac{V_u - V_d}{S_u - S_d} \\right) Se^{rT} \\notag \\\\\n",
52 | " &= \\frac{\\left( e^{rT}S - S_d \\right)}{S_u - S_d} V_u + \\frac{\\left( S_u - e^{rT}S \\right)}{S_u - S_d} V_d\n",
53 | "\\end{align}\n",
54 | "\n",
55 | "Finally, the option price is given by\n",
56 | "\n",
57 | "\\begin{equation}\n",
58 | " V = e^{-rT} (pV_u + (1 - p)V_d)\n",
59 | "\\end{equation}\n",
60 | "\n",
61 | "where\n",
62 | "\n",
63 | "\\begin{equation}\n",
64 | " p = \\frac{e^{rT}S - S_d}{S_u - S_d} = \\frac{e^{rT} - d}{u - d}\n",
65 | "\\end{equation}\n",
66 | "\n",
67 | "is the risk-neutral probability.\n",
68 | "\n",
69 | "## Implementation\n",
70 | "\n",
71 | "Consider $N$ time steps where the stock price can either go up are down. The binomial tree, has $N+1$ terminal nodes. The probability of reaching a terminal node (reached with $k$ up moves and $N-k$ down moves) is given by\n",
72 | "\n",
73 | "\\begin{equation}\n",
74 | " p_k = \\binom{N}{k} p^k (1-p)^{N-k}\n",
75 | "\\end{equation}\n",
76 | "\n",
77 | "where $k$ denotes the number of up moves to reach the terminal node. The value of the option is the discounted expected value of the payoff at maturity. Therefore, it is given by\n",
78 | "\n",
79 | "\\begin{equation}\n",
80 | " V_0 = e^{-rT} \\sum_{k = 0}^N \\binom{N}{k} p^k (1-p)^{N-k} \\max(\\theta(S u^k d^{N-k} - K),0) \n",
81 | "\\end{equation}\n",
82 | "\n",
83 | "where $K$ is the strike price and $\\theta = 1$ for a call and -1 for a put. Expanding $p$ and using the fact that $u = d^{-1}$, we can rewrite the equation as\n",
84 | "\n",
85 | "\\begin{equation}\n",
86 | " V_0 = e^{-rT} \\sum_{k = 0}^N \\frac{N!}{k!(N - k)!} \\left( \\frac{e^{rT} - d}{u - d} \\right)^k \\left(\\frac{u - e^{rT}}{u - d}\\right)^{N-k} \\max(\\theta(S u^{2k - N} - K),0).\n",
87 | "\\end{equation}\n",
88 | "\n",
89 | "Let's define some parameters and implement a function to price a call option. Then, we obtain the put price using put-call parity. Put-call parity states that\n",
90 | "\n",
91 | "\\begin{equation}\n",
92 | " S + V_p = V_c + Ke^{-rT}\n",
93 | "\\end{equation}\n",
94 | "\n",
95 | "where $V_p$ is the price of a put and $V_c$ is the price of a call."
96 | ]
97 | },
98 | {
99 | "cell_type": "code",
100 | "execution_count": 1,
101 | "id": "0bf96108",
102 | "metadata": {},
103 | "outputs": [
104 | {
105 | "name": "stdout",
106 | "output_type": "stream",
107 | "text": [
108 | "Call price: 9.85902\n",
109 | "Put price: 5.93797\n"
110 | ]
111 | }
112 | ],
113 | "source": [
114 | "import numpy as np\n",
115 | "from scipy.stats import norm\n",
116 | "import matplotlib.pyplot as plt\n",
117 | "\n",
118 | "def nCk(n, k):\n",
119 | " return np.math.factorial(n) / (np.math.factorial(n-k)*np.math.factorial(k))\n",
120 | "\n",
121 | "\n",
122 | "def binomial(S0, K , T, r, sigma, N):\n",
123 | " dt = T/N\n",
124 | " u = np.exp(sigma * np.sqrt(dt))\n",
125 | " d = np.exp(-sigma * np.sqrt(dt))\n",
126 | " p = (np.exp(r*dt) - d) / (u - d)\n",
127 | " Vc = 0 \n",
128 | " for k in range(N+1):\n",
129 | " p_k = nCk(N, k)*p**k * (1-p)**(N-k)\n",
130 | " S_k = S0*(u)**(2*k-N)\n",
131 | " Vc += max(S_k-K,0) * p_k\n",
132 | " \n",
133 | " return Vc*np.exp(-r*T)\n",
134 | "\n",
135 | "# Parameters\n",
136 | "S = 100\n",
137 | "K = 100\n",
138 | "T = 1\n",
139 | "sigma = 0.2\n",
140 | "r = 0.04\n",
141 | "N = 30\n",
142 | "\n",
143 | "# Get option prices\n",
144 | "Vc = binomial(S, K, T, r,sigma, N) # call\n",
145 | "Vp = K*np.exp(-r*T) + Vc - S # put with put-call parity\n",
146 | "\n",
147 | "print('Call price: ' + str(round(Vc, 5)))\n",
148 | "print('Put price: ' + str(round(Vp, 5)))"
149 | ]
150 | },
151 | {
152 | "cell_type": "markdown",
153 | "id": "34a53ec6",
154 | "metadata": {},
155 | "source": [
156 | "## Relation to Black-Scholes\n",
157 | "\n",
158 | "In the limit as $N \\to \\infty$ (i.e., $\\delta t \\to 0$) the price obtained from the binomial model tends to the one obtained with the Black-Scholes model.\n",
159 | "\n",
160 | "Consider a Taylor series expansion of $u$, $d$ and $e^{r\\delta t}$:\n",
161 | "\n",
162 | "\\begin{align}\n",
163 | " &u = e^{\\sigma \\sqrt{\\delta t}} = 1 + \\sigma \\sqrt{\\delta t} + \\frac{1}{2} \\sigma^2 \\delta t + \\mathcal{O}(\\delta t^{\\frac{3}{2}}), \\\\\n",
164 | " &d = e^{-\\sigma \\sqrt{\\delta t}} = 1 - \\sigma \\sqrt{\\delta t} + \\frac{1}{2} \\sigma^2 \\delta t + \\mathcal{O}(\\delta t^{\\frac{3}{2}}), \\\\\n",
165 | " &e^{r\\delta t} = 1 + r \\delta t + \\mathcal{O}(\\delta t^2).\n",
166 | "\\end{align}\n",
167 | "\n",
168 | "Ignoring the terms of order $\\mathcal{O}(\\delta t^{\\frac{3}{2}})$ and $\\mathcal{O}(\\delta t^2)$, the risk-neutral probability can be rewritten as\n",
169 | "\n",
170 | "\\begin{align}\n",
171 | " p &= \\frac{e^{r \\delta t} - d}{u - d} = \\frac{1 + r \\delta t - 1 + \\sigma \\sqrt{\\delta t} - \\frac{1}{2} \\sigma^2 \\delta t}{1 + \\sigma \\sqrt{\\delta t} + \\frac{1}{2} \\sigma^2 \\delta t - 1 + \\sigma \\sqrt{\\delta t} - \\frac{1}{2} \\sigma^2 \\delta t} \\notag \\\\\n",
172 | " & = \\frac{\\left( r - \\frac{1}{2} \\sigma^2 \\right) \\delta t + \\sigma \\sqrt{\\delta t}}{2 \\sigma \\sqrt{\\delta t}} \\notag \\\\\n",
173 | " &= \\frac{\\left( r - \\frac{1}{2} \\sigma^2 \\right) \\sqrt{\\delta t}}{2 \\sigma} + \\frac{1}{2}\n",
174 | "\\end{align}\n",
175 | "\n",
176 | "We can rewrite the binomial model formula as\n",
177 | "\n",
178 | "\\begin{align}\n",
179 | " V(S, t) &= e^{-r \\delta t} [pV(uS, t + \\delta t) + (1 - p) V(dS, t + \\delta t)] \\notag \\\\\n",
180 | " &= e^{-r \\delta t} \\left[p\\big(V(uS, t + \\delta t) - V(dS, t + \\delta t) \\big) + V(dS, t + \\delta t)\\right].\n",
181 | "\\end{align}\n",
182 | "\n",
183 | "Let's define $V_u$ and $V_d$ such that \n",
184 | "\n",
185 | "\\begin{align}\n",
186 | " V_u &= V(uS, t + \\delta t) = V(S + (uS - S), t + \\delta t), \\\\\n",
187 | " V_d &= V(dS, t + \\delta t) = V(S + (dS - S), t + \\delta t).\n",
188 | "\\end{align}\n",
189 | "\n",
190 | "The Taylor series approximations of $V_u$ and $V_d$ are given by\n",
191 | "\n",
192 | "\\begin{align}\n",
193 | " V_u &= V(S, t) + (uS - S) \\frac{\\partial V}{\\partial S} + \\frac{1}{2} (uS - S)^2 \\frac{\\partial^2 V}{\\partial S^2} + \\frac{\\partial V}{\\partial t} \\delta t \\notag \\\\\n",
194 | " &= V(S, t) + S(u - 1) \\frac{\\partial V}{\\partial S} + \\frac{1}{2} S^2(u - 1)^2 \\frac{\\partial^2 V}{\\partial S^2} + \\frac{\\partial V}{\\partial t} \\delta t, \\\\\n",
195 | " V_d &= V(S, t) + S(d - 1) \\frac{\\partial V}{\\partial S} + \\frac{1}{2} S^2(d - 1)^2 \\frac{\\partial^2 V}{\\partial S^2} + \\frac{\\partial V}{\\partial t} \\delta t.\n",
196 | "\\end{align}\n",
197 | "\n",
198 | "Note that $(u - 1)^2 = (d - 1)^2 = \\sigma^2 \\delta t$. Therefore, we have \n",
199 | "\n",
200 | "\\begin{equation}\n",
201 | " V_u - V_d = (u - d)S \\frac{\\partial V}{\\partial S} = 2 \\sigma \\sqrt{\\delta t} S \\frac{\\partial V}{\\partial S}.\n",
202 | "\\end{equation}\n",
203 | "\n",
204 | "It follows that\n",
205 | "\n",
206 | "\\begin{align}\n",
207 | " p(V_u - V_d) &= \\left[ \\frac{\\left( r - \\frac{1}{2} \\sigma^2 \\right) \\sqrt{\\delta t}}{2 \\sigma} + \\frac{1}{2} \\right] 2\\sigma \\sqrt{\\delta t} S \\frac{\\partial V}{\\partial S} \\notag \\\\\n",
208 | " &= \\left(\\sigma \\sqrt{\\delta t} + r \\delta t - \\frac{1}{2}\\sigma^2 \\delta t \\right) S\\frac{\\partial V}{\\partial S}.\n",
209 | "\\end{align}\n",
210 | "\n",
211 | "Let $V = V(S, t)$. We now insert the everything into the binomial formula. We obtain\n",
212 | "\n",
213 | "\\begin{align}\n",
214 | " V(1 + r \\delta t) &= \\left(\\sigma \\sqrt{\\delta t} + r \\delta t - \\frac{1}{2}\\sigma^2 \\delta t \\right) S\\frac{\\partial V}{\\partial S} + V + S(d - 1)\\frac{\\partial V}{\\partial S} + \\frac{1}{2} S^2(d - 1)^2 \\frac{\\partial^2 V}{\\partial S^2} + \\frac{\\partial V}{\\partial t} \\delta t \\notag \\\\\n",
215 | " &= \\left(\\sigma \\sqrt{\\delta t} + r \\delta t - \\frac{1}{2}\\sigma^2 \\delta t \\right) S\\frac{\\partial V}{\\partial S} + V + S(-\\sigma \\sqrt{\\delta t} + \\frac{1}{2}\\sigma^2 \\delta t)\\frac{\\partial V}{\\partial S} + \\frac{1}{2} S^2\\sigma^2 \\frac{\\partial^2 V}{\\partial S^2}\\delta t + \\frac{\\partial V}{\\partial t} \\delta t.\n",
216 | "\\end{align}\n",
217 | "\n",
218 | "After canceling terms, we obtain\n",
219 | "\n",
220 | "\\begin{equation}\n",
221 | " V + rV\\delta t = V + \\frac{\\partial V}{\\partial t}\\delta t + \\frac{1}{2} S^2\\sigma^2 \\frac{\\partial^2 V}{\\partial S^2}\\delta t + rS\\frac{\\partial V}{\\partial S} \\delta t.\n",
222 | "\\end{equation}\n",
223 | "\n",
224 | "Finally, subtracting $V$ on both sides and dividing through by $\\delta t$, we obtain the Black-Scholes PDE,\n",
225 | "\n",
226 | "\\begin{equation}\n",
227 | " \\frac{\\partial V}{\\partial t} + \\frac{1}{2} \\sigma^2 S^2 \\frac{\\partial^2 V}{\\partial S^2} + rS\\frac{\\partial V}{\\partial S} - rV = 0.\n",
228 | "\\end{equation}\n",
229 | "\n",
230 | "Let's plot the value of the call option from the binomial model using different values for $N$ and compare those prices to the Black-Scholes price."
231 | ]
232 | },
233 | {
234 | "cell_type": "code",
235 | "execution_count": 2,
236 | "id": "456ef822",
237 | "metadata": {},
238 | "outputs": [
239 | {
240 | "data": {
241 | "image/png": "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DYmJiWH/3nALW4+bmU0mFLBmAFOBs8xsXJtqNwAr3X0qMAv4hZklmdlQ4N+BfHefDMQDX26136/cfVrwE9HQBpCXmcKs8XmRboaIiEiHZs2atc/P7373OyDUQ9VeefPyUGVlZfuUHaxdu3aRlZW1z/aSkhJOOukkpk+fvlevHMBdd93FkUceydSpU7nlllv22q+pqYm5c+dy22237XPMzZs3tyxxBTB+/PiW9UwfeughpkyZwtSpU7n00ktb6ixevJgTTjiBMWPGtPS+uTvf+ta3mDx5MkceeSSPPvroPt/V2NjIt771LY455himTJnC73//+5Y2zJw5k2nTpjF58mT+8Y9/HMwfV7vC2eM2EfiXu1cBmNkiYA5wV6s6DmRaaJXYDGA70LwybAKQamb1QBqwKYxtFRERkTBoXvKqpqaGzZs388orr+xTJy8vj4ULF5KSksLatWu56KKLKCgo4LnnnuOpp57izTffJC0tje3bt7fs09DQwMUXX8zkyZP53ve+t88xr7zySk477TQef/xxTj31VObOncu4ceN4//33+clPfsLrr79OTk7OXsfcvHkz//znP1m9ejVnn302F1xwAU8++SSFhYUsW7aMsrIyjjnmGGbOnLnXd82bN4/+/fvz9ttvU1tby4knnshpp53Gk08+yemnn873vvc9GhsbqaqqOuQ/z3AGtxXAT8wsG6gGZgNtb0j/FvgroVCWCXzJ3ZuAj83s58CGYN8X3f3FVvvdaGaXBcf7prvvaPvlZnYtcC3AiBEjuvXEREREYtFrr72237K0tLQOy3Nycjos35/Wt0qXLFnCZZddxooVK/aqU19fz4033khhYSHx8fF88MEHALz00ktcccUVpKWFViUaOHBgyz7XXXcdX/ziF9sNbQDTpk2juLiYF198kZdeeoljjjmGJUuW8Morr3DBBReQk5OzzzHPPfdc4uLimDRpElu2bAHgn//8JxdddBHx8fEMGjSIk08+mbfffpspU6a07Pfiiy/y3nvvtfTSlZeXs3btWo455hiuvPJK6uvrOffcc1vWbD0UYbtV6u6rgDuBhcDzwDL29KY1Ox0oBIYA04Dfmlk/M8sCzgFGB2XpZnZJsM89wNig/mbgF/v5/vvcPd/d83Nzc7vvxERERKRLjj/+eMrKyigtLd1r+69+9SsGDRrEsmXLKCgooK6uDgjd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\n",
242 | "text/plain": [
243 | ""
244 | ]
245 | },
246 | "metadata": {
247 | "needs_background": "light"
248 | },
249 | "output_type": "display_data"
250 | }
251 | ],
252 | "source": [
253 | "# Function for pricing call with Black-Scholes analytical formula \n",
254 | "def bs_analytical(S, K, T, r, sigma):\n",
255 | " d1 = (np.log(S/K) + (r + 0.5 * sigma**2) * T) / (sigma * np.sqrt(T))\n",
256 | " d2 = (np.log(S/K) + (r - 0.5 * sigma**2) * T) / (sigma * np.sqrt(T))\n",
257 | "\n",
258 | " # Calculates call and put values\n",
259 | " Vc = S * norm.cdf(d1) - K * np.exp(-r * (T)) * norm.cdf(d2)\n",
260 | " return Vc \n",
261 | "\n",
262 | "# BS call price\n",
263 | "Vc_bs = bs_analytical(S, K, T, r, sigma)\n",
264 | "\n",
265 | "# Call price from binomial model for different numbers of time steps\n",
266 | "Vc_bin = []\n",
267 | "for i in range(1, 21):\n",
268 | " Vc_bin.append(binomial(S, K, T, r,sigma, i*50))\n",
269 | "\n",
270 | "# Plot \n",
271 | "fig = plt.figure(figsize=(10, 7))\n",
272 | "ax = fig.add_subplot(111)\n",
273 | "ax.plot(np.array(range(1, 21))*50, Vc_bin, label='Binomial')\n",
274 | "ax.hlines(Vc_bs, 50, 1000, color='k', linestyle='--', label='Black-Scholes')\n",
275 | "ax.set_ylabel('Call value')\n",
276 | "ax.set_xlabel('Number of time steps')\n",
277 | "ax.legend(loc='lower right');"
278 | ]
279 | },
280 | {
281 | "cell_type": "markdown",
282 | "id": "344c06c1",
283 | "metadata": {},
284 | "source": [
285 | "As expected, we see that the call value obtained from the binomial model converges to the price obtained with the Black-Scholes model as $N$ increases."
286 | ]
287 | },
288 | {
289 | "cell_type": "code",
290 | "execution_count": null,
291 | "id": "55fa7939",
292 | "metadata": {},
293 | "outputs": [],
294 | "source": []
295 | }
296 | ],
297 | "metadata": {
298 | "authors": [
299 | {
300 | "email": "robin.guilliou@gmail.com",
301 | "name": "Robin Guilliou"
302 | }
303 | ],
304 | "kernelspec": {
305 | "display_name": "Python 3 (ipykernel)",
306 | "language": "python",
307 | "name": "python3"
308 | },
309 | "language_info": {
310 | "codemirror_mode": {
311 | "name": "ipython",
312 | "version": 3
313 | },
314 | "file_extension": ".py",
315 | "mimetype": "text/x-python",
316 | "name": "python",
317 | "nbconvert_exporter": "python",
318 | "pygments_lexer": "ipython3",
319 | "version": "3.7.11"
320 | },
321 | "latex_envs": {
322 | "LaTeX_envs_menu_present": true,
323 | "autoclose": false,
324 | "autocomplete": true,
325 | "bibliofile": "biblio.bib",
326 | "cite_by": "apalike",
327 | "current_citInitial": 1,
328 | "eqLabelWithNumbers": true,
329 | "eqNumInitial": 1,
330 | "hotkeys": {
331 | "equation": "Ctrl-E",
332 | "itemize": "Ctrl-I"
333 | },
334 | "labels_anchors": false,
335 | "latex_user_defs": false,
336 | "report_style_numbering": false,
337 | "user_envs_cfg": false
338 | },
339 | "toc": {
340 | "base_numbering": 1,
341 | "nav_menu": {},
342 | "number_sections": true,
343 | "sideBar": true,
344 | "skip_h1_title": true,
345 | "title_cell": "Table of Contents",
346 | "title_sidebar": "Contents",
347 | "toc_cell": false,
348 | "toc_position": {},
349 | "toc_section_display": true,
350 | "toc_window_display": false
351 | },
352 | "varInspector": {
353 | "cols": {
354 | "lenName": 16,
355 | "lenType": 16,
356 | "lenVar": 40
357 | },
358 | "kernels_config": {
359 | "python": {
360 | "delete_cmd_postfix": "",
361 | "delete_cmd_prefix": "del ",
362 | "library": "var_list.py",
363 | "varRefreshCmd": "print(var_dic_list())"
364 | },
365 | "r": {
366 | "delete_cmd_postfix": ") ",
367 | "delete_cmd_prefix": "rm(",
368 | "library": "var_list.r",
369 | "varRefreshCmd": "cat(var_dic_list()) "
370 | }
371 | },
372 | "types_to_exclude": [
373 | "module",
374 | "function",
375 | "builtin_function_or_method",
376 | "instance",
377 | "_Feature"
378 | ],
379 | "window_display": false
380 | }
381 | },
382 | "nbformat": 4,
383 | "nbformat_minor": 5
384 | }
385 |
--------------------------------------------------------------------------------
/Implied Volatility/implied_vol_newton.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "c4c825fa",
6 | "metadata": {},
7 | "source": [
8 | "# Implied Volatility: Newton-Raphson \n",
9 | "\n",
10 | "In this notebook, we show how to compute implied volatility for European options and plot the volatility smile.\n",
11 | "\n",
12 | "## Data\n",
13 | "\n",
14 | "We are going to use the Yahoo Finance API to get prices for options on Apple (ticker: AAPL) expiring on 16/09/2022 with strike price between 117.5 and 195. For reproducibility, the options data are also available in the files ```aapl_call_data.csv``` and ```aapl_put_data.csv```. We also need an estimate of the risk-free rate and the dividend yield of AAPL. For the risk-free rate, we use the 13 weeks treasury bill rate (^IRX) as a proxy. For the dividend yield proxy, we sum the for most recent quarterly dividends and divide the result by the current stock price.\n",
15 | "\n",
16 | "Let's import the libraries and retrieve all the necessary data."
17 | ]
18 | },
19 | {
20 | "cell_type": "code",
21 | "execution_count": 1,
22 | "id": "467ff42a",
23 | "metadata": {},
24 | "outputs": [],
25 | "source": [
26 | "import numpy as np\n",
27 | "import matplotlib.pyplot as plt\n",
28 | "from scipy.stats import norm\n",
29 | "import yfinance as yf\n",
30 | "import pandas as pd\n",
31 | "from datetime import datetime\n",
32 | "\n",
33 | "# Get apple last stock price\n",
34 | "aapl = yf.Ticker(\"AAPL\")\n",
35 | "div = aapl.get_dividends()[-4:]\n",
36 | "S = aapl.history(period='1d')['Close'][0]\n",
37 | "\n",
38 | "# Compute continuously compounded dividend yield\n",
39 | "div_yield_cont = np.log(1 + np.sum(div)/S)\n",
40 | "\n",
41 | "# Get proxy for continuously compounded risk-free interest rate\n",
42 | "rfr = yf.Ticker(\"^IRX\").history(period='1d')['Close'][0]\n",
43 | "rfr = rfr/100\n",
44 | "rfr_cont = np.log(1 + rfr)\n",
45 | "\n",
46 | "# Get option infos for the tenth next expiration date\n",
47 | "options_expiration = aapl.options[13]\n",
48 | "call_info = pd.DataFrame(aapl.option_chain(options_expiration)[0])\n",
49 | "put_info = pd.DataFrame(aapl.option_chain(options_expiration)[1])\n",
50 | "\n",
51 | "# Get strikes and corresponding market prices\n",
52 | "K = np.array(call_info['strike'])\n",
53 | "call_market_price = np.array(call_info['lastPrice'])\n",
54 | "put_market_price = np.array(put_info['lastPrice'])\n",
55 | "\n",
56 | "# Calculate time to maturity (as percentage of year)\n",
57 | "today = datetime.today().strftime('%Y-%m-%d')\n",
58 | "today = datetime.strptime(today, '%Y-%m-%d')\n",
59 | "expiration = datetime.strptime(options_expiration, '%Y-%m-%d')\n",
60 | "days_to_maturity = (expiration - today).days\n",
61 | "T = days_to_maturity/365\n",
62 | "\n",
63 | "# Get range of strikes and market prices\n",
64 | "K = K[40:58]\n",
65 | "call_market_price = call_market_price[40:58]\n",
66 | "put_market_price = put_market_price[40:58]"
67 | ]
68 | },
69 | {
70 | "cell_type": "markdown",
71 | "id": "7f3c3860",
72 | "metadata": {},
73 | "source": [
74 | "## Newton-Raphson method\n",
75 | "\n",
76 | "Let $V_{m}$ denote the market price of an option and $V_{b}(\\sigma)$ be the price of the option obtained from the Black-Scholes model when the volatility is $\\sigma$. Our goal is to find the volatility value $\\sigma_I$ such that \n",
77 | "\n",
78 | "\\begin{equation}\n",
79 | " V_{m} = V_{b}(\\sigma_I).\n",
80 | "\\end{equation}\n",
81 | "\n",
82 | "To do so, we use the Newton-Raphson iterative technique. First, we start with an initial guess for the implied volatility, $\\sigma_I^{(0)}$. Then, at each step, we update the estimate according to \n",
83 | "\n",
84 | "\\begin{equation}\n",
85 | " \\sigma_I^{(n + 1)} = \\sigma_I^{(n)} + \\frac{V_m - V_b \\left(\\sigma_I^{(n)} \\right)}{\\nu \\left(\\sigma_I^{(n)} \\right)}\n",
86 | "\\end{equation}\n",
87 | "\n",
88 | "where\n",
89 | "\n",
90 | "\\begin{equation}\n",
91 | " \\nu = \\frac{\\partial V_b}{\\partial \\sigma} = S_t \\sqrt{T-t} e^{-q(T-t)} \\frac{1}{\\sqrt{2 \\pi}} \\exp \\left[ -\\frac{1}{2} \\left( \\frac{\\log \\frac{S_t}{K} + (r - q + \\frac{\\sigma^2}{2})(T-t)}{\\sigma \\sqrt{T - t}} \\right)^2 \\right]\n",
92 | "\\end{equation}\n",
93 | "\n",
94 | "is the vega of the option. $S_t$ is the stock price at time $t$, $T$ is the maturity time, $K$ is the strike price $r$ is the risk-free rate and $q$ is the dividend rate.\n",
95 | "\n",
96 | "Let's implement a function that computes the implied volatility."
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": 2,
102 | "id": "92b5ecdc",
103 | "metadata": {},
104 | "outputs": [],
105 | "source": [
106 | "# Black-Scholes formula\n",
107 | "def black_scholes(S, K, T, r, q, sigma, call_put=1):\n",
108 | " \"\"\" set call_put = 1 for call and 0 for put \"\"\"\n",
109 | " d1 = (np.log(S/K) + (r-q + 0.5 * sigma**2) * T) / (sigma * np.sqrt(T))\n",
110 | " d2 = d1 - sigma*np.sqrt(T)\n",
111 | " \n",
112 | " if call_put == 1:\n",
113 | " V = S * np.exp(-q*T) * norm.cdf(d1) - K * np.exp(-r*T) * norm.cdf(d2)\n",
114 | " else:\n",
115 | " V = K * np.exp(-r*T) * norm.cdf(-d2) - S * np.exp(-q*T) * norm.cdf(-d1)\n",
116 | " \n",
117 | " # Changes nan values to 0\n",
118 | " V = np.nan_to_num(V,nan=0.0)\n",
119 | " \n",
120 | " return V\n",
121 | "\n",
122 | "# Vega \n",
123 | "def vega_bs(S, K, T, r, q, sigma): \n",
124 | " d1 = (np.log(S/K) + (r-q + 0.5 * sigma**2) * T) / (sigma * np.sqrt(T))\n",
125 | " return S*np.sqrt(T)*np.exp(-q*T)*norm.pdf(d1)\n",
126 | " \n",
127 | "# Compute implied volatility using Newton-Raphson method\n",
128 | "def implied_vol(target_price, S, K, T, r, q, max_iter, epsilon, initial_guess=0.5, call_put=1):\n",
129 | " sigma = initial_guess\n",
130 | " for i in range(max_iter):\n",
131 | " V = black_scholes(S, K, T, r, q, sigma, call_put)\n",
132 | " vega = vega_bs(S, K, T, r, q, sigma)\n",
133 | " delta_price = target_price - V\n",
134 | " if (np.abs(delta_price) < epsilon).all():\n",
135 | " return sigma\n",
136 | "\n",
137 | " #sigma = sigma + np.divide(delta_price, (vega/100))\n",
138 | " sigma = sigma + delta_price / vega / 100\n",
139 | " print('Optimisation failed (algorithm has not converged): return sigma from last iteration.')\n",
140 | " return sigma"
141 | ]
142 | },
143 | {
144 | "cell_type": "markdown",
145 | "id": "f6427acc",
146 | "metadata": {},
147 | "source": [
148 | "Let's define some parameters to stop the optimization. The optimization algorithm stops when the maximum number of iterations is reached or when the algorithm has converged based on the tolerance level."
149 | ]
150 | },
151 | {
152 | "cell_type": "code",
153 | "execution_count": 3,
154 | "id": "741e7244",
155 | "metadata": {},
156 | "outputs": [],
157 | "source": [
158 | "# Optimisation parameters\n",
159 | "max_iter = 1000\n",
160 | "epsilon = 1e-4"
161 | ]
162 | },
163 | {
164 | "cell_type": "markdown",
165 | "id": "e12da822",
166 | "metadata": {},
167 | "source": [
168 | "Finally, let's compute the implied volatility for our option chain and plot the volatility smile."
169 | ]
170 | },
171 | {
172 | "cell_type": "code",
173 | "execution_count": 4,
174 | "id": "843a281a",
175 | "metadata": {},
176 | "outputs": [
177 | {
178 | "data": {
179 | "image/png": "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/Oqcm2lmWfl9iHPuSeBJ8N2aRS06P88+C7Nm5f5cRgZUr557cIv/2qgR1K+fyCpFUkPOKuAVK1YMXImISHIlMpwtAurEPa4NLM7rZOfcB2a2r5nVAI4CTjCzLkB5oKqZ/ds51yuB9e7QzJmwZg0sXQrLluX/dfZsf3/5cogf1leuHPz0kw9yIpK3Ll26ABpzJiLpJ5HhbDrQyMwaAD8BpwNnxp9gZg2B72MTAloAZYHlzrlrgGti52QBV4UOZjkqVIC6df2tIDZtgt9+84Ht44/hvPPg/ffh1FMTW6eIiIiUTAkbJeWc2whcCrwDfI2fifmlmfUzs36x03oAs80sG3gEOM0lavpoIBkZvjtz//2hd2+oWhUmTAhdlYiIiERVQoewO+fecs41ds7t65y7LXbscefc47H7dznnDnTOZTrnWjnn/pvLe0wuyDIaJUHp0tCuHbz3XuhKREREwrvttts48MADadasGZmZmXzyyScADBs27O9xp4V14403MnTo0GKpb/HixZxyyinF8l6FofmFSdahA8yfD/Pmha5EREQknGnTpjFu3DhmzZrFF198wYQJE6hTxw9VL0o4Ky4bN25kr732YtSoUUn/bIWzJOvY0X9V16ZI/vr06UOfPn1ClyEiCfLzzz9To0YNypUrB0CNGjXYa6+9ePDBB1m8eDHt2rX7eyeAl156iYMOOoimTZty9dVX//0eb7/9Ni1atKB58+a0b99+u8946qmn6Ny5M2vWrNnqeJ8+fejXrx9t2rShcePGjBvnNyIaMWIEp556Kt26daNTp0788MMPNG3aFIBNmzZx1VVXcdBBB9GsWTMeeughAGbOnEnbtm055JBDOPbYY/n555+LfG208XmSNW4MtWv7rs2+fUNXIxJdCmYiyZWzK0e8nj17cvHFF7N69eq/Z1DHy/klatmyZdt1/+1opnWnTp24+eabady4MR06dOC0006jbdu2XHbZZdx3331MmjSJGjVqsHjxYq6++mpmzpzJbrvtRqdOnXj11Vc56qijuPDCC/nggw9o0KABK1as2Or9H374Yd59911effXVvwNgvB9++IEpU6bw/fff065dO+bOnQv4Fr0vvviCatWq8cMPP/x9/pNPPsn8+fP57LPPKF26NCtWrGDDhg384x//4LXXXqNmzZqMHDmSa6+9luHDh+f7ve+IwlmSmfmuzddf9zM5MzJCVyQSTcuWLQP8b9MiknoqV67MzJkz+fDDD5k0aRKnnXYad95553a/mE2fPp2srCxq1qwJwFlnncUHH3xARkYGRx99NA0aNACgWrVqf7/m+eefp3bt2rz66quUKVMm18/v2bMnpUqVolGjRuyzzz588803AHTs2HGr98oxYcIE+vXrR+nSpf/+vNmzZzN79mw6xrrFNm3axJ577lm0C4PCWRAdO8KIEfDZZ9Byux21RAT4+7dwrXMmkhz5/VurWLFivs/XqFFjp/6tZmRkkJWVRVZWFgcddBDPPffcduEsr0UcnHOY5bbePTRt2pTs7GwWLVr0d3jb1ravzXlcqVKlAn+ec44DDzyQadOm5fqanaUxZwHkdItr3JmIiKSrOXPm8N133/39ODs7m3r16gFQpUoVVq5cCcDhhx/OlClTWLZsGZs2beKll16ibdu2tGrViilTpjB//nyArbo1Dz74YJ544glOOOEEFi/Off37//znP2zevJnvv/+eefPm0aRJk3zr7dSpE48//jgbN278+/OaNGnC0qVL/w5nGzZs4Msvv9zJK7KFwlkAu+8OzZopnImISPpatWoV55xzDgcccADNmjXjq6++4sYbbwSgb9++dO7cmXbt2rHnnntyxx130K5dO5o3b06LFi048cQTqVmzJk8++STdu3enefPmnHbaaVu9f+vWrRk6dCjHH3/838Mk4jVp0oS2bdvSuXNnHn/8ccqXL59vvRdccAF169alWbNmNG/enBdffJGyZcsyatQorr76apo3b05mZiZTp04t8rWxVFrztWXLlm7GjBmhyyiQgQPhkUf87gEVKoSuRiR6cgYnq1tTJDG+/vpr9t9//9BlBNGnTx+6du2a1DXMcrveZjbTObfdACe1nAXSsSOsWwf/3W7ZXREREUlnmhAQSJs2UKaMX1IjZ+0zEdmif//+oUsQkRQ1YsSI0CXkS+EskEqV4MgjNe5MJC/bjh8RkeKX34xHKT6FHUKmbs2AOnb0y2ksXRq6EpHoWbhwIQsXLgxdhkjKKl++PMuXLy90cJDCcc6xfPnyHU44iKeWs4A6dIAhQ+D990GNBCJb6927N6AJASKJUrt2bRYtWsRStRAkXPny5aldu3aBz1c4C6hlS9hlF9+1qXAmIiLJVKZMmTwXaJWw1K0ZUEYGHHOMnxSgVmUREREB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VVddFboEEUmGHj3g0kvh669h//1DVxMJajkTERGRcE46yX9V69nfFM5EJJKysrLIysoKXYaIJNree8MRRyicxVE4ExERkbB69IBZs/zMTVE4ExERkcBOPtl/Dd16tn49zJkDkycHLUMTAkRERCSsffeF5s19OLvyysR+1vr1MH8+zJ0L33235et338GCBX6vzwoVYNUqv8xHAApnIiIiEl737nDjjfDzz7DnnkV7r5wAFh++cr7mBLAcu+wCjRrB4YdDr17QsKF/HJDCmYhEUs+ePUOXICLJ1KMH3HADvPoq9O+/4/OLEsAaNdoSwqpXB7OEfVs7w1wK7WfVsmVLN2PGjNBliIiISGE5B/vtB3Xrwnvv+WPr18O8eduHr7lz8w5g8cErwgEMwMxmOudabntcLWciEkmrV68GoGLFioErEZGkMPNdm/fcA5065R/AjjhiSwtYTgiLaADbGQpnIhJJXbp0AWBy4FlTIpJE55wDL78Mv/3mA1jv3lu3gqVQAMuPwpmIiIhEw377+XFkaU7rnImIiIhEiMKZiIiISIQonImIiIhEiMaciUgk9enTJ3QJIiJBKJyJSCQpnIlIulK3pohE0rJly1i2bFnoMkREkk4tZyISSaeccgqgdc5EJP2o5UxEREQkQhTORERERCJE4UxEREQkQhTORERERCJEEwJEJJL69+8fugQRkSAUzkQkkk477bTQJYiIBKFuTRGJpIULF7Jw4cLQZYiIJJ1azkQkknr37g1onTMRST9qORMRERGJEIUzERERkQhROBMRERGJEIUzERERkQjRhAARiaSBAweGLkFEJAiFMxGJpG7duoUuQUQkCHVrikgkzZkzhzlz5oQuQ0Qk6dRyJiKRdNFFFwFa50xE0o9azkREREQixJxzoWsoNma2FFgQuo4dqAEsC11EBOg66Brk0HXQNcih66BrAOl1Deo552puezClwllJYGYznHMtQ9cRmq6DrkEOXQddgxy6DroGoGsA6tYUERERiRSFMxEREZEIUThLvidDFxARug66Bjl0HXQNcug66BqAroHGnImIiIhEiVrORERERCJE4UxEREQkQhTOipmZDTezX81sdtyxe8zsGzP7wszGmtmucc9dY2ZzzWyOmR0bpOhilsc1uCX2/Web2btmtlfccyl3DSD36xD33FVm5sysRtyxlLsOefxduNHM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\n",
180 | "text/plain": [
181 | ""
182 | ]
183 | },
184 | "metadata": {
185 | "needs_background": "light"
186 | },
187 | "output_type": "display_data"
188 | }
189 | ],
190 | "source": [
191 | "# Compute IV\n",
192 | "sigma_call = implied_vol(call_market_price, S, K, T, rfr_cont, div_yield_cont, max_iter, epsilon, 0.3, 1)\n",
193 | "sigma_put = implied_vol(put_market_price, S, K, T, rfr_cont, div_yield_cont, max_iter, epsilon, 0.3, 0)\n",
194 | "\n",
195 | "# Plot volatility smile\n",
196 | "fig = plt.figure(figsize=(10, 7))\n",
197 | "ax = fig.add_subplot(111)\n",
198 | "ax.plot(K, sigma_call, 'b', label='Call')\n",
199 | "ax.plot(K, sigma_put, 'r', label='Put')\n",
200 | "ax.vlines(S, 0, 1, color='k', ls='--', label='Stock price')\n",
201 | "ax.set_ylim(np.min((sigma_call.min(), sigma_put.min()))/1.03, np.max((sigma_call.max(), sigma_put.max()))*1.03)\n",
202 | "ax.set_xlabel('Strike price')\n",
203 | "ax.set_ylabel('Implied volatility')\n",
204 | "ax.set_title('Volatility smile')\n",
205 | "ax.legend(loc='best');"
206 | ]
207 | }
208 | ],
209 | "metadata": {
210 | "authors": [
211 | {
212 | "email": "robin.guilliou@gmail.com",
213 | "name": "Robin Guilliou"
214 | }
215 | ],
216 | "kernelspec": {
217 | "display_name": "Python 3 (ipykernel)",
218 | "language": "python",
219 | "name": "python3"
220 | },
221 | "language_info": {
222 | "codemirror_mode": {
223 | "name": "ipython",
224 | "version": 3
225 | },
226 | "file_extension": ".py",
227 | "mimetype": "text/x-python",
228 | "name": "python",
229 | "nbconvert_exporter": "python",
230 | "pygments_lexer": "ipython3",
231 | "version": "3.7.11"
232 | },
233 | "latex_envs": {
234 | "LaTeX_envs_menu_present": true,
235 | "autoclose": false,
236 | "autocomplete": true,
237 | "bibliofile": "biblio.bib",
238 | "cite_by": "apalike",
239 | "current_citInitial": 1,
240 | "eqLabelWithNumbers": true,
241 | "eqNumInitial": 1,
242 | "hotkeys": {
243 | "equation": "Ctrl-E",
244 | "itemize": "Ctrl-I"
245 | },
246 | "labels_anchors": false,
247 | "latex_user_defs": false,
248 | "report_style_numbering": false,
249 | "user_envs_cfg": false
250 | },
251 | "toc": {
252 | "base_numbering": 1,
253 | "nav_menu": {},
254 | "number_sections": true,
255 | "sideBar": true,
256 | "skip_h1_title": true,
257 | "title_cell": "Table of Contents",
258 | "title_sidebar": "Contents",
259 | "toc_cell": false,
260 | "toc_position": {},
261 | "toc_section_display": true,
262 | "toc_window_display": false
263 | },
264 | "varInspector": {
265 | "cols": {
266 | "lenName": 16,
267 | "lenType": 16,
268 | "lenVar": 40
269 | },
270 | "kernels_config": {
271 | "python": {
272 | "delete_cmd_postfix": "",
273 | "delete_cmd_prefix": "del ",
274 | "library": "var_list.py",
275 | "varRefreshCmd": "print(var_dic_list())"
276 | },
277 | "r": {
278 | "delete_cmd_postfix": ") ",
279 | "delete_cmd_prefix": "rm(",
280 | "library": "var_list.r",
281 | "varRefreshCmd": "cat(var_dic_list()) "
282 | }
283 | },
284 | "types_to_exclude": [
285 | "module",
286 | "function",
287 | "builtin_function_or_method",
288 | "instance",
289 | "_Feature"
290 | ],
291 | "window_display": false
292 | }
293 | },
294 | "nbformat": 4,
295 | "nbformat_minor": 5
296 | }
297 |
--------------------------------------------------------------------------------