The Hodrick-Prescott Filter
The Hodrick-Prescott filter models a time series (\(y_t\)) as \[\begin{align} y_t = \tau_t + c_t \end{align}\] where \(\tau_t\) and \(c_t\) are trend and cyclical components respectively.
To decompose in this way, we solve the following minimization problem. \[\begin{align} \min_{\tau} \left( \sum_{t=1}^{T} (y_t - \tau_t)^2 + \lambda \sum_{t=2}^{T-1} (\Delta \tau_{t+1} - \Delta \tau_t)^2 \right) \end{align}\] \(\lambda\) is typically recommended as 100, 1600, and 14400 for annual, quarterly, and monthly frequency, respectively.
HP filter using statsmodels
statsmodels library provides a function for the HP filter. I make the one-sided HP filter which uses only the information available at time t, not the full sample. The following Python Jupyter notebook code shows the difference between the conventional and one-sided HP filter.
import statsmodels.api as sm import yfinance as yf import matplotlib.pyplot as plt plt.rcParams.update({'font.size': 14}) from IPython.core.interactiveshell import InteractiveShell InteractiveShell.ast_node_interactivity = "all" #------------------------------------ # monthly stock data: AAPL #------------------------------------ yts = yf.download('AAPL','2011-01-01','2022-12-31', interval='1mo')['Adj Close'] date = yts.index.to_numpy() y = yts.to_numpy() #==================================== # HP filter using statsmodels #==================================== lamb = 14400 tr = sm.tsa.filters.hpfilter(y, lamb)[1] cy = y - tr #==================================== # One-sided HP filter #==================================== def one_sided_HP_filter(y, lamb=1600): sn = 2; cy_os = y*0 tr_os = y*0; tr_os[:sn] = y[:sn]; for i in range(sn,len(y)): tr_os[i] = sm.tsa.filters.hpfilter(y[:i+1], lamb)[1][-1] cy_os[i] = y[i] - tr_os[i] return tr_os tr_os = one_sided_HP_filter(y, lamb) cy_os = y-tr_os #------------------------------------ # Graph #------------------------------------ plt.figure(figsize=(9,5)) plt.plot(date, y,linewidth=2, color='black', label='Data') plt.plot(date, tr,linewidth=4, color='dodgerblue', label='Trend') plt.plot(date, tr_os, linewidth=4, color='tomato', label='Trend-one-sided') plt.plot(date, cy, linewidth=4, color='dodgerblue', label='Cycle') plt.plot(date, cy_os, linewidth=4, color='tomato', label='Cycle-one-sided') plt.axhline(y=0, color='gray', linestyle='-') plt.legend() plt.show() | cs |
The outputs of two HP filters coincide at the end of the full sample, as shown in the following figure.
No comments:
Post a Comment