.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/interest_rate_models/curve_fitted/plot_01_ho_lee.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_curve_fitted_plot_01_ho_lee.py: Ho-Lee: the first arbitrage-free term-structure model ===================================================== Thomas Ho and Sang-Bin Lee (1986) turned the problem around. Instead of deriving a curve from a short-rate model, they took today's curve as given and made the model fit it: a binomial tree of whole discount curves whose drift is chosen to reprice every bond. Its continuous-time limit is Merton's Gaussian rate with a time-dependent drift, .. math:: dr = \theta(t)\,dt + \sigma\,dW, \qquad \theta(t) = \partial_t f(0, t) + \sigma^2 t, so any initial curve is matched exactly and every interest-rate derivative is priced relative to it. .. GENERATED FROM PYTHON SOURCE LINES 18-28 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from financialkit.fixed_income import NelsonSiegelCurve from financialkit.fixed_income.visualizers import plot_yield_curve from financialkit.interest_rate_models import HoLeeModel, VasicekModel, monte_carlo_bond_prices curve = NelsonSiegelCurve(0.05, -0.025, 0.02, 1.5) # a humped market curve model = HoLeeModel(curve, sigma=0.01) .. GENERATED FROM PYTHON SOURCE LINES 29-35 An equilibrium model cannot fit the market ------------------------------------------ The best a Vasicek curve can do is a smooth monotone or single-hump shape tied to its own parameters; Ho-Lee reproduces the market curve by construction. .. GENERATED FROM PYTHON SOURCE LINES 35-42 .. code-block:: Python fig, axes = plt.subplots(1, 3, figsize=(14, 4)) plot_yield_curve(curve, t_max=20, ax=axes[0], label="market", show_forward=False) T = np.linspace(0.1, 20, 200) axes[0].plot(T, 100 * VasicekModel(0.025, 0.3, 0.06, 0.015).yields(T), "--", label="a Vasicek curve") axes[0].legend() .. image-sg:: /api/gallery/interest_rate_models/curve_fitted/images/sphx_glr_plot_01_ho_lee_001.png :alt: plot 01 ho lee :srcset: /api/gallery/interest_rate_models/curve_fitted/images/sphx_glr_plot_01_ho_lee_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 43-45 The drift that fits the curve ----------------------------- .. GENERATED FROM PYTHON SOURCE LINES 45-54 .. code-block:: Python t = np.linspace(0.0, 20, 200) axes[1].plot(t, 100 * model.theta(t), label=r"$\theta(t)$") axes[1].plot(t, 100 * curve.instantaneous_forward(t), label="f(0, t)") axes[1].plot(t, 100 * model.shift(t), label=r"E[r(t)] = f(0,t) + $\sigma^2 t^2/2$") axes[1].set_xlabel("t (years)") axes[1].set_ylabel("% per year") axes[1].legend() .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 55-57 Simulated rates reprice every market bond ----------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 57-68 .. code-block:: Python res = monte_carlo_bond_prices(model, np.arange(1.0, 21.0), n_steps=200, n_paths=8000, rng=0) axes[2].plot(res.maturities, 100 * curve.zero_rate(res.maturities), "k-", label="market zero curve") axes[2].plot(res.maturities, 100 * -np.log(res.prices) / res.maturities, "o", ms=3, label="Ho-Lee Monte Carlo") axes[2].set_xlabel("maturity (years)") axes[2].set_ylabel("zero yield (%)") axes[2].legend() print(f"largest |z| across 20 maturities: {np.abs(res.z_scores).max():.2f}") fig.tight_layout() plt.show() .. rst-class:: sphx-glr-script-out .. code-block:: none largest |z| across 20 maturities: 1.50 .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.596 seconds) .. _sphx_glr_download_api_gallery_interest_rate_models_curve_fitted_plot_01_ho_lee.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/curve_fitted/plot_01_ho_lee.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_01_ho_lee.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_01_ho_lee.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_01_ho_lee.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_