.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/pde_methods/schemes/plot_01_crank_nicolson.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code or to run this example in your browser via JupyterLite. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_pde_methods_schemes_plot_01_crank_nicolson.py: Crank-Nicolson ============== John Crank and Phyllis Nicolson (1947) averaged the explicit and implicit differences of the heat equation around the half step, .. math:: \frac{V^{n+1} - V^n}{\Delta\tau} = \tfrac12 \bigl(A V^{n+1} + A V^n\bigr), which makes the scheme unconditionally stable *and* second-order accurate in time. Applied to the Black-Scholes equation it is the workhorse of finite-difference option pricing. Here :class:`~financialkit.pde_methods.CrankNicolson` prices a call and its error falls by four each time both grids are halved. .. GENERATED FROM PYTHON SOURCE LINES 18-31 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from financialkit.options import black_scholes_price from financialkit.pde_methods import CrankNicolson from financialkit.pde_methods.visualizers import plot_grid_convergence, plot_value_surface S, K, T, r, sigma = 100.0, 100.0, 1.0, 0.05, 0.2 exact = black_scholes_price(S, K, T, r, sigma) res = CrankNicolson(200, 100, rannacher_steps=2).price(S, K, T, r, sigma) print(f"Crank-Nicolson {res.price:.5f}, Black-Scholes {exact:.5f}") .. rst-class:: sphx-glr-script-out .. code-block:: none Crank-Nicolson 10.44060, Black-Scholes 10.45058 .. GENERATED FROM PYTHON SOURCE LINES 32-34 The value surface, from the payoff at expiry back to today ---------------------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 34-39 .. code-block:: Python fig, axes = plt.subplots(1, 2, figsize=(11, 4)) plot_value_surface(res, ax=axes[0], s_range=(40, 180)) axes[0].set_title("call value V(S, t)") .. image-sg:: /api/gallery/pde_methods/schemes/images/sphx_glr_plot_01_crank_nicolson_001.png :alt: call value V(S, t) :srcset: /api/gallery/pde_methods/schemes/images/sphx_glr_plot_01_crank_nicolson_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Text(0.5, 1.0, 'call value V(S, t)') .. GENERATED FROM PYTHON SOURCE LINES 40-42 Second order in space and time together --------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 42-49 .. code-block:: Python ns = np.array([25, 50, 100, 200, 400]) errors = [abs(CrankNicolson(n, n, rannacher_steps=2, s_max=400.0).price(S, K, T, r, sigma).price - exact) for n in ns] plot_grid_convergence(ns, errors, ax=axes[1], label="Crank-Nicolson, M = N = n", rates=(2.0,)) axes[1].set_title("error against grid size") fig.tight_layout() plt.show() .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.140 seconds) .. _sphx_glr_download_api_gallery_pde_methods_schemes_plot_01_crank_nicolson.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: lite-badge .. image:: images/jupyterlite_badge_logo.svg :target: ../../../../lite/lab/index.html?path=api/gallery/pde_methods/schemes/plot_01_crank_nicolson.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_01_crank_nicolson.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_01_crank_nicolson.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_01_crank_nicolson.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_