.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/fixed_income/duration/plot_04_convexity.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_duration_plot_04_convexity.py: Bierwag-Kaufman-Toevs: convexity ================================ Duration is a tangent, but the price-yield curve bends. Bierwag, Kaufman and Toevs (1983) brought the second-order term into portfolio practice: .. math:: \frac{\Delta P}{P} \approx -D_{mod}\,\Delta y + \tfrac12 C\,(\Delta y)^2, \qquad C = \frac{1}{P}\frac{d^2P}{dy^2}. For a long bond the convexity term removes most of the duration approximation's error, and a barbell of the same duration as a bullet is more convex. .. GENERATED FROM PYTHON SOURCE LINES 17-26 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from financialkit.fixed_income import CashFlows, bond_cash_flows, bond_risk, price_from_yield from financialkit.fixed_income.visualizers import plot_price_yield cf = bond_cash_flows(100.0, 0.04, 30.0) plot_price_yield(cf, 0.04, dy=0.04).set_title("30-year 4% bond") .. image-sg:: /api/gallery/fixed_income/duration/images/sphx_glr_plot_04_convexity_001.png :alt: 30-year 4% bond :srcset: /api/gallery/fixed_income/duration/images/sphx_glr_plot_04_convexity_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Text(0.5, 1.0, '30-year 4% bond') .. GENERATED FROM PYTHON SOURCE LINES 27-29 Approximation errors -------------------- .. GENERATED FROM PYTHON SOURCE LINES 29-40 .. code-block:: Python risk = bond_risk(cf, 0.04) dy = np.linspace(-0.03, 0.03, 61) exact = price_from_yield(cf, 0.04 + dy) - risk.price fig, ax = plt.subplots() ax.plot(1e4 * dy, risk.price_change(dy, order=1) - exact, label="duration only") ax.plot(1e4 * dy, risk.price_change(dy, order=2) - exact, label="duration + convexity") ax.set_xlabel("yield change (bp)") ax.set_ylabel("approximation error") ax.legend() .. image-sg:: /api/gallery/fixed_income/duration/images/sphx_glr_plot_04_convexity_002.png :alt: plot 04 convexity :srcset: /api/gallery/fixed_income/duration/images/sphx_glr_plot_04_convexity_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 41-43 Bullet versus barbell of equal duration --------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 43-52 .. code-block:: Python y = 0.04 bullet = CashFlows([10.0], [100.0]) w = 0.5 # half in 2-year, half in 18-year zeros: Macaulay duration 10 barbell = CashFlows([2.0, 18.0], [w * 100 * np.exp(-y * 8), (1 - w) * 100 * np.exp(y * 8)]) for name, port in (("bullet", bullet), ("barbell", barbell)): r = bond_risk(port, y) print(f"{name:8s} D={r.macaulay_duration:.3f} C={r.convexity:.2f}") plt.show() .. rst-class:: sphx-glr-script-out .. code-block:: none bullet D=10.000 C=100.00 barbell D=10.000 C=164.00 .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.051 seconds) .. _sphx_glr_download_api_gallery_fixed_income_duration_plot_04_convexity.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/duration/plot_04_convexity.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_04_convexity.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_04_convexity.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_04_convexity.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_