.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/time_series/volatility/plot_06_riskmetrics_ewma.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_time_series_volatility_plot_06_riskmetrics_ewma.py: RiskMetrics EWMA ================ In 1994 J.P. Morgan published RiskMetrics, a free methodology and data set for Value-at-Risk. Its volatility model was deliberately simple: an exponentially weighted moving average .. math:: \sigma_t^2 = \lambda\,\sigma_{t-1}^2 + (1 - \lambda)\,r_{t-1}^2, with one decay factor for every asset, :math:`\lambda = 0.94` for daily and :math:`0.97` for monthly data, chosen to minimize forecast errors across hundreds of series. It is GARCH(1,1) with :math:`\omega = 0` and :math:`\alpha + \beta = 1`: no estimation, no long-run level, and a flat term structure of forecasts. .. GENERATED FROM PYTHON SOURCE LINES 19-27 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from financialkit.constants import TRADING_DAYS_PER_YEAR from financialkit.time_series import EWMA, GARCH ann = TRADING_DAYS_PER_YEAR .. GENERATED FROM PYTHON SOURCE LINES 28-33 Weights on past squared returns ------------------------------- A 0.94 decay puts 6% weight on yesterday and has an effective memory of about 1/(1 - 0.94), roughly 17 days, against an equally weighted window's hard cut-off. .. GENERATED FROM PYTHON SOURCE LINES 33-43 .. code-block:: Python k = np.arange(1, 101) fig, ax = plt.subplots() for lam in (0.94, 0.97): ax.plot(k, (1 - lam) * lam ** (k - 1), label=rf"EWMA $\lambda$ = {lam}") ax.step(k, np.where(k <= 30, 1 / 30, 0.0), where="post", color="k", lw=1, label="30-day window") ax.set_xlabel("days ago") ax.set_ylabel("weight") ax.legend() .. image-sg:: /api/gallery/time_series/volatility/images/sphx_glr_plot_06_riskmetrics_ewma_001.png :alt: plot 06 riskmetrics ewma :srcset: /api/gallery/time_series/volatility/images/sphx_glr_plot_06_riskmetrics_ewma_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 44-49 Tracking a volatility shock --------------------------- Returns from a GARCH process with a crisis in the middle. EWMA follows the true conditional volatility closely without any fitting; the 30-day window lags it and drops abruptly 30 days after the shock. .. GENERATED FROM PYTHON SOURCE LINES 49-68 .. code-block:: Python g = GARCH(omega=0.15**2 / ann * 0.03, alpha=0.09, beta=0.88) path = g.simulate(1000, rng=1994) r = path.returns.copy() r[500:505] *= 6 # five days of crisis true_var = g.variance(r, v0=path.variance[0]) ewma = EWMA(0.94).variance(r, v0=path.variance[0]) window = np.convolve(r**2, np.ones(30) / 30)[: r.size] fig, ax = plt.subplots(figsize=(8, 3.5)) sl = slice(430, 650) t = np.arange(r.size)[sl] ax.plot(t, 100 * np.sqrt(ann * true_var[sl]), "k", lw=1.5, label="true (GARCH)") ax.plot(t, 100 * np.sqrt(ann * ewma[sl]), label="RiskMetrics EWMA") ax.plot(t, 100 * np.sqrt(ann * window[sl]), label="30-day window") ax.set_xlabel("day") ax.set_ylabel("volatility (% a year)") ax.legend() .. image-sg:: /api/gallery/time_series/volatility/images/sphx_glr_plot_06_riskmetrics_ewma_002.png :alt: plot 06 riskmetrics ewma :srcset: /api/gallery/time_series/volatility/images/sphx_glr_plot_06_riskmetrics_ewma_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 69-75 Estimating lambda ----------------- Maximum likelihood picks the decay that best fits this one series. RiskMetrics instead fixed 0.94 for every series, trading a little fit for simplicity and comparability across a whole portfolio. .. GENERATED FROM PYTHON SOURCE LINES 75-78 .. code-block:: Python print(f"maximum-likelihood lambda: {EWMA.fit(r).params['lam']:.3f}") plt.show() .. rst-class:: sphx-glr-script-out .. code-block:: none maximum-likelihood lambda: 0.896 .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.054 seconds) .. _sphx_glr_download_api_gallery_time_series_volatility_plot_06_riskmetrics_ewma.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/time_series/volatility/plot_06_riskmetrics_ewma.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_06_riskmetrics_ewma.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_06_riskmetrics_ewma.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_06_riskmetrics_ewma.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_