.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/interest_rate_models/short_rate/plot_07_g2pp.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_interest_rate_models_short_rate_plot_07_g2pp.py: Brigo-Mercurio G2++: two Gaussian factors ========================================= In a one-factor model a single shock moves every yield, so the 1-year and 30-year rates are perfectly correlated, which the data flatly reject. Damiano Brigo and Fabio Mercurio's G2++ (2001) adds a second Gaussian factor, .. math:: r = x + y + \varphi(t), \quad dx = -a x\,dt + \sigma\,dW_1, \quad dy = -b y\,dt + \eta\,dW_2, \quad dW_1 dW_2 = \rho\,dt, with :math:`\varphi` fitted to today's curve. Bonds and bond options stay in closed form, and a negative :math:`\rho` between a fast and a slow factor decorrelates the ends of the curve. .. GENERATED FROM PYTHON SOURCE LINES 19-28 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from financialkit.fixed_income import NelsonSiegelCurve from financialkit.interest_rate_models import G2PlusPlusModel, monte_carlo_bond_prices curve = NelsonSiegelCurve(0.045, -0.02, 0.01, 2.0) model = G2PlusPlusModel(curve, a=0.8, sigma=0.012, b=0.05, eta=0.008, rho=-0.75) .. GENERATED FROM PYTHON SOURCE LINES 29-31 Correlation between yields -------------------------- .. GENERATED FROM PYTHON SOURCE LINES 31-41 .. code-block:: Python taus = np.array([0.5, 1, 2, 5, 10, 20, 30]) fig, axes = plt.subplots(1, 3, figsize=(14, 4)) im = axes[0].imshow(model.yield_correlation(taus[:, None], taus[None, :]), vmin=0, vmax=1, cmap="viridis") axes[0].set_xticks(range(taus.size), [f"{t:g}" for t in taus]) axes[0].set_yticks(range(taus.size), [f"{t:g}" for t in taus]) axes[0].set_title("instantaneous yield correlation") fig.colorbar(im, ax=axes[0]) print(f"corr(1y, 30y): G2++ {model.yield_correlation(1.0, 30.0):.2f}; any one-factor model 1.00") .. image-sg:: /api/gallery/interest_rate_models/short_rate/images/sphx_glr_plot_07_g2pp_001.png :alt: instantaneous yield correlation :srcset: /api/gallery/interest_rate_models/short_rate/images/sphx_glr_plot_07_g2pp_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none corr(1y, 30y): G2++ 0.37; any one-factor model 1.00 .. GENERATED FROM PYTHON SOURCE LINES 42-44 The same correlation from simulated yield changes ------------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 44-60 .. code-block:: Python _, xy = model.simulate_factors(1.0, 50, 4000, rng=0) dx = xy[:, 1, :] - xy[:, 0, :] # factor moves over the first step def dyield(tau): """Change in the tau-year yield, -d ln P / tau = (B_a dx + B_b dy) / tau.""" Ba, Bb = -np.expm1(-model.a * tau) / model.a, -np.expm1(-model.b * tau) / model.b return (Ba * dx[:, 0] + Bb * dx[:, 1]) / tau axes[1].scatter(1e4 * dyield(1.0), 1e4 * dyield(30.0), s=2, alpha=0.3) axes[1].set_xlabel("1y yield change (bp)") axes[1].set_ylabel("30y yield change (bp)") axes[1].set_title(f"sample corr {np.corrcoef(dyield(1.0), dyield(30.0))[0, 1]:.2f}") .. rst-class:: sphx-glr-script-out .. code-block:: none Text(0.5, 1.0, 'sample corr 0.37') .. GENERATED FROM PYTHON SOURCE LINES 61-63 The fitted model reprices the curve ----------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 63-74 .. code-block:: Python res = monte_carlo_bond_prices(model, np.arange(1.0, 11.0), n_steps=100, n_paths=8000, rng=1) axes[2].plot(res.maturities, 100 * -np.log(res.exact) / res.maturities, "k-", label="initial curve") yield_se = 100 * res.std_errors / res.prices / res.maturities axes[2].errorbar(res.maturities, 100 * -np.log(res.prices) / res.maturities, yerr=1.96 * yield_se, fmt="o", ms=3, label="G2++ Monte Carlo") axes[2].set_xlabel("maturity (years)") axes[2].set_ylabel("zero yield (%)") axes[2].legend() fig.tight_layout() plt.show() .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.601 seconds) .. _sphx_glr_download_api_gallery_interest_rate_models_short_rate_plot_07_g2pp.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/interest_rate_models/short_rate/plot_07_g2pp.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_07_g2pp.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_07_g2pp.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_07_g2pp.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_