Repository: statsmodels/statsmodels

Issue:
Fit ARIMA Error: exog contains inf or nans 
#### Describe the bug

I am getting `statsmodels.tools.sm_exceptions.MissingDataError: exog contains inf or nans` with `d=0`. This does not happen when say `d=1`.

Error log:
```
/my_path/test.py
/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/statsmodels/tsa/innovations/arma_innovations.py:83: RuntimeWarning: invalid value encountered in sqrt
  v05 = v**0.5
Traceback (most recent call last):
  File "/my_path/test.py", line 19, in <module>
    cov_type="none")
  File "/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/statsmodels/tsa/arima/model.py", line 307, in fit
    **gls_kwargs)
  File "/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/statsmodels/tsa/arima/estimators/gls.py", line 251, in gls
    mod_gls = OLS(u, x)
  File "/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/statsmodels/regression/linear_model.py", line 858, in __init__
    hasconst=hasconst, **kwargs)
  File "/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/statsmodels/regression/linear_model.py", line 701, in __init__
    weights=weights, hasconst=hasconst, **kwargs)
  File "/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/statsmodels/regression/linear_model.py", line 189, in __init__
    super(RegressionModel, self).__init__(endog, exog, **kwargs)
  File "/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/statsmodels/base/model.py", line 236, in __init__
    super(LikelihoodModel, self).__init__(endog, exog, **kwargs)
  File "/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/statsmodels/base/model.py", line 77, in __init__
    **kwargs)
  File "/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/statsmodels/base/model.py", line 100, in _handle_data
    data = handle_data(endog, exog, missing, hasconst, **kwargs)
  File "/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/statsmodels/base/data.py", line 667, in handle_data
    **kwargs)
  File "/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/statsmodels/base/data.py", line 83, in __init__
    self._handle_constant(hasconst)
  File "/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/statsmodels/base/data.py", line 129, in _handle_constant
    raise MissingDataError('exog contains inf or nans')
statsmodels.tools.sm_exceptions.MissingDataError: exog contains inf or nans
```

#### Code Sample, a copy-pastable example if possible


```python
endog = pd.read_csv("my_data_sample2.csv", index_col=0, parse_dates=True)
endog = endog.asfreq(pd.infer_freq(endog.index))

mod = sm.tsa.arima.ARIMA(
                endog,
                order=(18, 0, 39),
                enforce_stationarity=False,
                enforce_invertibility=False,
            )
res = mod.fit(
                method="hannan_rissanen",
                low_memory=True,
                cov_type="none")
```

[Edit] link to my data sample: [my_data_sample2.csv](https://drive.google.com/file/d/185CkaiFpeKsy978PnawqoclwVS3tIOzQ/view?usp=sharing)


#### Expected Output

No `exog contains inf or nans` error

#### Output of ``import statsmodels.api as sm; sm.show_versions()``

```
INSTALLED VERSIONS
------------------
Python: 3.7.4.final.0
OS: Linux 5.3.0-40-generic #32~18.04.1-Ubuntu SMP Mon Feb 3 14:05:59 UTC 2020 x86_64
byteorder: little
LC_ALL: None
LANG: en_CA.UTF-8

statsmodels
===========

Installed: 0.11.0dev0+628.g17f7c3481 (/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/statsmodels)

Required Dependencies
=====================

cython: 0.29.13 (/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/Cython)
numpy: 1.17.0 (/my_path3/.local/lib/python3.7/site-packages/numpy)
scipy: 1.3.1 (/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/scipy)
pandas: 0.25.3 (/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/pandas)
    dateutil: 2.8.1 (/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/dateutil)
patsy: 0.5.1 (/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/patsy)

Optional Dependencies
=====================

matplotlib: 3.1.1 (/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/matplotlib)
    backend: Qt5Agg 
cvxopt: Not installed
joblib: 0.14.0 (/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/joblib)

Developer Tools
================

IPython: 7.9.0 (/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/IPython)
    jinja2: 2.10.3 (/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/jinja2)
sphinx: Not installed
    pygments: 2.4.2 (/my_path2/anaconda3/envs/vision/lib/python3.7/site-packages/pygments)
pytest: Not installed
virtualenv: Not installed
```


Discussion:
Thanks for the report!
Thanks again. This is a bug.

By default, `sm.tsa.arima.ARIMA` includes a constant for stationary models (`d=0`) but does not include a constant for integrated models (`d=1`).

When there is a constant (or some other regression effect) and you're not using `method='statespace'`, then GLS with ARMA errors is used. However, it can't handle ARIMA errors, and it is possible with the Hannan-Rissanen method that we get estimates that imply a non-stationary (i.e. ARIMA) process.

So I think what we need to do is check for parameters for stationarity in GLS and raise an exception if that's not satisfied.
Just wanted to add a bit of context to this situation:
when I run `arima` I am seeing the following warning ```/my_path/envs/conda-default/lib/python3.7/site-packages/statsmodels/tsa/arima/model.py:340: UserWarning: Provided `endog` series has been differenced to eliminate integration prior to parameter estimation by method "hannan_rissanen".' estimation by method "%s".' % method)```.
Because I run grid search with multiprocessing, I decided to differentiate the data myself. Isn't that what `arima`  does under the hood?

Also, here is an example where I do differentiate the data myself but still get the same error:
```
endog = pd.read_csv("my_data_sample2.csv", index_col=0, parse_dates=True)
endog = endog.asfreq(pd.infer_freq(endog.index))
endog = endog.diff().dropna()

mod = sm.tsa.arima.ARIMA(
    endog,
    order=(2, 0, 2),
    enforce_stationarity=False,
    enforce_invertibility=False,
)
res = mod.fit(
    method="hannan_rissanen",
    low_memory=True,
    cov_type="none")
```
The issue is that the parameter estimates for the *differenced* data are coming up as non-stationary. That's why differencing the data yourself doesn't improve things have an effect.
Any update on this. How do we use this if we encounter the issue again?

Resolving patch:
diff --git a/statsmodels/tsa/arima/estimators/gls.py b/statsmodels/tsa/arima/estimators/gls.py
--- a/statsmodels/tsa/arima/estimators/gls.py
+++ b/statsmodels/tsa/arima/estimators/gls.py
@@ -240,6 +240,16 @@ def gls(endog, exog=None, order=(0, 0, 0), seasonal_order=(0, 0, 0, 0),
         # argument applies a Prais-Winsten-type normalization to the first few
         # observations to ensure homoskedasticity). Brockwell and Davis
         # mention that they also take this approach in practice.
+
+        # GH-6540: AR must be stationary
+
+        if not p_arma.is_stationary:
+            raise ValueError(
+                "Roots of the autoregressive parameters indicate that data is"
+                "non-stationary. GLS cannot be used with non-stationary "
+                "parameters. You should consider differencing the model data"
+                "or applying a nonlinear transformation (e.g., natural log)."
+            )
         tmp, _ = arma_innovations.arma_innovations(
             augmented, ar_params=ar_params, ma_params=ma_params,
             normalize=True)
diff --git a/statsmodels/tsa/arima_process.py b/statsmodels/tsa/arima_process.py
--- a/statsmodels/tsa/arima_process.py
+++ b/statsmodels/tsa/arima_process.py
@@ -30,6 +30,12 @@
            'lpol2index', 'index2lpol']
 
 
+NONSTATIONARY_ERROR = """\
+The model's autoregressive parameters (ar) indicate that the process
+ is non-stationary. arma_acovf can only be used with stationary processes.
+"""
+
+
 # Remove after 0.11
 @deprecate_kwarg('sigma', 'scale')
 def arma_generate_sample(ar, ma, nsample, scale=1, distrvs=None,
@@ -107,7 +113,7 @@ def arma_generate_sample(ar, ma, nsample, scale=1, distrvs=None,
 
 def arma_acovf(ar, ma, nobs=10, sigma2=1, dtype=None):
     """
-    Theoretical autocovariance function of ARMA process.
+    Theoretical autocovariances of stationary ARMA processes
 
     Parameters
     ----------
@@ -150,6 +156,8 @@ def arma_acovf(ar, ma, nobs=10, sigma2=1, dtype=None):
         out = np.zeros(nobs, dtype=dtype)
         out[0] = sigma2
         return out
+    elif p > 0 and np.max(np.abs(np.roots(ar))) >= 1:
+        raise ValueError(NONSTATIONARY_ERROR)
 
     # Get the moving average representation coefficients that we need
     ma_coeffs = arma2ma(ar, ma, lags=m)
@@ -166,7 +174,10 @@ def arma_acovf(ar, ma, nobs=10, sigma2=1, dtype=None):
         A[k, 1:m - k] += tmp_ar[(k + 1):m]
         b[k] = sigma2 * np.dot(ma[k:q + 1], ma_coeffs[:max((q + 1 - k), 0)])
     acovf = np.zeros(max(nobs, m), dtype=dtype)
-    acovf[:m] = np.linalg.solve(A, b)[:, 0]
+    try:
+        acovf[:m] = np.linalg.solve(A, b)[:, 0]
+    except np.linalg.LinAlgError:
+        raise ValueError(NONSTATIONARY_ERROR)
 
     # Iteratively apply (BD, eq. 3.3.9) to solve for remaining autocovariances
     if nobs > m:
diff --git a/statsmodels/tsa/innovations/arma_innovations.py b/statsmodels/tsa/innovations/arma_innovations.py
--- a/statsmodels/tsa/innovations/arma_innovations.py
+++ b/statsmodels/tsa/innovations/arma_innovations.py
@@ -6,6 +6,11 @@
 from scipy.linalg.blas import find_best_blas_type
 from . import _arma_innovations
 
+NON_STATIONARY_ERROR = """\
+The model's autoregressive parameters (ar_params) indicate that the process
+ is non-stationary. The innovations algorithm cannot be used.
+"""
+
 
 def arma_innovations(endog, ar_params=None, ma_params=None, sigma2=1,
                      normalize=False, prefix=None):
@@ -79,16 +84,21 @@ def arma_innovations(endog, ar_params=None, ma_params=None, sigma2=1,
     theta, v = arma_innovations_algo_fast(nobs, ar_params, ma_params,
                                           acovf, acovf2)
     v = np.array(v)
-    if normalize:
-        v05 = v**0.5
+    if (np.any(v < 0) or
+            not np.isfinite(theta).all() or
+            not np.isfinite(v).all()):
+        # This is defensive code that is hard to hit
+        raise ValueError(NON_STATIONARY_ERROR)
 
     # Run the innovations filter across each series
     u = []
     for i in range(k_endog):
         u_i = np.array(arma_innovations_filter(endog[:, i], ar_params,
                                                ma_params, theta))
-        u.append(u_i / v05 if normalize else u_i)
+        u.append(u_i)
     u = np.vstack(u).T
+    if normalize:
+        u /= v[:, None]**0.5
 
     # Post-processing
     if squeezed:


Test patch:
diff --git a/statsmodels/tsa/arima/tests/test_model.py b/statsmodels/tsa/arima/tests/test_model.py
--- a/statsmodels/tsa/arima/tests/test_model.py
+++ b/statsmodels/tsa/arima/tests/test_model.py
@@ -11,8 +11,11 @@
 """
 from statsmodels.compat.platform import PLATFORM_WIN32
 
+import io
+
 import numpy as np
 import pandas as pd
+import pytest
 
 from numpy.testing import assert_equal, assert_allclose, assert_raises, assert_
 
@@ -282,3 +285,41 @@ def test_cov_type_none():
     mod = ARIMA(endog[:50], trend='c')
     res = mod.fit(cov_type='none')
     assert_allclose(res.cov_params(), np.nan)
+
+
+def test_nonstationary_gls_error():
+    # GH-6540
+    endog = pd.read_csv(
+        io.StringIO(
+            """\
+data\n
+9.112\n9.102\n9.103\n9.099\n9.094\n9.090\n9.108\n9.088\n9.091\n9.083\n9.095\n
+9.090\n9.098\n9.093\n9.087\n9.088\n9.083\n9.095\n9.077\n9.082\n9.082\n9.081\n
+9.081\n9.079\n9.088\n9.096\n9.081\n9.098\n9.081\n9.094\n9.091\n9.095\n9.097\n
+9.108\n9.104\n9.098\n9.085\n9.093\n9.094\n9.092\n9.093\n9.106\n9.097\n9.108\n
+9.100\n9.106\n9.114\n9.111\n9.097\n9.099\n9.108\n9.108\n9.110\n9.101\n9.111\n
+9.114\n9.111\n9.126\n9.124\n9.112\n9.120\n9.142\n9.136\n9.131\n9.106\n9.112\n
+9.119\n9.125\n9.123\n9.138\n9.133\n9.133\n9.137\n9.133\n9.138\n9.136\n9.128\n
+9.127\n9.143\n9.128\n9.135\n9.133\n9.131\n9.136\n9.120\n9.127\n9.130\n9.116\n
+9.132\n9.128\n9.119\n9.119\n9.110\n9.132\n9.130\n9.124\n9.130\n9.135\n9.135\n
+9.119\n9.119\n9.136\n9.126\n9.122\n9.119\n9.123\n9.121\n9.130\n9.121\n9.119\n
+9.106\n9.118\n9.124\n9.121\n9.127\n9.113\n9.118\n9.103\n9.112\n9.110\n9.111\n
+9.108\n9.113\n9.117\n9.111\n9.100\n9.106\n9.109\n9.113\n9.110\n9.101\n9.113\n
+9.111\n9.101\n9.097\n9.102\n9.100\n9.110\n9.110\n9.096\n9.095\n9.090\n9.104\n
+9.097\n9.099\n9.095\n9.096\n9.085\n9.097\n9.098\n9.090\n9.080\n9.093\n9.085\n
+9.075\n9.067\n9.072\n9.062\n9.068\n9.053\n9.051\n9.049\n9.052\n9.059\n9.070\n
+9.058\n9.074\n9.063\n9.057\n9.062\n9.058\n9.049\n9.047\n9.062\n9.052\n9.052\n
+9.044\n9.060\n9.062\n9.055\n9.058\n9.054\n9.044\n9.047\n9.050\n9.048\n9.041\n
+9.055\n9.051\n9.028\n9.030\n9.029\n9.027\n9.016\n9.023\n9.031\n9.042\n9.035\n
+"""
+        ),
+        index_col=None,
+    )
+    mod = ARIMA(
+        endog,
+        order=(18, 0, 39),
+        enforce_stationarity=False,
+        enforce_invertibility=False,
+    )
+    with pytest.raises(ValueError, match="Roots of the autoregressive"):
+        mod.fit(method="hannan_rissanen", low_memory=True, cov_type="none")
diff --git a/statsmodels/tsa/innovations/tests/test_arma_innovations.py b/statsmodels/tsa/innovations/tests/test_arma_innovations.py
--- a/statsmodels/tsa/innovations/tests/test_arma_innovations.py
+++ b/statsmodels/tsa/innovations/tests/test_arma_innovations.py
@@ -42,3 +42,11 @@ def test_innovations_algo_filter_kalman_filter(ar_params, ma_params, sigma2):
     # Note: the tolerance on the two gets worse as more nobs are added
     assert_allclose(score, mod.score(params), atol=1e-5)
     assert_allclose(score_obs, mod.score_obs(params), atol=1e-5)
+
+
+@pytest.mark.parametrize("ar_params", ([1.9, -0.8], [1.0], [2.0, -1.0]))
+def test_innovations_nonstationary(ar_params):
+    np.random.seed(42)
+    endog = np.random.normal(size=100)
+    with pytest.raises(ValueError, match="The model's autoregressive"):
+        arma_innovations.arma_innovations(endog, ar_params=ar_params)