Skip to content

Commit a1a73a6

Browse files
authored
Merge pull request #263 from bashtage/fix-adf-short-time-series
BUG: Ensure ADF has sufficient obs
2 parents 8a3c5ff + 0a7805e commit a1a73a6

File tree

3 files changed

+23
-4
lines changed

3 files changed

+23
-4
lines changed

arch/tests/unitroot/test_unitroot.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,3 +433,13 @@ def test_mackinnoncrit_errors():
433433
cv_50 = mackinnoncrit(nobs=50)
434434
cv_inf = mackinnoncrit()
435435
assert np.all(cv_50 <= cv_inf)
436+
437+
438+
def test_adf_short_timeseries():
439+
# GH 262
440+
import numpy as np
441+
from arch.unitroot import ADF
442+
x = np.asarray([0., 0., 0., 0., 0., 0., 1., 1., 0., 0.])
443+
adf = ADF(x)
444+
assert_almost_equal(adf.stat, -2.236, decimal=3)
445+
assert adf.lags == 1

arch/unitroot/unitroot.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from numpy import (abs, arange, argwhere, array, ceil, cumsum, diff, empty,
88
float64, hstack, inf, int32, int64, interp, log, nan, ones,
99
pi, polyval, power, sort, sqrt, squeeze, sum)
10-
from numpy.linalg import inv, pinv, qr, solve
10+
from numpy.linalg import inv, pinv, qr, solve, matrix_rank
1111
from pandas import DataFrame
1212
from scipy.stats import norm
1313
from statsmodels.iolib.summary import Summary
@@ -208,12 +208,13 @@ def _autolag_ols(endog, exog, startlag, maxlag, method):
208208
qpy = q.T.dot(endog)
209209
ypy = endog.T.dot(endog)
210210
xpx = exog.T.dot(exog)
211+
effective_max_lag = min(maxlag, matrix_rank(xpx) - startlag)
211212

212-
sigma2 = empty(maxlag + 1)
213-
tstat = empty(maxlag + 1)
213+
sigma2 = empty(effective_max_lag + 1)
214+
tstat = empty(effective_max_lag + 1)
214215
nobs = float(endog.shape[0])
215216
tstat[0] = inf
216-
for i in range(startlag, startlag + maxlag + 1):
217+
for i in range(startlag, startlag + effective_max_lag + 1):
217218
b = solve(r[:i, :i], qpy[:i])
218219
sigma2[i - startlag] = (ypy - b.T.dot(xpx[:i, :i]).dot(b)) / nobs
219220
if method == 't-stat' and i > startlag:
@@ -256,8 +257,14 @@ def _df_select_lags(y, trend, max_lags, method, low_memory=False):
256257
If max_lags is None, the default value of 12 * (nobs/100)**(1/4) is used.
257258
"""
258259
nobs = y.shape[0]
260+
# This is the absolute maximum number of lags possible,
261+
# only needed to very short time series.
262+
max_max_lags = nobs // 2 - 1
263+
if trend != 'nc':
264+
max_max_lags -= len(trend)
259265
if max_lags is None:
260266
max_lags = int(ceil(12. * power(nobs / 100., 1 / 4.)))
267+
max_lags = max(min(max_lags, max_max_lags), 0)
261268
if low_memory:
262269
out = _autolag_ols_low_memory(y, max_lags, trend, method)
263270
return out

doc/source/changes/4.0.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
Changes since 4.0
22
=================
3+
- Fixed a bug in ``ADF`` when applying to very short time series
4+
(:issue:`262`).
35
- Added ability to set the ``random_state`` when initializing a bootstrap
46
(:issue:`259`).
57
- Added support for Fractionally Integrated GARCH (FIGARCH)

0 commit comments

Comments
 (0)