HodrickPrescottFilter#

class cultivars.spectral.filters.HodrickPrescottFilter(*, penalty=1600.0)[source]

Bases: object

The Hodrick-Prescott filter, with Hamilton’s critique on the result.

The trend is the minimizer of

\[\sum_{t=1}^{T} (y_t - \tau_t)^2 + \lambda \sum_{t=3}^{T} (\Delta^2 \tau_t)^2,\]

the order-2 case of the penalized smoother, whose two-sided gain is

\[G(\omega) = \frac{1}{1 + 4\lambda(1 - \cos\omega)^2},\]

a low-pass that lets a linear trend through untouched and is one half at the period the result reports as cutoff. The conventional penalties are 1600 quarterly, 100 annual and 14400 monthly (Ravn-Uhlig’s frequency-power rule gives 6.25 and 129600 instead), which is to say cutoff periods of 39.7, 19.8, 68.8, 9.8 and 119.2 observations; as \(\lambda \to \infty\) the trend becomes the least-squares line.

Variables:

_penalty – The smoothing weight \(\lambda\).

Parameters:

penalty (float) – The smoothing weight \(\lambda\), positive.

Raises:

SpecificationError – If the penalty is not positive.

Note

The result’s summary carries Hamilton’s (2018) critique in its notes rather than assuming the user knows it: the filter manufactures a smooth cycle from a random walk, its end-point values are revised as data arrive (the rows the result flags as provisional), and 1600 has no rationale outside quarterly data. Use it where comparability with the literature is the point; use HamiltonFilter where the cycle will be subject to inference. ButterworthFilter at order 2 and the matching cutoff period is the same filter stated by frequency rather than by weight.

See also

References

Hodrick, R. J., & Prescott, E. C. (1997). Postwar U.S. business cycles: An empirical investigation. Journal of Money, Credit and Banking, 29(1), 1-16.

Ravn, M. O., & Uhlig, H. (2002). On adjusting the Hodrick-Prescott filter for the frequency of observations. Review of Economics and Statistics, 84(2), 371-376.

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 = HodrickPrescottFilter().filter(y)
>>> res.trend.shape, round(res.cutoff, 1)
((200, 1), 39.7)

The gain at the cutoff period is one half – a cosine of that period comes out at half amplitude away from the edges – and a linear trend passes through as trend, leaving no cycle:

>>> t = np.arange(4000.0)
>>> wave = np.cos(2 * np.pi * t / res.cutoff)
>>> smoothed = HodrickPrescottFilter().filter(wave).trend[1000:3000, 0]
>>> round(float(smoothed.std() / wave[1000:3000].std()), 2)
0.5
>>> line = HodrickPrescottFilter().filter(2.0 + 0.5 * t[:100])
>>> bool(np.abs(line.cycle).max() < 1e-8)
True

Private attributes#