cultivars.diagnostics.long_memory#

Semiparametric long memory: the differencing parameter without a short-run model.

A fractionally integrated process \((1 - L)^d y_t = u_t\) with \(u_t\) short-memory has a spectrum that behaves near the origin as

\[f(\lambda) \sim c\,\lambda^{-2d}, \qquad \lambda \to 0^+,\]

whatever the short-run structure of \(u_t\), and the three estimators here read \(d\) off that behaviour at the \(m\) lowest Fourier frequencies alone. An ARFIMA fit commits to an ARMA short-run model and estimates \(d\) jointly with it; when the ARMA order is wrong, \(d\) absorbs the error. These need no short-run model, and their bandwidth \(m\) is the only choice, trading bias from the short-run spectrum, which grows with \(m\), against variance, which shrinks with it. Geweke-Porter-Hudak is the log-periodogram regression, the oldest and least efficient, with standard error \(\pi / \sqrt{24 m}\); local Whittle is Robinson’s Gaussian semiparametric estimator, standard error \(1 / (2\sqrt{m})\) and valid for \(d < 3/4\); exact local Whittle fractionally differences the series inside the objective and is valid for any \(d\), which makes it the one to run when the answer might be “this is a unit root”. The unit-root question is exactly where they earn their place: \(d = 1\) and \(d = 0.7\) reject the same ADF null and mean different things, the first a permanent shock and the second a shock that decays, however slowly.

Two commitments shape the surface. First, a record is an estimate that carries its test, not a test that happens to expose an estimate: every producer returns a LongMemoryEstimate with d and se first, and the natural nulls, \(d = 0\) for no long memory, \(d = 1/2\) for the stationarity boundary, \(d = 1\) for a unit root, are one LongMemoryEstimate.test() away without re-estimating, the summary table showing all three at once. Second, the record says what its standard error is worth. The asymptotic standard error is a function of the bandwidth alone and does not see the short-run dynamics the estimator ignored, so the record carries m, the table names it, and the local Whittle record warns when the estimate has left the range its limit theory covers rather than printing a p-value from a law that no longer holds.

Layout. LongMemoryEstimate is the record, a HypothesisTest with test(), confidence_interval(), and is_stationary; gph(), local_whittle(), and exact_local_whittle() are the producers, which validate, estimate, and assemble the record through one shared constructor. The numerics live in _core: _validate_semiparametric checks the series and applies the bandwidth rule, _gph runs the log-periodogram regression, local_whittle_d minimizes the concentrated Whittle objective and is shared with the ARFIMA model’s starting value, _exact_local_whittle applies the fractional difference and mean correction inside that objective, and the bandwidth exponents, search bounds, and minimum sample length are the module’s named defaults.

References

Geweke, J., & Porter-Hudak, S. (1983). The estimation and application of long memory time series models. Journal of Time Series Analysis, 4(4), 221-238.

Robinson, P. M. (1995). Gaussian semiparametric estimation of long range dependence. Annals of Statistics, 23(5), 1630-1661.

Shimotsu, K., & Phillips, P. C. B. (2005). Exact local Whittle estimation of fractional integration. Annals of Statistics, 33(4), 1890-1933.

Shimotsu, K. (2010). Exact local Whittle estimation of fractional integration with unknown mean and time trend. Econometric Theory, 26(2), 501-540.

Baillie, R. T. (1996). Long memory processes and fractional integration in econometrics. Journal of Econometrics, 73(1), 5-59.

Example

A fractionally integrated series with \(d = 0.3\) is stationary with long memory: every estimator puts \(d\) between zero and one half, and the Whittle pair does so with the smaller standard error:

>>> import numpy as np
>>> from cultivars.engine._core._transforms import _fractional_difference_weights
>>> rng = np.random.default_rng(0)
>>> weights = _fractional_difference_weights(-0.3, 1000)
>>> y = np.convolve(rng.standard_normal(1000), weights)[:1000]
>>> for estimate in (gph(y), local_whittle(y), exact_local_whittle(y)):
...     print(f"{estimate.method:<20} d={estimate.d:.2f}  se={estimate.se:.3f}")
gph                  d=0.36  se=0.137
local_whittle        d=0.31  se=0.053
exact_local_whittle  d=0.32  se=0.053
>>> estimate.reject(), estimate.test(0.5).reject(), estimate.is_stationary
(True, True, True)

Classes#

LongMemoryEstimate

A semiparametric estimate of the fractional differencing parameter, with a test.

Functions#

exact_local_whittle(endog, *[, f_bandwidth, ...])

Shimotsu-Phillips exact local Whittle estimate of \(d\), valid for any \(d\).

gph(endog, *[, f_bandwidth, exponent])

Geweke-Porter-Hudak log-periodogram estimate of \(d\).

local_whittle(endog, *[, f_bandwidth, exponent])

Robinson's (1995) local Whittle estimate of \(d\).