BeveridgeNelsonDecomposition#
- class cultivars.spectral.filters.BeveridgeNelsonDecomposition(result)[source]#
The Beveridge-Nelson decomposition of a fitted ARIMA(p, 1, q).
With \(\Delta y_t = \mu + \psi(L) e_t\) the permanent component is the level the long-horizon forecast settles on once the drift is netted out,
\[\tau_t = \lim_{H \to \infty}\bigl(E_t\, y_{t+H} - H\mu\bigr) = y_t + \sum_{k \ge 1}\bigl(E_t \Delta y_{t+k} - \mu\bigr),\]and the cycle \(c_t = y_t - \tau_t\) is minus the sum of forecastable future changes. The trend is a random walk with drift \(\mu\) and innovation \(\psi(1) e_t\), so the decomposition is the unique one in which the permanent component carries all the long-run variance. The sum is evaluated exactly in companion form (Morley 2002): with the state \(x_t\) of the demeaned differences and their innovations and companion matrix \(F\),
\[\sum_{k \ge 1} E_t \Delta y_{t+k} - \mu = e_1' F (I - F)^{-1} x_t,\]which is a linear function of the current state and needs no truncation. In closed form for the simplest cases: an ARIMA(1, 1, 0) with coefficient \(\phi\) has cycle \(-\phi (\Delta y_t - \mu) / (1 - \phi)\), an ARIMA(0, 1, 1) with coefficient \(\theta\) has cycle \(-\theta e_t\), and a pure random walk has none.
Not an estimator: takes the fitted model and reads the decomposition off its parameters and residuals, so every number is conditional on that ARIMA being right.
- Variables:
_result – The fitted ARIMA(p, 1, q) result.
- Parameters:
result (
ARMAResult) – A fittedARIMAwithd = 1, no seasonal part, no exogenous regressors and trend"n"or"c".- Raises:
SpecificationError – If the result is not fitted, or not an ARIMA(p, 1, q) of that form.
Note
The BN cycle is typically small, volatile, and – for an ARIMA(1, 1, 0) with \(\phi > 0\) – perfectly negatively correlated with growth, because it is a fixed multiple of the demeaned current change. Readers used to the smooth HP hump find this counterintuitive; it is the correct answer to “how far is the level from where it is heading”, which is a different question from “what is the smooth part of the level”. The decomposition is one-sided and exact, so no row is provisional, but it inherits the ARIMA’s estimation error in full and the cycle changes with the model order chosen.
See also
DecompositionFilterResult– the container returned.ARIMA– the model whose fitted result is the input.HamiltonFilter– the other forecast-based definition of the cycle, model-free.UnobservedComponents– the structural alternative, in which trend and cycle are separate stochastic components with their own variances.
References
Beveridge, S., & Nelson, C. R. (1981). A new approach to decomposition of economic time series into permanent and transitory components. Journal of Monetary Economics, 7(2), 151-174.
Morley, J. C. (2002). A state-space approach to calculating the Beveridge-Nelson decomposition. Economics Letters, 75(1), 123-127.
Example
>>> from cultivars.univariate.box_jenkins import ARIMA >>> rng = np.random.default_rng(0) >>> y = np.cumsum(0.2 + rng.standard_normal(300)) >>> res = BeveridgeNelsonDecomposition(ARIMA(y, order=(1, 1, 0)).fit()).compute() >>> res.trend.shape, res.offset ((299, 1), 1)
With genuine momentum in the differences the cycle is the closed form \(-\phi(\Delta y_t - \mu)/(1 - \phi)\), and much smaller than the HP cycle of the same series:
>>> e = rng.standard_normal(400) >>> z = np.zeros(400) >>> for t in range(1, 400): ... z[t] = 0.5 * z[t - 1] + e[t] >>> y = np.cumsum(0.2 + z) >>> fit = ARIMA(y, order=(1, 1, 0)).fit() >>> bn = BeveridgeNelsonDecomposition(fit).compute() >>> phi, mu = float(fit.ar_params[0]), float(fit.beta[0]) >>> bool(np.allclose(bn.cycle[:, 0], -phi * (np.diff(y) - mu) / (1 - phi))) True >>> hp = HodrickPrescottFilter().filter(y) >>> bool(bn.cycle.std() < 0.6 * hp.cycle.std()) True
Methods#
|
Decompose the levels. |