.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/portfolio/covariance/plot_01_single_index.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_portfolio_covariance_plot_01_single_index.py: Sharpe's single-index model =========================== Markowitz's method needed every pairwise covariance, :math:`d(d+1)/2` numbers, which no 1960s computer (or analyst) could supply for hundreds of stocks. William Sharpe (1963) assumed that stocks move together only through a common market index, :math:`R_i = \alpha_i + \beta_i R_m + \varepsilon_i`, so the covariance is :math:`\sigma_m^2\beta\beta' + \mathrm{diag}(\sigma_{\varepsilon}^2)`, with :math:`3d + 1` parameters. The structure also filters noise: with short histories, the single-index estimate is closer to the truth than the sample covariance. .. GENERATED FROM PYTHON SOURCE LINES 17-35 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from financialkit.portfolio import sample_covariance, single_index_covariance rng = np.random.default_rng(5) d, n = 30, 36 beta = rng.uniform(0.5, 1.5, d) resid = rng.uniform(0.04, 0.10, d) sig_m = 0.045 true = sig_m**2 * np.outer(beta, beta) + np.diag(resid**2) def simulate(n_months): m = sig_m * rng.standard_normal(n_months) return np.outer(m, beta) + resid * rng.standard_normal((n_months, d)), m .. GENERATED FROM PYTHON SOURCE LINES 36-38 Fitted betas from three years of monthly data --------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 38-49 .. code-block:: Python X, m = simulate(n) si = single_index_covariance(X, m) fig, ax = plt.subplots(figsize=(5, 4)) ax.plot(beta, si.betas, "o") ax.plot([0.4, 1.6], [0.4, 1.6], "k:") ax.set_xlabel("true beta") ax.set_ylabel("estimated beta") fig.tight_layout() print(f"parameters: sample {sample_covariance(X).n_params}, single index {si.n_params}") .. image-sg:: /api/gallery/portfolio/covariance/images/sphx_glr_plot_01_single_index_001.png :alt: plot 01 single index :srcset: /api/gallery/portfolio/covariance/images/sphx_glr_plot_01_single_index_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none parameters: sample 465, single index 91 .. GENERATED FROM PYTHON SOURCE LINES 50-52 Estimation error against the length of history ---------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 52-71 .. code-block:: Python months = [24, 36, 60, 120, 240] err_s, err_si = [], [] for T in months: es, esi = [], [] for _ in range(30): X, m = simulate(T) es.append(np.linalg.norm(sample_covariance(X).cov - true)) esi.append(np.linalg.norm(single_index_covariance(X, m).cov - true)) err_s.append(np.mean(es)) err_si.append(np.mean(esi)) fig, ax = plt.subplots(figsize=(7, 3.5)) ax.loglog(months, err_s, "o-", label="sample covariance") ax.loglog(months, err_si, "s-", label="single-index model") ax.set_xlabel("months of data") ax.set_ylabel("Frobenius error") ax.legend() fig.tight_layout() plt.show() .. image-sg:: /api/gallery/portfolio/covariance/images/sphx_glr_plot_01_single_index_002.png :alt: plot 01 single index :srcset: /api/gallery/portfolio/covariance/images/sphx_glr_plot_01_single_index_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.108 seconds) .. _sphx_glr_download_api_gallery_portfolio_covariance_plot_01_single_index.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/portfolio/covariance/plot_01_single_index.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_01_single_index.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_01_single_index.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_01_single_index.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_