HamiltonFilter#
- class cultivars.spectral.filters.HamiltonFilter(*, horizon=8, lags=4)[source]
Bases:
objectHamilton’s (2018) regression filter.
Regress the level \(h\) steps ahead on a constant and its own \(p\) most recent values,
\[y_{t+h} = \beta_0 + \beta_1 y_t + \beta_2 y_{t-1} + \cdots + \beta_p y_{t-p+1} + v_{t+h},\]by ordinary least squares over the whole sample; the fitted value is the trend at \(t + h\) – what the level’s own recent history could predict that far ahead – and the residual \(\hat v_{t+h}\) is the cycle. Both begin at observation \(h + p - 1\), so the result is that many rows shorter than the input and reports the shortfall as
offset. The defaults are the paper’s quarterly \(h = 8, p = 4\); monthly data want \(h = 24, p = 12\), and in either case \(h\) should span the two years over which a business-cycle downturn resolves.The filter exists as the alternative to
HodrickPrescottFilterthat Hamilton’s critique calls for. The regression is valid for I(1) and I(2) series alike – for a random walk the population coefficients are \(\beta_1 = 1\) and the rest zero, so the cycle is the \(h\)-step forecast error \(y_{t+h} - y_t\) – and the cycle is stationary by construction for any process whose \(d\)-th difference is stationary with \(d \le p\). No future observations enter the regressors, so the filter does not manufacture dynamics from the two-sided smoothing that HP does.- Variables:
_horizon – The forecast horizon \(h\).
_lags – The number of own-lag regressors \(p\).
- Parameters:
- Raises:
SpecificationError – If either is not an integer of at least 1.
Note
“One-sided” describes the regressors, not the estimate. The coefficients are estimated on the full sample, so extending the data re-estimates \(\beta\) and changes every fitted value a little; the result’s
provisionalflags are allFalsebecause no row depends on observations after \(t + h\) through the design, which is the revision HP suffers from. For a strictly real-time cycle fix the coefficients at their random walk values and take \(y_{t+h} - y_t\) directly.For a random walk with innovation variance \(\sigma^2\) the cycle’s standard deviation is about \(\sigma\sqrt{h}\), which is what an \(h\)-step forecast error is; this is larger than the HP cycle’s, and correctly so.
See also
DecompositionFilterResult– the container returned.HodrickPrescottFilter– the filter this one is the proposed replacement for.BeveridgeNelsonDecomposition– the other definition in which the cycle is a forecast object.
References
Hamilton, J. D. (2018). Why you should never use the Hodrick-Prescott filter. Review of Economics and Statistics, 100(5), 831-843.
Example
>>> rng = np.random.default_rng(0) >>> y = np.cumsum(rng.standard_normal(200)) >>> res = HamiltonFilter().filter(y) >>> res.trend.shape, res.offset ((189, 1), 11)
The result is the OLS regression it claims to be, and on a random walk the cycle has the scale of an eight-step forecast error:
>>> design = np.column_stack([np.ones(189), y[3:192], y[2:191], y[1:190], y[0:189]]) >>> beta = np.linalg.lstsq(design, y[11:], rcond=None)[0] >>> bool(np.allclose(design @ beta, res.trend[:, 0])) True >>> bool(abs(res.cycle.std() / np.sqrt(8) - 1.0) < 0.1) True