├── CITATION.md
├── LICENCE.md
├── README.md
├── notebooks
├── rbergomi.ipynb
└── turbocharged.ipynb
├── papers
├── hybrid_scheme.pdf
├── pricing_under_rough.pdf
├── turbocharged_rbergomi.pdf
└── volatility_is_rough.pdf
├── rbergomi
├── rbergomi.py
└── utils.py
├── surface0.png
└── surface1.png
/CITATION.md:
--------------------------------------------------------------------------------
1 | Should you wish to refer to this repository or any of its contents, please cite the url https://github.com/ryanmccrickerd/rough_bergomi.
2 |
--------------------------------------------------------------------------------
/LICENCE.md:
--------------------------------------------------------------------------------
1 | Copyright 2017 Ryan McCrickerd
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | rBergomi simulation and turbocharged pricing
2 | ============================================
3 |
4 | A Python implementation of the rough Bergomi (rBergomi) stochastic volatility model introduced by [Bayer, Friz and Gatheral](https://ssrn.com/abstract=2554754), using the hybrid simulation scheme of [Bennedsen, Lunde and Pakkanen](https://arxiv.org/abs/1507.03004) and variance reduction pricing methods of [McCrickerd and Pakkanen](https://arxiv.org/abs/1708.02563).
5 |
6 | Example Jupyter notebooks are included which demonstrate usage. Tested with Python 3.5.2 and macOS Sierra 10.12.5.
7 |
8 |
9 |
--------------------------------------------------------------------------------
/notebooks/turbocharged.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "nbpresent": {
7 | "id": "b590a017-9bad-4ff8-ac89-d1d90e1ebf09"
8 | }
9 | },
10 | "source": [
11 | "Turbocharged demo\n",
12 | "=="
13 | ]
14 | },
15 | {
16 | "cell_type": "markdown",
17 | "metadata": {},
18 | "source": [
19 | "We demonstrate the rough Bergomi (rBergomi) price process introduced by [Bayer, Friz and Gatheral](https://ssrn.com/abstract=2554754), which we define here by"
20 | ]
21 | },
22 | {
23 | "cell_type": "markdown",
24 | "metadata": {},
25 | "source": [
26 | "$$S_t := \\exp \\left\\{ \\int_0^t \\sqrt{ V_u } \\mathrm{d}B_u - \\frac{1}{2}\\int_0^t V_u \\mathrm{d}u \\right\\},\\quad B_u:=\\rho W_u^1 + \\sqrt{1 - \\rho^2}W_u^2, $$"
27 | ]
28 | },
29 | {
30 | "cell_type": "markdown",
31 | "metadata": {},
32 | "source": [
33 | "$$V_t := \\xi\\ \\exp \\left\\{ \\eta Y^a_t - \\frac{\\eta^2}{2} t^{2a + 1}\\right\\}, \\quad Y_t^a := \\sqrt{2a + 1} \\int_0^t (t - u)^a \\mathrm{d}W^1_u,$$"
34 | ]
35 | },
36 | {
37 | "cell_type": "markdown",
38 | "metadata": {},
39 | "source": [
40 | "for Brownian motion $(W^1, W^2)$. The *hybrid scheme* of [Bennedsen, Lunde and Pakkanen](https://arxiv.org/abs/1507.03004) is used for efficient, $\\mathcal{O}(n\\log n)$, simulation of the Volterra process, $Y_t^a$."
41 | ]
42 | },
43 | {
44 | "cell_type": "markdown",
45 | "metadata": {},
46 | "source": [
47 | "From $N$ samples of the price process, $\\{S^i_t\\}_{i = 1}^N$ , we show implied volatilities, $\\hat{\\sigma}^N_{BS}(k,t)$, using estimators of the form"
48 | ]
49 | },
50 | {
51 | "cell_type": "markdown",
52 | "metadata": {},
53 | "source": [
54 | "$$\\hat{\\sigma}^N_{BS}(k,t)^2 t = BS^{-1}\\left(\\hat{C}_N(k,t)\\right),\\quad \\hat{C}_N(k,t) = \\frac{1}{N}\\sum_{i = 1}^N (X_i + c Y_i) - c\\mathbb{E}[Y],$$"
55 | ]
56 | },
57 | {
58 | "cell_type": "markdown",
59 | "metadata": {},
60 | "source": [
61 | "as described in [McCrickerd and Pakkanen](https://arxiv.org/abs/1708.02563). For simplicity, we just use call option estimators (rather than OTM option estimators) and do not use antithetic sampling here."
62 | ]
63 | },
64 | {
65 | "cell_type": "markdown",
66 | "metadata": {},
67 | "source": [
68 | "We thus define a Base estimator here by $$X = \\max(S_t - e^k,0),\\quad Y = 0$$ and a Mixed estimator by $$X = BS\\left((1 - \\rho^2)\\int_0^t V_u\\mathrm{d}u; S^1_t,k\\right),\\quad Y = BS\\left(\\rho^2\\left(Q - \\int_0^t V_u\\mathrm{d}u\\right); S^1_t,k\\right)$$"
69 | ]
70 | },
71 | {
72 | "cell_type": "markdown",
73 | "metadata": {},
74 | "source": [
75 | "where $S^1_t$ is the parallel component of the price process, defined by $$S^1_t := \\exp \\left\\{ \\rho\\int_0^t \\sqrt{ V_u } \\mathrm{d}W^1_u - \\frac{\\rho^2}{2}\\int_0^t V_u \\mathrm{d}u \\right\\}.$$"
76 | ]
77 | },
78 | {
79 | "cell_type": "markdown",
80 | "metadata": {},
81 | "source": [
82 | "While most computations are hidden in the methods of the rBergomi class, we expose the Mixed estimator calculations in this notebook for transparency."
83 | ]
84 | },
85 | {
86 | "cell_type": "markdown",
87 | "metadata": {
88 | "nbpresent": {
89 | "id": "4523a2f1-a876-4216-a222-c3e0c4d62e9a"
90 | }
91 | },
92 | "source": [
93 | "Change directory to folder with rBergomi scripts"
94 | ]
95 | },
96 | {
97 | "cell_type": "code",
98 | "execution_count": 1,
99 | "metadata": {
100 | "nbpresent": {
101 | "id": "d3eb17f0-eba6-4483-b962-9fc62b4ae12b"
102 | }
103 | },
104 | "outputs": [],
105 | "source": [
106 | "import os\n",
107 | "os.chdir('/Users/ryanmccrickerd/desktop/phd/2016-17/rough_bergomi/rbergomi')"
108 | ]
109 | },
110 | {
111 | "cell_type": "markdown",
112 | "metadata": {
113 | "nbpresent": {
114 | "id": "d95b28a8-a3ad-42d8-b1de-453db5f619a8"
115 | }
116 | },
117 | "source": [
118 | "Import required libraries, classes and functions"
119 | ]
120 | },
121 | {
122 | "cell_type": "code",
123 | "execution_count": 2,
124 | "metadata": {
125 | "nbpresent": {
126 | "id": "577b9e39-b12e-4ca8-9b95-fdb814c09a91"
127 | },
128 | "scrolled": true
129 | },
130 | "outputs": [],
131 | "source": [
132 | "import numpy as np\n",
133 | "from matplotlib import pyplot as plt\n",
134 | "from rbergomi import rBergomi\n",
135 | "from utils import bs, bsinv\n",
136 | "vec_bsinv = np.vectorize(bsinv)\n",
137 | "% matplotlib inline"
138 | ]
139 | },
140 | {
141 | "cell_type": "markdown",
142 | "metadata": {
143 | "nbpresent": {
144 | "id": "c235967a-8303-4e62-abf1-10e5c7229c9f"
145 | }
146 | },
147 | "source": [
148 | "Create instance of the rBergomi class with $n$ steps per year, $N$ paths, maximum maturity $T$ and roughness index $a$"
149 | ]
150 | },
151 | {
152 | "cell_type": "code",
153 | "execution_count": 3,
154 | "metadata": {
155 | "collapsed": true,
156 | "nbpresent": {
157 | "id": "c6acd2d1-8354-4afc-b6ce-fe12e3358df1"
158 | }
159 | },
160 | "outputs": [],
161 | "source": [
162 | "rB = rBergomi(n = 312*4, N = 1000, T = 0.25, a = -0.43)"
163 | ]
164 | },
165 | {
166 | "cell_type": "markdown",
167 | "metadata": {
168 | "nbpresent": {
169 | "id": "104e4831-a151-403d-91de-d5190e5f4001"
170 | }
171 | },
172 | "source": [
173 | "Fix the generator's seed for replicable results"
174 | ]
175 | },
176 | {
177 | "cell_type": "code",
178 | "execution_count": 4,
179 | "metadata": {
180 | "collapsed": true,
181 | "nbpresent": {
182 | "id": "1ff02865-583a-4770-a987-c941f24cccc6"
183 | }
184 | },
185 | "outputs": [],
186 | "source": [
187 | "np.random.seed(0)"
188 | ]
189 | },
190 | {
191 | "cell_type": "markdown",
192 | "metadata": {
193 | "nbpresent": {
194 | "id": "6edc32ba-80b0-41e0-a268-bcd279fbf478"
195 | }
196 | },
197 | "source": [
198 | "Generate required Brownian increments"
199 | ]
200 | },
201 | {
202 | "cell_type": "code",
203 | "execution_count": 5,
204 | "metadata": {
205 | "collapsed": true,
206 | "nbpresent": {
207 | "id": "d48220f4-a06c-4182-b6ea-bfdef938934b"
208 | }
209 | },
210 | "outputs": [],
211 | "source": [
212 | "dW1 = rB.dW1()\n",
213 | "dW2 = rB.dW2()"
214 | ]
215 | },
216 | {
217 | "cell_type": "markdown",
218 | "metadata": {
219 | "nbpresent": {
220 | "id": "fda3303d-3c49-4b89-b4f4-049d78ded1f1"
221 | }
222 | },
223 | "source": [
224 | "Construct the Volterra process, $$Y_t^a := \\sqrt{2a + 1} \\int_0^t (t - u)^a \\mathrm{d}W^1_u$$"
225 | ]
226 | },
227 | {
228 | "cell_type": "code",
229 | "execution_count": 6,
230 | "metadata": {
231 | "collapsed": true,
232 | "nbpresent": {
233 | "id": "5e7430b0-873d-4756-ab2c-f4069dc668b3"
234 | }
235 | },
236 | "outputs": [],
237 | "source": [
238 | "Ya = rB.Y(dW1)"
239 | ]
240 | },
241 | {
242 | "cell_type": "markdown",
243 | "metadata": {},
244 | "source": [
245 | "Correlate the orthogonal increments, using $\\rho$, $$B_u:=\\rho W_u^1 + \\sqrt{1 - \\rho^2}W_u^2$$"
246 | ]
247 | },
248 | {
249 | "cell_type": "code",
250 | "execution_count": 7,
251 | "metadata": {
252 | "collapsed": true,
253 | "nbpresent": {
254 | "id": "f95288a5-2adb-483f-8488-c6ebd08f1027"
255 | }
256 | },
257 | "outputs": [],
258 | "source": [
259 | "dB = rB.dB(dW1, dW2, rho = -0.9)"
260 | ]
261 | },
262 | {
263 | "cell_type": "markdown",
264 | "metadata": {
265 | "nbpresent": {
266 | "id": "b39ab489-9218-4ba6-a971-74813f713283"
267 | }
268 | },
269 | "source": [
270 | "Construct the variance process, using $\\xi$ and $\\eta$, $$V_t := \\xi\\ \\exp \\left\\{ \\eta Y^a_t - \\frac{\\eta^2}{2} t^{2a + 1}\\right\\}$$"
271 | ]
272 | },
273 | {
274 | "cell_type": "code",
275 | "execution_count": 8,
276 | "metadata": {
277 | "collapsed": true,
278 | "nbpresent": {
279 | "id": "207584be-40fb-4957-833c-0e11ab89433d"
280 | }
281 | },
282 | "outputs": [],
283 | "source": [
284 | "V = rB.V(Ya, xi = 0.235**2, eta = 1.9) "
285 | ]
286 | },
287 | {
288 | "cell_type": "markdown",
289 | "metadata": {
290 | "nbpresent": {
291 | "id": "83d17e74-5d6a-4f1a-a58d-349d082fb1df"
292 | }
293 | },
294 | "source": [
295 | "Finally construct the price processes, $$S_t := \\exp \\left\\{ \\int_0^t \\sqrt{ V_u } \\mathrm{d}B_u - \\frac{1}{2}\\int_0^t V_u \\mathrm{d}u \\right\\},\\quad S^1_t := \\exp \\left\\{ \\rho\\int_0^t \\sqrt{ V_u } \\mathrm{d}W^1_u - \\frac{\\rho^2}{2}\\int_0^t V_u \\mathrm{d}u \\right\\}$$"
296 | ]
297 | },
298 | {
299 | "cell_type": "code",
300 | "execution_count": 9,
301 | "metadata": {
302 | "collapsed": true,
303 | "nbpresent": {
304 | "id": "698f4b14-0398-46bb-88aa-c822fcff2ad1"
305 | }
306 | },
307 | "outputs": [],
308 | "source": [
309 | "S = rB.S(V, dB)\n",
310 | "S1 = rB.S1(V, dW1, rho = -0.9)"
311 | ]
312 | },
313 | {
314 | "cell_type": "markdown",
315 | "metadata": {},
316 | "source": [
317 | "Now set log-strikes, $k$"
318 | ]
319 | },
320 | {
321 | "cell_type": "code",
322 | "execution_count": 10,
323 | "metadata": {},
324 | "outputs": [],
325 | "source": [
326 | "k = np.array([-0.1787,0.0000,0.1041])\n",
327 | "K = np.exp(k)[np.newaxis,:]"
328 | ]
329 | },
330 | {
331 | "cell_type": "markdown",
332 | "metadata": {},
333 | "source": [
334 | "and known implied volatilities for this model specification"
335 | ]
336 | },
337 | {
338 | "cell_type": "code",
339 | "execution_count": 11,
340 | "metadata": {
341 | "collapsed": true
342 | },
343 | "outputs": [],
344 | "source": [
345 | "implied_vols = np.array([0.2961,0.2061,0.1576])[:,np.newaxis]"
346 | ]
347 | },
348 | {
349 | "cell_type": "markdown",
350 | "metadata": {},
351 | "source": [
352 | "Compute Base call payoffs, prices, and estimated volatilities,"
353 | ]
354 | },
355 | {
356 | "cell_type": "code",
357 | "execution_count": 12,
358 | "metadata": {},
359 | "outputs": [],
360 | "source": [
361 | "ST = S[:,-1][:,np.newaxis]\n",
362 | "base_payoffs = np.maximum(ST - K,0)\n",
363 | "base_prices = np.mean(base_payoffs, axis = 0)[:,np.newaxis]\n",
364 | "base_vols = vec_bsinv(base_prices, 1., np.transpose(K), rB.T)"
365 | ]
366 | },
367 | {
368 | "cell_type": "markdown",
369 | "metadata": {},
370 | "source": [
371 | "Do the same for the Mixed estimator, including the quadratic variation, $\\mathrm{QV} = \\int_0^t V_u \\mathrm{d}u$, and variation budget, $\\mathrm{Q}$"
372 | ]
373 | },
374 | {
375 | "cell_type": "code",
376 | "execution_count": 13,
377 | "metadata": {},
378 | "outputs": [],
379 | "source": [
380 | "QV = np.sum(V, axis = 1)[:,np.newaxis] * rB.dt\n",
381 | "Q = np.max(QV) + 1e-9 "
382 | ]
383 | },
384 | {
385 | "cell_type": "markdown",
386 | "metadata": {},
387 | "source": [
388 | "$$X = BS\\left((1 - \\rho^2)\\int_0^t V_u\\mathrm{d}u; S^1_t,k\\right),\\quad Y = BS\\left(\\rho^2\\left(Q - \\int_0^t V_u\\mathrm{d}u\\right); S^1_t,k\\right)$$"
389 | ]
390 | },
391 | {
392 | "cell_type": "code",
393 | "execution_count": 14,
394 | "metadata": {},
395 | "outputs": [],
396 | "source": [
397 | "S1T = S1[:,-1][:,np.newaxis]\n",
398 | "X = bs(S1T, K, (1 - rB.rho**2) * QV)\n",
399 | "Y = bs(S1T, K, rB.rho**2 * (Q - QV))\n",
400 | "eY = bs(1., K, rB.rho**2 * Q)\n",
401 | "\n",
402 | "# Asymptotically optimal weights\n",
403 | "c = np.zeros_like(k)[np.newaxis,:]\n",
404 | "for i in range(len(k)):\n",
405 | " cov_mat = np.cov(X[:,i], Y[:,i])\n",
406 | " c[0,i] = - cov_mat[0,1] / cov_mat[1,1]\n",
407 | "\n",
408 | "# Payoffs, prices and volatilities\n",
409 | "mixed_payoffs = X + c * (Y - eY)\n",
410 | "mixed_prices = np.mean(mixed_payoffs, axis = 0)[:,np.newaxis]\n",
411 | "mixed_vols = vec_bsinv(mixed_prices, 1., np.transpose(K), rB.T)"
412 | ]
413 | },
414 | {
415 | "cell_type": "markdown",
416 | "metadata": {},
417 | "source": [
418 | "Now plot implied volatilities against Base and Mixed estimators"
419 | ]
420 | },
421 | {
422 | "cell_type": "code",
423 | "execution_count": 15,
424 | "metadata": {},
425 | "outputs": [
426 | {
427 | "data": {
428 | "image/png": "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\n",
429 | "text/plain": [
430 | ""
431 | ]
432 | },
433 | "metadata": {},
434 | "output_type": "display_data"
435 | }
436 | ],
437 | "source": [
438 | "plot,axes = plt.subplots()\n",
439 | "# Add Implied, Base and Mixed vols\n",
440 | "axes.plot(k, implied_vols, 'bo', fillstyle = 'none', ms = 10, mew = 2)\n",
441 | "axes.plot(k, base_vols, 'gx', ms = 7, mew = 2)\n",
442 | "axes.plot(k, mixed_vols, 'rx', ms = 7, mew = 2)\n",
443 | "# Label figure\n",
444 | "axes.set_xlabel(r'$k$',fontsize=16)\n",
445 | "axes.set_ylabel(r'$\\sigma_{BS}(k,t=%.2f)$'%rB.T,fontsize=16)\n",
446 | "title1 = r'$\\mathrm{Base\\ vs\\ Mixed\\ estimators}$'\n",
447 | "title2 = r'$\\xi=%.3f,\\ \\eta=%.2f,\\ \\rho=%.2f,\\ \\alpha=%.2f $'\n",
448 | "axes.set_title(title1+'\\n'+title2%(rB.xi,rB.eta,rB.rho,rB.a), fontsize=16)\n",
449 | "axes.legend([r'$\\mathrm{Implied}$',r'$\\mathrm{Base}$',r'$\\mathrm{Mixed}$'], fontsize=14)\n",
450 | "# Set scale to match paper\n",
451 | "set_scale = True\n",
452 | "if set_scale:\n",
453 | " xmin,xmax = -0.25,0.15\n",
454 | " ymin,ymax = 0.14,0.34\n",
455 | " nticks = 5\n",
456 | " plt.xlim([xmin,xmax])\n",
457 | " plt.ylim([ymin,ymax])\n",
458 | " axes.xaxis.set_ticks(np.linspace(xmin,xmax,nticks))\n",
459 | " axes.yaxis.set_ticks(np.linspace(ymin,ymax,nticks))\n",
460 | "plt.grid(True)"
461 | ]
462 | },
463 | {
464 | "cell_type": "markdown",
465 | "metadata": {},
466 | "source": [
467 | "Please do not attempt to draw conclusions regarding the relative performance of the Base and Mixed estimators from just one (or several) simulation(s) / seed(s) !"
468 | ]
469 | }
470 | ],
471 | "metadata": {
472 | "anaconda-cloud": {},
473 | "kernelspec": {
474 | "display_name": "Python [default]",
475 | "language": "python",
476 | "name": "python3"
477 | },
478 | "language_info": {
479 | "codemirror_mode": {
480 | "name": "ipython",
481 | "version": 3
482 | },
483 | "file_extension": ".py",
484 | "mimetype": "text/x-python",
485 | "name": "python",
486 | "nbconvert_exporter": "python",
487 | "pygments_lexer": "ipython3",
488 | "version": "3.5.2"
489 | }
490 | },
491 | "nbformat": 4,
492 | "nbformat_minor": 1
493 | }
494 |
--------------------------------------------------------------------------------
/papers/hybrid_scheme.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanmccrickerd/rough_bergomi/6a04ca5d2d0f6a45df28ae7bad9c882d537ef14e/papers/hybrid_scheme.pdf
--------------------------------------------------------------------------------
/papers/pricing_under_rough.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanmccrickerd/rough_bergomi/6a04ca5d2d0f6a45df28ae7bad9c882d537ef14e/papers/pricing_under_rough.pdf
--------------------------------------------------------------------------------
/papers/turbocharged_rbergomi.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanmccrickerd/rough_bergomi/6a04ca5d2d0f6a45df28ae7bad9c882d537ef14e/papers/turbocharged_rbergomi.pdf
--------------------------------------------------------------------------------
/papers/volatility_is_rough.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanmccrickerd/rough_bergomi/6a04ca5d2d0f6a45df28ae7bad9c882d537ef14e/papers/volatility_is_rough.pdf
--------------------------------------------------------------------------------
/rbergomi/rbergomi.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from utils import *
3 |
4 | class rBergomi(object):
5 | """
6 | Class for generating paths of the rBergomi model.
7 | """
8 | def __init__(self, n = 100, N = 1000, T = 1.00, a = -0.4):
9 | """
10 | Constructor for class.
11 | """
12 | # Basic assignments
13 | self.T = T # Maturity
14 | self.n = n # Granularity (steps per year)
15 | self.dt = 1.0/self.n # Step size
16 | self.s = int(self.n * self.T) # Steps
17 | self.t = np.linspace(0, self.T, 1 + self.s)[np.newaxis,:] # Time grid
18 | self.a = a # Alpha
19 | self.N = N # Paths
20 |
21 | # Construct hybrid scheme correlation structure for kappa = 1
22 | self.e = np.array([0,0])
23 | self.c = cov(self.a, self.n)
24 |
25 | def dW1(self):
26 | """
27 | Produces random numbers for variance process with required
28 | covariance structure.
29 | """
30 | rng = np.random.multivariate_normal
31 | return rng(self.e, self.c, (self.N, self.s))
32 |
33 | def Y(self, dW):
34 | """
35 | Constructs Volterra process from appropriately
36 | correlated 2d Brownian increments.
37 | """
38 | Y1 = np.zeros((self.N, 1 + self.s)) # Exact integrals
39 | Y2 = np.zeros((self.N, 1 + self.s)) # Riemann sums
40 |
41 | # Construct Y1 through exact integral
42 | for i in np.arange(1, 1 + self.s, 1):
43 | Y1[:,i] = dW[:,i-1,1] # Assumes kappa = 1
44 |
45 | # Construct arrays for convolution
46 | G = np.zeros(1 + self.s) # Gamma
47 | for k in np.arange(2, 1 + self.s, 1):
48 | G[k] = g(b(k, self.a)/self.n, self.a)
49 |
50 | X = dW[:,:,0] # Xi
51 |
52 | # Initialise convolution result, GX
53 | GX = np.zeros((self.N, len(X[0,:]) + len(G) - 1))
54 |
55 | # Compute convolution, FFT not used for small n
56 | # Possible to compute for all paths in C-layer?
57 | for i in range(self.N):
58 | GX[i,:] = np.convolve(G, X[i,:])
59 |
60 | # Extract appropriate part of convolution
61 | Y2 = GX[:,:1 + self.s]
62 |
63 | # Finally contruct and return full process
64 | Y = np.sqrt(2 * self.a + 1) * (Y1 + Y2)
65 | return Y
66 |
67 | def dW2(self):
68 | """
69 | Obtain orthogonal increments.
70 | """
71 | return np.random.randn(self.N, self.s) * np.sqrt(self.dt)
72 |
73 | def dB(self, dW1, dW2, rho = 0.0):
74 | """
75 | Constructs correlated price Brownian increments, dB.
76 | """
77 | self.rho = rho
78 | dB = rho * dW1[:,:,0] + np.sqrt(1 - rho**2) * dW2
79 | return dB
80 |
81 | def V(self, Y, xi = 1.0, eta = 1.0):
82 | """
83 | rBergomi variance process.
84 | """
85 | self.xi = xi
86 | self.eta = eta
87 | a = self.a
88 | t = self.t
89 | V = xi * np.exp(eta * Y - 0.5 * eta**2 * t**(2 * a + 1))
90 | return V
91 |
92 | def S(self, V, dB, S0 = 1):
93 | """
94 | rBergomi price process.
95 | """
96 | self.S0 = S0
97 | dt = self.dt
98 | rho = self.rho
99 |
100 | # Construct non-anticipative Riemann increments
101 | increments = np.sqrt(V[:,:-1]) * dB - 0.5 * V[:,:-1] * dt
102 |
103 | # Cumsum is a little slower than Python loop.
104 | integral = np.cumsum(increments, axis = 1)
105 |
106 | S = np.zeros_like(V)
107 | S[:,0] = S0
108 | S[:,1:] = S0 * np.exp(integral)
109 | return S
110 |
111 | def S1(self, V, dW1, rho, S0 = 1):
112 | """
113 | rBergomi parallel price process.
114 | """
115 | dt = self.dt
116 |
117 | # Construct non-anticipative Riemann increments
118 | increments = rho * np.sqrt(V[:,:-1]) * dW1[:,:,0] - 0.5 * rho**2 * V[:,:-1] * dt
119 |
120 | # Cumsum is a little slower than Python loop.
121 | integral = np.cumsum(increments, axis = 1)
122 |
123 | S = np.zeros_like(V)
124 | S[:,0] = S0
125 | S[:,1:] = S0 * np.exp(integral)
126 | return S
127 |
--------------------------------------------------------------------------------
/rbergomi/utils.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from scipy.stats import norm
3 | from scipy.optimize import brentq
4 |
5 | def g(x, a):
6 | """
7 | TBSS kernel applicable to the rBergomi variance process.
8 | """
9 | return x**a
10 |
11 | def b(k, a):
12 | """
13 | Optimal discretisation of TBSS process for minimising hybrid scheme error.
14 | """
15 | return ((k**(a+1)-(k-1)**(a+1))/(a+1))**(1/a)
16 |
17 | def cov(a, n):
18 | """
19 | Covariance matrix for given alpha and n, assuming kappa = 1 for
20 | tractability.
21 | """
22 | cov = np.array([[0.,0.],[0.,0.]])
23 | cov[0,0] = 1./n
24 | cov[0,1] = 1./((1.*a+1) * n**(1.*a+1))
25 | cov[1,1] = 1./((2.*a+1) * n**(2.*a+1))
26 | cov[1,0] = cov[0,1]
27 | return cov
28 |
29 | def bs(F, K, V, o = 'call'):
30 | """
31 | Returns the Black call price for given forward, strike and integrated
32 | variance.
33 | """
34 | # Set appropriate weight for option token o
35 | w = 1
36 | if o == 'put':
37 | w = -1
38 | elif o == 'otm':
39 | w = 2 * (K > 1.0) - 1
40 |
41 | sv = np.sqrt(V)
42 | d1 = np.log(F/K) / sv + 0.5 * sv
43 | d2 = d1 - sv
44 | P = w * F * norm.cdf(w * d1) - w * K * norm.cdf(w * d2)
45 | return P
46 |
47 | def bsinv(P, F, K, t, o = 'call'):
48 | """
49 | Returns implied Black vol from given call price, forward, strike and time
50 | to maturity.
51 | """
52 | # Set appropriate weight for option token o
53 | w = 1
54 | if o == 'put':
55 | w = -1
56 | elif o == 'otm':
57 | w = 2 * (K > 1.0) - 1
58 |
59 | # Ensure at least instrinsic value
60 | P = np.maximum(P, np.maximum(w * (F - K), 0))
61 |
62 | def error(s):
63 | return bs(F, K, s**2 * t, o) - P
64 | s = brentq(error, 1e-9, 1e+9)
65 | return s
66 |
--------------------------------------------------------------------------------
/surface0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanmccrickerd/rough_bergomi/6a04ca5d2d0f6a45df28ae7bad9c882d537ef14e/surface0.png
--------------------------------------------------------------------------------
/surface1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanmccrickerd/rough_bergomi/6a04ca5d2d0f6a45df28ae7bad9c882d537ef14e/surface1.png
--------------------------------------------------------------------------------