Repository: statsmodels/statsmodels

Issue:
augmented dickey fuller raises an error if maxlag=1
``` python
from statsmodels.tsa.arima_process import arma_generate_sample
import statsmodels.api as sm

y = arma_generate_sample([1, .95], [1], nsample=500, burnin=300)
sm.tsa.stattools.adfuller(y, maxlag=1)
```



Discussion:
I think maxlag doesn't take into account that there is a constant and possibly trend in front of exog

maxlag -> startlag+maxlag in call to _autolag seems to do it

```
        icbest, bestlag = _autolag(OLS, xdshort, fullRHS, startlag,
                startlag+maxlag, autolag)
```

there should have been other errors when trend order is larger, ? actual maxlag that was checked would have been too short, IISIC, if I see it correctly


Resolving patch:
diff --git a/statsmodels/tsa/stattools.py b/statsmodels/tsa/stattools.py
--- a/statsmodels/tsa/stattools.py
+++ b/statsmodels/tsa/stattools.py
@@ -18,7 +18,7 @@ def __str__(self):
         return self._str
 
 def _autolag(mod, endog, exog, startlag, maxlag, method, modargs=(),
-        fitargs=()):
+        fitargs=(), regresults=False):
     """
     Returns the results for the lag length that maximimizes the info criterion.
 
@@ -60,19 +60,19 @@ def _autolag(mod, endog, exog, startlag, maxlag, method, modargs=(),
 
     results = {}
     method = method.lower()
-    for lag in range(startlag,maxlag+1):
+    for lag in range(startlag, startlag+maxlag+1):
         mod_instance = mod(endog, exog[:,:lag], *modargs)
         results[lag] = mod_instance.fit()
 
     if method == "aic":
-        icbest, bestlag = max((v.aic,k) for k,v in results.iteritems())
+        icbest, bestlag = min((v.aic,k) for k,v in results.iteritems())
     elif method == "bic":
-        icbest, bestlag = max((v.bic,k) for k,v in results.iteritems())
+        icbest, bestlag = min((v.bic,k) for k,v in results.iteritems())
     elif method == "t-stat":
         lags = sorted(results.keys())[::-1]
 #        stop = stats.norm.ppf(.95)
         stop = 1.6448536269514722
-        for lag in range(maxlag,startlag-1,-1):
+        for lag in range(startlag + maxlag, startlag - 1, -1):
             icbest = np.abs(results[lag].tvalues[-1])
             if np.abs(icbest) >= stop:
                 bestlag = lag
@@ -80,7 +80,11 @@ def _autolag(mod, endog, exog, startlag, maxlag, method, modargs=(),
                 break
     else:
         raise ValueError("Information Criterion %s not understood.") % method
-    return icbest, bestlag
+
+    if not regresults:
+        return icbest, bestlag
+    else:
+        return icbest, bestlag, results
 
 #this needs to be converted to a class like HetGoldfeldQuandt, 3 different returns are a mess
 # See:
@@ -153,6 +157,8 @@ def adfuller(x, maxlag=None, regression="c", autolag='AIC',
     If the p-value is close to significant, then the critical values should be
     used to judge whether to accept or reject the null.
 
+    The autolag option and maxlag for it are described in Greene.
+
     Examples
     --------
     see example script
@@ -172,7 +178,12 @@ def adfuller(x, maxlag=None, regression="c", autolag='AIC',
     MacKinnon, J.G. 2010. "Critical Values for Cointegration Tests."  Queen's
     University, Dept of Economics, Working Papers.  Available at
     http://ideas.repec.org/p/qed/wpaper/1227.html
+
     '''
+
+    if regresults:
+        store = True
+
     trenddict = {None:'nc', 0:'c', 1:'ct', 2:'ctt'}
     if regression is None or isinstance(regression, int):
         regression = trenddict[regression]
@@ -201,11 +212,19 @@ def adfuller(x, maxlag=None, regression="c", autolag='AIC',
         else:
             fullRHS = xdall
         startlag = fullRHS.shape[1] - xdall.shape[1] + 1 # 1 for level
-
-        #search for lag length with highest information criteria
+        #search for lag length with smallest information criteria
         #Note: use the same number of observations to have comparable IC
-        icbest, bestlag = _autolag(OLS, xdshort, fullRHS, startlag,
-                maxlag, autolag)
+        #aic and bic: smaller is better
+
+        if not regresults:
+            icbest, bestlag = _autolag(OLS, xdshort, fullRHS, startlag,
+                                       maxlag, autolag)
+        else:
+            icbest, bestlag, alres = _autolag(OLS, xdshort, fullRHS, startlag,
+                                        maxlag, autolag, regresults=regresults)
+            resstore.autolag_results = alres
+
+        bestlag -= startlag  #convert to lag not column index
 
         #rerun ols with best autolag
         xdall = lagmat(xdiff[:,None], bestlag, trim='both', original='in')
@@ -220,6 +239,7 @@ def adfuller(x, maxlag=None, regression="c", autolag='AIC',
         resols = OLS(xdshort, add_trend(xdall[:,:usedlag+1], regression)).fit()
     else:
         resols = OLS(xdshort, xdall[:,:usedlag+1]).fit()
+
     adfstat = resols.tvalues[0]
 #    adfstat = (resols.params[0]-1.0)/resols.bse[0]
     # the "asymptotically correct" z statistic is obtained as
@@ -234,12 +254,13 @@ def adfuller(x, maxlag=None, regression="c", autolag='AIC',
             "10%" : critvalues[2]}
     if store:
         resstore.resols = resols
+        resstore.maxlag = maxlag
         resstore.usedlag = usedlag
         resstore.adfstat = adfstat
         resstore.critvalues = critvalues
         resstore.nobs = nobs
-        resstore.H0 = "The coefficient on the lagged level equals 1"
-        resstore.HA = "The coefficient on the lagged level < 1"
+        resstore.H0 = "The coefficient on the lagged level equals 1 - unit root"
+        resstore.HA = "The coefficient on the lagged level < 1 - stationary"
         resstore.icbest = icbest
         return adfstat, pvalue, critvalues, resstore
     else:


Test patch:
diff --git a/statsmodels/tsa/tests/test_adfuller_lag.py b/statsmodels/tsa/tests/test_adfuller_lag.py
new file mode 100644
--- /dev/null
+++ b/statsmodels/tsa/tests/test_adfuller_lag.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+"""Test for autolag of adfuller, unitroot_adf
+
+Created on Wed May 30 21:39:46 2012
+Author: Josef Perktold
+"""
+
+import numpy as np
+from numpy.testing import assert_equal, assert_almost_equal
+import statsmodels.tsa.stattools as tsast
+from statsmodels.datasets import macrodata
+
+def test_adf_autolag():
+    #see issue #246
+    #this is mostly a unit test
+    d2 = macrodata.load().data
+
+    for k_trend, tr in enumerate(['nc', 'c', 'ct', 'ctt']):
+        #[None:'nc', 0:'c', 1:'ct', 2:'ctt']
+        x = np.log(d2['realgdp'])
+        xd = np.diff(x)
+
+        #check exog
+        adf3 = tsast.adfuller(x, maxlag=None, autolag='aic',
+                              regression=tr, store=True, regresults=True)
+        st2 = adf3[-1]
+
+        assert_equal(len(st2.autolag_results), 14 + 1)  #+1 for lagged level
+        for l, res in sorted(st2.autolag_results.iteritems())[:5]:
+            lag = l-k_trend
+            #assert correct design matrices in _autolag
+            assert_equal(res.model.exog[-10:,k_trend], x[-11:-1])
+            assert_equal(res.model.exog[-1,k_trend+1:], xd[-lag:-1][::-1])
+            #min-ic lag of dfgls in Stata is also 2, or 9 for maic with notrend
+            assert_equal(st2.usedlag, 2)
+
+        #same result with lag fixed at usedlag of autolag
+        adf2 = tsast.adfuller(x, maxlag=2, autolag=None, regression=tr)
+        assert_almost_equal(adf3[:2], adf2[:2], decimal=12)
+
+
+    tr = 'c'
+    #check maxlag with autolag
+    adf3 = tsast.adfuller(x, maxlag=5, autolag='aic',
+                          regression=tr, store=True, regresults=True)
+    assert_equal(len(adf3[-1].autolag_results), 5 + 1)
+    adf3 = tsast.adfuller(x, maxlag=0, autolag='aic',
+                          regression=tr, store=True, regresults=True)
+    assert_equal(len(adf3[-1].autolag_results), 0 + 1)