|
36 | 36 | } |
37 | 37 | ], |
38 | 38 | "source": [ |
39 | | - "from devito import (Eq, Grid, TimeFunction, Operator, solve, Constant,\n", |
| 39 | + "from devito import (Eq, Grid, TimeFunction, Operator, solve, Constant, \n", |
40 | 40 | " SpaceDimension, configuration, centered)\n", |
41 | 41 | "\n", |
| 42 | + "from mpl_toolkits.mplot3d import Axes3D\n", |
| 43 | + "from mpl_toolkits.mplot3d.axis3d import Axis\n", |
42 | 44 | "import matplotlib.pyplot as plt\n", |
43 | 45 | "import matplotlib as mpl\n", |
44 | 46 | "\n", |
|
51 | 53 | "\n", |
52 | 54 | "configuration[\"log-level\"] = 'INFO'\n", |
53 | 55 | "\n", |
54 | | - "# Constants\n", |
| 56 | + "## Constants\n", |
55 | 57 | "# The strike price of the option\n", |
56 | 58 | "K = 100.0\n", |
57 | 59 | "\n", |
|
67 | 69 | "\n", |
68 | 70 | "# If you want to try some different problems, uncomment these lines\n", |
69 | 71 | "\n", |
70 | | - "# Example 2\n", |
| 72 | + "## Example 2\n", |
71 | 73 | "# K = 10.0\n", |
72 | 74 | "# r = 0.1\n", |
73 | 75 | "# sigma = 0.2\n", |
74 | 76 | "# smin = 0.0\n", |
75 | 77 | "# smax = 20.0\n", |
76 | 78 | "\n", |
77 | | - "# Example 3\n", |
| 79 | + "## Example 3\n", |
78 | 80 | "# K = 100.0\n", |
79 | 81 | "# r = 0.05\n", |
80 | 82 | "# sigma = 0.25\n", |
81 | 83 | "# smin = 50.0\n", |
82 | 84 | "# smax = 150.0\n", |
83 | 85 | "\n", |
84 | | - "# Amount of padding to process left/right (hidden from graphs)\n", |
| 86 | + "# Amount of padding to proccess left/right (hidden from graphs)\n", |
85 | 87 | "padding = 10\n", |
86 | 88 | "smin -= padding\n", |
87 | 89 | "smax += padding\n", |
88 | 90 | "\n", |
89 | 91 | "# Extent calculations\n", |
90 | 92 | "tmax = 1.0\n", |
91 | 93 | "dt0 = 0.0005\n", |
92 | | - "ds0 = 1.0\n", |
| 94 | + "ds0 = 1.0\n", |
93 | 95 | "nt = (int)(tmax / dt0) + 1\n", |
94 | | - "ns = int((smax - smin) / ds0) + 1\n", |
| 96 | + "ns = int((smax - smin) / ds0) + 1 \n", |
95 | 97 | "\n", |
96 | 98 | "shape = (ns, )\n", |
97 | | - "origin = (smin, )\n", |
| 99 | + "origin =(smin, )\n", |
98 | 100 | "spacing = (ds0, )\n", |
99 | 101 | "extent = int(ds0 * (ns - 1))\n", |
100 | 102 | "\n", |
101 | | - "print(\"dt,tmax,nt;\", dt0, tmax, nt)\n", |
| 103 | + "print(\"dt,tmax,nt;\", dt0,tmax,nt)\n", |
102 | 104 | "print(\"shape; \", shape)\n", |
103 | 105 | "print(\"origin; \", origin)\n", |
104 | 106 | "print(\"spacing; \", spacing)\n", |
|
162 | 164 | "grid = Grid(shape=shape, origin=origin, extent=extent, dimensions=(s, ))\n", |
163 | 165 | "\n", |
164 | 166 | "so = 2\n", |
165 | | - "v = TimeFunction(name='v', grid=grid, space_order=so, time_order=1, save=nt)\n", |
166 | | - "v_no_bc = TimeFunction(name='v_no_bc', grid=grid, space_order=so, time_order=1, save=nt)\n", |
| 167 | + "v = TimeFunction(name='v', grid=grid, space_order=so, time_order=1, save=nt)\n", |
| 168 | + "v_no_bc = TimeFunction(name='v_no_bc', grid=grid, space_order=so, time_order=1, save=nt)\n", |
167 | 169 | "\n", |
168 | | - "t, s = v.dimensions\n", |
| 170 | + "t,s = v.dimensions\n", |
169 | 171 | "ds = s.spacing\n", |
170 | 172 | "dt = t.spacing\n", |
171 | 173 | "\n", |
|
215 | 217 | "outputs": [], |
216 | 218 | "source": [ |
217 | 219 | "# Equations with Neumann boundary conditions\n", |
218 | | - "eq = [Eq(v[t, extent], v[t, extent-1]+(v[t, extent-1]-v[t, extent-2])),\n", |
219 | | - " Eq(v[t, extent+1], v[t, extent]+(v[t, extent-1]-v[t, extent-2])),\n", |
| 220 | + "eq = [Eq(v[t,extent], v[t,extent-1]+(v[t,extent-1]-v[t,extent-2])),\n", |
| 221 | + " Eq(v[t,extent+1], v[t,extent]+(v[t,extent-1]-v[t,extent-2])),\n", |
220 | 222 | " Eq(v.forward, update_centered)]\n", |
221 | 223 | "eq_no_bc = [Eq(v.forward, update_centered)]\n", |
222 | 224 | "\n", |
223 | | - "op = Operator(eq, subs=v.grid.spacing_map)\n", |
| 225 | + "op = Operator(eq, subs=v.grid.spacing_map)\n", |
224 | 226 | "op_no_bc = Operator(eq_no_bc, subs=v_no_bc.grid.spacing_map)\n", |
225 | 227 | "\n", |
226 | 228 | "# Initial conditions\n", |
227 | 229 | "\n", |
228 | 230 | "for i in range(shape[0]):\n", |
229 | | - " v.data[0, i] = max((smin + ds0 * i) - K, 0)\n", |
| 231 | + " v.data[0, i] = max((smin + ds0 * i) - K, 0)\n", |
230 | 232 | " v_no_bc.data[0, i] = max((smin + ds0 * i) - K, 0)" |
231 | 233 | ] |
232 | 234 | }, |
|
239 | 241 | "name": "stderr", |
240 | 242 | "output_type": "stream", |
241 | 243 | "text": [ |
242 | | - "Operator `Kernel` run in 0.01 s\n", |
243 | | - "Operator `Kernel` run in 0.01 s\n" |
| 244 | + "Operator `Kernel` ran in 0.01 s\n", |
| 245 | + "Operator `Kernel` ran in 0.01 s\n" |
244 | 246 | ] |
245 | 247 | }, |
246 | 248 | { |
|
256 | 258 | } |
257 | 259 | ], |
258 | 260 | "source": [ |
259 | | - "# NBVAL_IGNORE_OUTPUT\n", |
| 261 | + "#NBVAL_IGNORE_OUTPUT\n", |
260 | 262 | "\n", |
261 | 263 | "# Run our operators\n", |
262 | 264 | "startDevito = timer.time()\n", |
|
287 | 289 | } |
288 | 290 | ], |
289 | 291 | "source": [ |
290 | | - "# NBVAL_IGNORE_OUTPUT\n", |
| 292 | + "#NBVAL_IGNORE_OUTPUT\n", |
291 | 293 | "\n", |
292 | 294 | "# Get an appropriate ylimit\n", |
293 | 295 | "slice_smax = v.data[:, int(smax-smin-padding)]\n", |
294 | 296 | "ymax = max(slice_smax) + 2\n", |
295 | 297 | "\n", |
296 | 298 | "# Plot\n", |
297 | 299 | "s = np.linspace(smin, smax, shape[0])\n", |
298 | | - "plt.figure(figsize=(12, 10), facecolor='w')\n", |
| 300 | + "plt.figure(figsize=(12,10), facecolor='w')\n", |
299 | 301 | "\n", |
300 | 302 | "time = [1*nt//5, 2*nt//5, 3*nt//5, 4*nt//5, 5*nt//5-1]\n", |
301 | 303 | "colors = [\"blue\", \"green\", \"gold\", \"darkorange\", \"red\"]\n", |
302 | 304 | "\n", |
303 | 305 | "# initial conditions\n", |
304 | | - "plt.plot(s, v_no_bc.data[0, :], '-', color=\"black\", label='initial condition', linewidth=1)\n", |
| 306 | + "plt.plot(s, v_no_bc.data[0,:], '-', color=\"black\", label='initial condition', linewidth=1)\n", |
305 | 307 | "\n", |
306 | 308 | "for i in range(len(time)):\n", |
307 | | - " plt.plot(s, v_no_bc.data[time[i], :], '-', color=colors[i], label='t='+str(time[i]*dt0), linewidth=1.5)\n", |
| 309 | + " plt.plot(s, v_no_bc.data[time[i],:], '-', color=colors[i], label='t='+str(time[i]*dt0), linewidth=1.5)\n", |
308 | 310 | "\n", |
309 | | - "plt.xlim([smin+padding, smax-padding])\n", |
310 | | - "plt.ylim([0, ymax])\n", |
| 311 | + "plt.xlim([smin+padding,smax-padding])\n", |
| 312 | + "plt.ylim([0,ymax])\n", |
311 | 313 | "\n", |
312 | 314 | "plt.legend(loc=2)\n", |
313 | 315 | "plt.grid(True)\n", |
|
341 | 343 | } |
342 | 344 | ], |
343 | 345 | "source": [ |
344 | | - "# NBVAL_IGNORE_OUTPUT\n", |
| 346 | + "#NBVAL_IGNORE_OUTPUT\n", |
345 | 347 | "\n", |
346 | 348 | "# Get an appropriate ylimit\n", |
347 | | - "slice_smax = v.data[:, int(smax-smin-padding)]\n", |
| 349 | + "slice_smax = v.data[:,int(smax-smin-padding)]\n", |
348 | 350 | "ymax = max(slice_smax) + 2\n", |
349 | 351 | "\n", |
350 | 352 | "# Plot\n", |
351 | 353 | "s = np.linspace(smin, smax, shape[0])\n", |
352 | | - "plt.figure(figsize=(12, 10), facecolor='w')\n", |
| 354 | + "plt.figure(figsize=(12,10), facecolor='w')\n", |
353 | 355 | "\n", |
354 | 356 | "time = [1*nt//5, 2*nt//5, 3*nt//5, 4*nt//5, 5*nt//5-1]\n", |
355 | 357 | "colors = [\"blue\", \"green\", \"gold\", \"darkorange\", \"red\"]\n", |
356 | 358 | "\n", |
357 | 359 | "# initial conditions\n", |
358 | | - "plt.plot(s, v.data[0, :], '-', color=\"black\", label='initial condition', linewidth=1)\n", |
| 360 | + "plt.plot(s, v.data[0,:], '-', color=\"black\", label='initial condition', linewidth=1)\n", |
359 | 361 | "\n", |
360 | 362 | "for i in range(len(time)):\n", |
361 | | - " plt.plot(s, v.data[time[i], :], '-', color=colors[i], label='t='+str(time[i]*dt0), linewidth=1.5)\n", |
| 363 | + " plt.plot(s, v.data[time[i],:], '-', color=colors[i], label='t='+str(time[i]*dt0), linewidth=1.5)\n", |
362 | 364 | "\n", |
363 | | - "plt.xlim([smin+padding, smax-padding])\n", |
364 | | - "plt.ylim([0, ymax])\n", |
| 365 | + "plt.xlim([smin+padding,smax-padding])\n", |
| 366 | + "plt.ylim([0,ymax])\n", |
365 | 367 | "\n", |
366 | 368 | "plt.legend(loc=2)\n", |
367 | 369 | "plt.grid(True)\n", |
|
403 | 405 | } |
404 | 406 | ], |
405 | 407 | "source": [ |
406 | | - "# NBVAL_IGNORE_OUTPUT\n", |
| 408 | + "#NBVAL_IGNORE_OUTPUT\n", |
407 | 409 | "\n", |
| 410 | + "from mpl_toolkits.mplot3d import Axes3D\n", |
408 | 411 | "\n", |
409 | 412 | "# Trim the padding off smin and smax\n", |
410 | 413 | "trim_data = v.data[:, padding:-padding]\n", |
|
413 | 416 | "tt = np.linspace(0.0, dt0*(nt-1), nt)\n", |
414 | 417 | "ss = np.linspace(smin+padding, smax-padding, shape[0]-padding*2)\n", |
415 | 418 | "\n", |
416 | | - "hf = plt.figure(figsize=(12, 12))\n", |
| 419 | + "hf = plt.figure(figsize=(12,12))\n", |
417 | 420 | "ha = plt.axes(projection='3d')\n", |
418 | 421 | "\n", |
419 | 422 | "# 45 degree viewpoint\n", |
420 | 423 | "ha.view_init(elev=25, azim=-45)\n", |
421 | 424 | "\n", |
422 | | - "ha.set_xlim3d([0.0, 1.0])\n", |
423 | | - "ha.set_ylim3d([smin+padding, smax-padding])\n", |
424 | | - "ha.set_zlim3d([0, ymax])\n", |
| 425 | + "ha.set_xlim3d([0.0,1.0])\n", |
| 426 | + "ha.set_ylim3d([smin+padding,smax-padding])\n", |
| 427 | + "ha.set_zlim3d([0,ymax])\n", |
425 | 428 | "\n", |
426 | 429 | "ha.set_xlabel('Time to expiration', labelpad=12, fontsize=16)\n", |
427 | 430 | "ha.set_ylabel('Stock value', labelpad=12, fontsize=16)\n", |
|
473 | 476 | "name": "stdout", |
474 | 477 | "output_type": "stream", |
475 | 478 | "text": [ |
476 | | - "devito pde timesteps: 2000, 0.205647s runtime\n", |
477 | | - "call_value_bs timesteps: 5, 3.813932s runtime\n" |
| 479 | + "devito pde timesteps: 2000, 0.019737s runtime\n", |
| 480 | + "call_value_bs timesteps: 5, 2.596800s runtime\n" |
478 | 481 | ] |
479 | 482 | }, |
480 | 483 | { |
|
491 | 494 | } |
492 | 495 | ], |
493 | 496 | "source": [ |
494 | | - "# NBVAL_IGNORE_OUTPUT\n", |
| 497 | + "#NBVAL_IGNORE_OUTPUT\n", |
495 | 498 | "\n", |
496 | | - "# Derived formula for Black Scholes call from\n", |
| 499 | + "# Derived formula for Black Scholes call from \n", |
497 | 500 | "# https://aaronschlegel.me/black-scholes-formula-python.html\n", |
498 | 501 | "def call_value_bs(S, K, T, r, sigma):\n", |
499 | 502 | " N = Normal('x', 0.0, 1.0)\n", |
|
504 | 507 | " call = (S * cdf(N)(d1) - K * np.exp(-r * T) * cdf(N)(d2))\n", |
505 | 508 | " return call\n", |
506 | 509 | "\n", |
507 | | - "\n", |
508 | 510 | "startBF = timer.time()\n", |
509 | 511 | "\n", |
510 | 512 | "# Calculate truth and compare to our solution\n", |
|
519 | 521 | "\n", |
520 | 522 | "endBF = timer.time()\n", |
521 | 523 | "\n", |
522 | | - "print(f\"devito pde timesteps: {nt - 1}, {endDevito - startDevito:12.6f}s runtime\")\n", |
523 | | - "print(f\"call_value_bs timesteps: {len(time)}, {endBF - startBF:12.6f}s runtime\")\n", |
524 | | - "\n", |
| 524 | + "print(\"devito pde timesteps: %12.6s, %12.6fs runtime\" % (nt-1, endDevito - startDevito))\n", |
| 525 | + "print(\"call_value_bs timesteps: %12.6s, %12.6fs runtime\" % (len(time), endBF - startBF))\n", |
| 526 | + " \n", |
525 | 527 | "s2 = np.linspace(smin, smax, shape[0])\n", |
526 | | - "plt.figure(figsize=(12, 10))\n", |
| 528 | + "plt.figure(figsize=(12,10))\n", |
527 | 529 | "\n", |
528 | 530 | "colors = [\"blue\", \"green\", \"gold\", \"darkorange\", \"red\"]\n", |
529 | | - "plt.plot(s2, v.data[0, :], '-', color=\"black\", label='initial condition', linewidth=1)\n", |
| 531 | + "plt.plot(s2, v.data[0,:], '-', color=\"black\", label='initial condition', linewidth=1)\n", |
530 | 532 | "\n", |
531 | 533 | "for i in range(len(time)):\n", |
532 | | - " plt.plot(s2, results[i], ':', color=colors[i], label='truth t='+str(time[i]), linewidth=3)\n", |
533 | | - " plt.plot(s2, v.data[int(time[i]*nt), :], '-', color=colors[i], label='pde t='+str(time[i]), linewidth=1)\n", |
| 534 | + " plt.plot(s2, results[i], ':', color=colors[i], label='truth t='+str(time[i]), linewidth=3)\n", |
| 535 | + " plt.plot(s2, v.data[int(time[i]*nt),:], '-', color=colors[i], label='pde t='+str(time[i]), linewidth=1)\n", |
534 | 536 | "\n", |
535 | | - "plt.xlim([smin+padding, smax-padding])\n", |
536 | | - "plt.ylim([0, ymax])\n", |
| 537 | + "plt.xlim([smin+padding,smax-padding])\n", |
| 538 | + "plt.ylim([0,ymax])\n", |
537 | 539 | "\n", |
538 | 540 | "plt.legend()\n", |
539 | 541 | "plt.grid(True)\n", |
|
560 | 562 | { |
561 | 563 | "data": { |
562 | 564 | "text/plain": [ |
563 | | - "[<matplotlib.lines.Line2D at 0x7f5495584640>]" |
| 565 | + "[<matplotlib.lines.Line2D at 0x7fe2669fda50>]" |
564 | 566 | ] |
565 | 567 | }, |
566 | 568 | "execution_count": 9, |
|
581 | 583 | } |
582 | 584 | ], |
583 | 585 | "source": [ |
584 | | - "# NBVAL_IGNORE_OUTPUT\n", |
| 586 | + "#NBVAL_IGNORE_OUTPUT\n", |
585 | 587 | "\n", |
586 | 588 | "# Plot the l2 norm of the formula and our solution over time\n", |
587 | 589 | "t_range = np.linspace(dt0, 1.0, 50)\n", |
|
592 | 594 | " l2 = 0.0\n", |
593 | 595 | " for x in x_range:\n", |
594 | 596 | " truth = call_value_bs(x+smin, K, t, r, sigma)\n", |
595 | | - " val = v.data[int(t*(nt-1)), x]\n", |
596 | | - " l2 += (truth - val)**2\n", |
| 597 | + " val = v.data[int(t*(nt-1)), x]\n", |
| 598 | + " l2 += (truth - val)**2\n", |
597 | 599 | "\n", |
598 | 600 | " rms = np.sqrt(np.float64(l2 / len(x_range)))\n", |
599 | 601 | " vals.append(rms)\n", |
600 | 602 | "\n", |
601 | | - "plt.figure(figsize=(12, 10))\n", |
| 603 | + "plt.figure(figsize=(12,10))\n", |
602 | 604 | "plt.plot(t_range, np.array(vals))" |
603 | 605 | ] |
604 | 606 | }, |
|
610 | 612 | { |
611 | 613 | "data": { |
612 | 614 | "text/plain": [ |
613 | | - "0.00581731890853893" |
| 615 | + "np.float64(0.005885208362743295)" |
614 | 616 | ] |
615 | 617 | }, |
616 | 618 | "execution_count": 10, |
|
619 | 621 | } |
620 | 622 | ], |
621 | 623 | "source": [ |
622 | | - "# NBVAL_IGNORE_OUTPUT\n", |
| 624 | + "#NBVAL_IGNORE_OUTPUT\n", |
623 | 625 | "\n", |
624 | 626 | "np.mean(vals)" |
625 | 627 | ] |
|
0 commit comments