Repository: statsmodels/statsmodels

Issue:
BUG: cloning of arima.ARIMA models.
Attempting to clone one of the new `arima.ARIMA` models fails:

```python
endog = np.arange(20)
mod = sm.tsa.arima.ARIMA(endog)
mod_c = mod.clone(endog)
```

yields:

```
TypeError: __init__() got an unexpected keyword argument 'measurement_error'
```

because `measurement_error` is a valid argument for `SARIMAX` but not for `arima.ARIMA`.


Discussion:

Resolving patch:
diff --git a/statsmodels/tsa/arima/model.py b/statsmodels/tsa/arima/model.py
--- a/statsmodels/tsa/arima/model.py
+++ b/statsmodels/tsa/arima/model.py
@@ -104,8 +104,8 @@ class ARIMA(sarimax.SARIMAX):
     def __init__(self, endog, exog=None, order=(0, 0, 0),
                  seasonal_order=(0, 0, 0, 0), trend=None,
                  enforce_stationarity=True, enforce_invertibility=True,
-                 concentrate_scale=False, dates=None, freq=None,
-                 missing='none'):
+                 concentrate_scale=False, trend_offset=1, dates=None,
+                 freq=None, missing='none'):
         # Default for trend
         # 'c' if there is no integration and 'n' otherwise
         # TODO: if trend='c', then we could alternatively use `demean=True` in
@@ -134,11 +134,19 @@ def __init__(self, endog, exog=None, order=(0, 0, 0),
         # standardizes the trend to always be part of exog, while the base
         # SARIMAX class puts it in the transition equation.
         super(ARIMA, self).__init__(
-            endog, exog, order=order, seasonal_order=seasonal_order,
+            endog, exog, trend=None, order=order,
+            seasonal_order=seasonal_order,
             enforce_stationarity=enforce_stationarity,
             enforce_invertibility=enforce_invertibility,
             concentrate_scale=concentrate_scale, dates=dates, freq=freq,
             missing=missing)
+        self.trend = trend
+
+        # Remove some init kwargs that aren't used in this model
+        unused = ['measurement_error', 'time_varying_regression',
+                  'mle_regression', 'simple_differencing',
+                  'hamilton_representation']
+        self._init_keys = [key for key in self._init_keys if key not in unused]
 
     @property
     def _res_classes(self):
diff --git a/statsmodels/tsa/arima/specification.py b/statsmodels/tsa/arima/specification.py
--- a/statsmodels/tsa/arima/specification.py
+++ b/statsmodels/tsa/arima/specification.py
@@ -214,13 +214,14 @@ def __init__(self, endog=None, exog=None, order=None,
                  seasonal_ar_order=None, seasonal_diff=None,
                  seasonal_ma_order=None, seasonal_periods=None, trend=None,
                  enforce_stationarity=None, enforce_invertibility=None,
-                 concentrate_scale=None, dates=None, freq=None,
+                 concentrate_scale=None, trend_offset=1, dates=None, freq=None,
                  missing='none'):
 
         # Basic parameters
         self.enforce_stationarity = enforce_stationarity
         self.enforce_invertibility = enforce_invertibility
         self.concentrate_scale = concentrate_scale
+        self.trend_offset = trend_offset
 
         # Validate that we were not given conflicting specifications
         has_order = order is not None
@@ -403,7 +404,7 @@ def __init__(self, endog=None, exog=None, order=None,
         # Add trend data into exog
         nobs = len(endog) if exog is None else len(exog)
         if self.trend_order is not None:
-            trend_data = self.construct_trend_data(nobs)
+            trend_data = self.construct_trend_data(nobs, trend_offset)
             if exog is None:
                 exog = trend_data
             elif _is_using_pandas(exog, None):


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
@@ -197,3 +197,53 @@ def test_low_memory():
     assert_(res2.predicted_state is None)
     assert_(res2.filtered_state is None)
     assert_(res2.smoothed_state is None)
+
+
+def check_cloned(mod, endog, exog=None):
+    mod_c = mod.clone(endog, exog=exog)
+
+    assert_allclose(mod.nobs, mod_c.nobs)
+    assert_(mod._index.equals(mod_c._index))
+    assert_equal(mod.k_params, mod_c.k_params)
+    assert_allclose(mod.start_params, mod_c.start_params)
+    p = mod.start_params
+    assert_allclose(mod.loglike(p), mod_c.loglike(p))
+    assert_allclose(mod.concentrate_scale, mod_c.concentrate_scale)
+
+
+def test_clone():
+    endog = dta['infl'].iloc[:50]
+    exog = np.arange(endog.shape[0])
+
+    # Basic model
+    check_cloned(ARIMA(endog), endog)
+    check_cloned(ARIMA(endog.values), endog.values)
+    # With trends
+    check_cloned(ARIMA(endog, trend='c'), endog)
+    check_cloned(ARIMA(endog, trend='t'), endog)
+    check_cloned(ARIMA(endog, trend='ct'), endog)
+    # With exog
+    check_cloned(ARIMA(endog, exog=exog), endog, exog=exog)
+    check_cloned(ARIMA(endog, exog=exog, trend='c'), endog, exog=exog)
+    # Concentrated scale
+    check_cloned(ARIMA(endog, exog=exog, trend='c', concentrate_scale=True),
+                 endog, exog=exog)
+
+    # Higher order (use a different dataset to avoid warnings about
+    # non-invertible start params)
+    endog = dta['realgdp'].iloc[:100]
+    exog = np.arange(endog.shape[0])
+    check_cloned(ARIMA(endog, order=(2, 1, 1), seasonal_order=(1, 1, 2, 4),
+                       exog=exog, trend='c', concentrate_scale=True),
+                 endog, exog=exog)
+
+
+def test_append():
+    endog = dta['infl'].iloc[:100].values
+    mod = ARIMA(endog[:50], trend='c')
+    res = mod.fit()
+    res_e = res.append(endog[50:])
+    mod2 = ARIMA(endog)
+    res2 = mod2.filter(res_e.params)
+
+    assert_allclose(res2.llf, res_e.llf)