.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/fixed_income/curves/plot_04_nelson_siegel.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_fixed_income_curves_plot_04_nelson_siegel.py: Nelson-Siegel ============= Nelson and Siegel (1987) described the whole yield curve with four numbers: .. math:: r(t) = \beta_0 + \beta_1 \frac{1-e^{-t/\tau}}{t/\tau} + \beta_2\left(\frac{1-e^{-t/\tau}}{t/\tau} - e^{-t/\tau}\right). The three loadings are a level, a slope that decays from 1 to 0, and a hump. The script plots them and fits the model to noisy yields. .. GENERATED FROM PYTHON SOURCE LINES 15-21 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from financialkit.fixed_income import NelsonSiegelCurve, fit_nelson_siegel from financialkit.fixed_income.visualizers import plot_yield_curve .. GENERATED FROM PYTHON SOURCE LINES 22-24 The three loadings ------------------ .. GENERATED FROM PYTHON SOURCE LINES 24-33 .. code-block:: Python t = np.linspace(0.01, 30, 300) fig, ax = plt.subplots() for name, curve in (("level", NelsonSiegelCurve(1, 0, 0, 2.0)), ("slope", NelsonSiegelCurve(0, 1, 0, 2.0)), ("curvature", NelsonSiegelCurve(0, 0, 1, 2.0))): ax.plot(t, curve.zero_rate(t), label=name) ax.set_xlabel("maturity (years)") ax.set_ylabel(r"loading ($\tau$ = 2)") ax.legend() .. image-sg:: /api/gallery/fixed_income/curves/images/sphx_glr_plot_04_nelson_siegel_001.png :alt: plot 04 nelson siegel :srcset: /api/gallery/fixed_income/curves/images/sphx_glr_plot_04_nelson_siegel_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 34-36 Fit to noisy yields ------------------- .. GENERATED FROM PYTHON SOURCE LINES 36-47 .. code-block:: Python rng = np.random.default_rng(1987) tenors = np.array([0.25, 0.5, 1, 2, 3, 5, 7, 10, 15, 20, 30]) true = NelsonSiegelCurve(0.048, -0.022, 0.025, 1.6) observed = true.zero_rate(tenors) + rng.normal(0, 0.0005, tenors.size) fit = fit_nelson_siegel(tenors, observed) print("fitted [b0, b1, b2, tau]:", fit.params.round(4), f"RMSE {1e4 * fit.rmse:.1f} bp") ax = plot_yield_curve(fit.curve, label="fitted") ax.plot(tenors, 100 * observed, "ko", label="observed") ax.legend() plt.show() .. image-sg:: /api/gallery/fixed_income/curves/images/sphx_glr_plot_04_nelson_siegel_002.png :alt: plot 04 nelson siegel :srcset: /api/gallery/fixed_income/curves/images/sphx_glr_plot_04_nelson_siegel_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none fitted [b0, b1, b2, tau]: [ 0.0485 -0.0225 0.0233 1.5472] RMSE 2.4 bp .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.132 seconds) .. _sphx_glr_download_api_gallery_fixed_income_curves_plot_04_nelson_siegel.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/fixed_income/curves/plot_04_nelson_siegel.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_04_nelson_siegel.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_04_nelson_siegel.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_04_nelson_siegel.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_