Repository: statsmodels/statsmodels

Issue:
BUG coint_johansen with k_ar_diff = 0
#### Describe the bug

The coint_johansen module specifies:
k_ar_diff (int, nonnegative) – Number of lagged differences in the model.
So k_ar_diff = 0 is a possible value and means that the VECM model looks like 
Delta y_t = \Pi * y_t + noise.
However coint_johansen seems it doesn't work if k_ar_diff = 0. For example, the following code gives an error:

import pandas as pd
import numpy as np
from statsmodels.tsa.vector_ar.vecm import coint_johansen

Xreturns = np.random.normal(0, 1, 1000) 
X = pd.Series(np.cumsum( Xreturns))
noise1 = np.random.normal(0, 1, 1000)
noise2 = np.random.normal(0, 1, 1000)
Y = X + 5 + noise1
data=pd.concat([X, Y], axis=1)
result = coint_johansen(data, det_order = -1, k_ar_diff = 0)

ValueError: shapes (2,0) and (999,2) not aligned: 0 (dim 1) != 999 (dim 0)

It also gives error if det_order = 0 or det_order = 1.

#### Output of ``import statsmodels.api as sm; sm.show_versions()``

INSTALLED VERSIONS
------------------
Python: 3.6.7.final.0
OS: Linux 4.15.0-48-generic #51-Ubuntu SMP Wed Apr 3 08:28:49 UTC 2019 x86_64
byteorder: little
LC_ALL: None
LANG: es_AR.UTF-8

Statsmodels
===========

Installed: 0.9.0 (/home/patricia/anaconda3/lib/python3.6/site-packages/statsmodels)

Required Dependencies
=====================

cython: 0.27.3 (/home/patricia/anaconda3/lib/python3.6/site-packages/Cython)
numpy: 1.14.3 (/home/patricia/anaconda3/lib/python3.6/site-packages/numpy)
scipy: 0.19.1 (/home/patricia/anaconda3/lib/python3.6/site-packages/scipy)
pandas: 0.23.4 (/home/patricia/anaconda3/lib/python3.6/site-packages/pandas)
    dateutil: 2.6.1 (/home/patricia/anaconda3/lib/python3.6/site-packages/dateutil)
patsy: 0.5.0 (/home/patricia/anaconda3/lib/python3.6/site-packages/patsy)

Optional Dependencies
=====================

matplotlib: 2.1.2 (/home/patricia/anaconda3/lib/python3.6/site-packages/matplotlib)
    backend: module://ipykernel.pylab.backend_inline 
cvxopt: Not installed
joblib: Not installed

Developer Tools
================

IPython: 6.2.1 (/home/patricia/anaconda3/lib/python3.6/site-packages/IPython)
    jinja2: 2.10 (/home/patricia/anaconda3/lib/python3.6/site-packages/jinja2)
sphinx: 1.6.6 (/home/patricia/anaconda3/lib/python3.6/site-packages/sphinx)
    pygments: 2.3.1 (/home/patricia/anaconda3/lib/python3.6/site-packages/pygments)
nose: 1.3.7 (/home/patricia/anaconda3/lib/python3.6/site-packages/nose)
pytest: 3.3.2 (/home/patricia/anaconda3/lib/python3.6/site-packages)
virtualenv: Not installed


Discussion:
Hi:
Lines 644 and forward in vecm module are:
lx = endog[:-k_ar_diff]
lx = lx[1:]
dx = detrend(lx, f)
rkt = resid(dx, z)  # level on lagged diffs
So, if k_ar_diff is iqual to zero, then lx is an empty vector and it raises an error.




Resolving patch:
diff --git a/statsmodels/tsa/vector_ar/vecm.py b/statsmodels/tsa/vector_ar/vecm.py
--- a/statsmodels/tsa/vector_ar/vecm.py
+++ b/statsmodels/tsa/vector_ar/vecm.py
@@ -623,6 +623,7 @@ def resid(y, x):
         r = y - np.dot(x, np.dot(np.linalg.pinv(x), y))
         return r
 
+    endog = np.asarray(endog)
     nobs, neqs = endog.shape
 
     # why this?  f is detrend transformed series, det_order is detrend data
@@ -641,11 +642,14 @@ def resid(y, x):
 
     dx = detrend(dx, f)
     r0t = resid(dx, z)
-    lx = endog[:-k_ar_diff]
+    # GH 5731, [:-0] does not work, need [:t-0]
+    lx = endog[:(endog.shape[0]-k_ar_diff)]
     lx = lx[1:]
     dx = detrend(lx, f)
     rkt = resid(dx, z)  # level on lagged diffs
+    # Level covariance after filtering k_ar_diff
     skk = np.dot(rkt.T, rkt) / rkt.shape[0]
+    # Covariacne between filtered and unfiltered
     sk0 = np.dot(rkt.T, r0t) / rkt.shape[0]
     s00 = np.dot(r0t.T, r0t) / r0t.shape[0]
     sig = np.dot(sk0, np.dot(inv(s00), sk0.T))


Test patch:
diff --git a/statsmodels/tsa/vector_ar/tests/test_coint.py b/statsmodels/tsa/vector_ar/tests/test_coint.py
--- a/statsmodels/tsa/vector_ar/tests/test_coint.py
+++ b/statsmodels/tsa/vector_ar/tests/test_coint.py
@@ -10,6 +10,8 @@
 
 import numpy as np
 from numpy.testing import assert_almost_equal, assert_equal
+import pandas as pd
+import pytest
 
 from statsmodels.tsa.vector_ar.vecm import coint_johansen
 from statsmodels.tools.sm_exceptions import HypothesisTestWarning
@@ -120,8 +122,32 @@ def setup_class(cls):
             cls.res = coint_johansen(dta, 2, 5)
         cls.nobs_r = 173 - 1 - 5
 
-        #Note: critical values not available if trend>1
-        cls.res1_m = np.array([270.1887263915158,  171.6870096307863,  107.8613367358704,  70.82424032233558,  44.62551818267534,  25.74352073857572,  14.17882426926978,  4.288656185006764,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0])
+        # Note: critical values not available if trend>1
+        cls.res1_m = np.array([270.1887263915158, 171.6870096307863,
+                               107.8613367358704, 70.82424032233558,
+                               44.62551818267534, 25.74352073857572,
+                               14.17882426926978, 4.288656185006764,
+                               0, 0, 0, 0, 0, 0, 0, 0, 0,
+                               0, 0, 0, 0, 0, 0, 0, 0, 0,
+                               0, 0, 0, 0, 0, 0])
         cls.res1_m[cls.res1_m == 0] = np.nan
-        cls.res2_m = np.array([98.50171676072955,  63.82567289491584,  37.03709641353485,  26.19872213966024,  18.88199744409963,  11.56469646930594,  9.890168084263012,  4.288656185006764,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0])
+        cls.res2_m = np.array([98.50171676072955, 63.82567289491584,
+                               37.03709641353485, 26.19872213966024,
+                               18.88199744409963, 11.56469646930594,
+                               9.890168084263012, 4.288656185006764,
+                               0, 0, 0, 0, 0, 0, 0, 0,
+                               0, 0, 0, 0, 0, 0, 0, 0,
+                               0, 0, 0, 0, 0, 0, 0, 0])
         cls.res2_m[cls.res2_m == 0] = np.nan
+
+
+@pytest.mark.smoke
+def test_coint_johansen_0lag(reset_randomstate):
+    # GH 5731
+    x_diff = np.random.normal(0, 1, 1000)
+    x = pd.Series(np.cumsum(x_diff))
+    e1 = np.random.normal(0, 1, 1000)
+    y = x + 5 + e1
+    data = pd.concat([x, y], axis=1)
+    result = coint_johansen(data, det_order=-1, k_ar_diff=0)
+    assert result.eig.shape == (2,)