Repository: statsmodels/statsmodels

Issue:
Error in Statsmodel ARIMA Predict if “d” less than 1
Using V0.8 of Statsmodel from master branch, however I have replicated on V0.7 as well.

Calling predict() from an ARIMA model with the keyword argument 'typ' will throw an error unless d is a value greater than 0. A user on Stackoverflow noted that this is likely because when d=0 it simply hands off to ARMA where there is no typ keyword.

In the following example, df_account is a dataframe with a single accounts order history. The code below width p,d,q 0,0,1 will throw this error:

```
TypeError: predict() got an unexpected keyword argument 'typ'
```

It will throw that error in any scenario where "d" is less than 1. So (1,1,0) will work, but (1,0,0) will throw the unexpected keyword argument "typ" error.

```
fit = sm.tsa.ARIMA(df_account, (0,0,1)).fit()

predict = np.sum(fit.predict(p_start, p_end, dynamic=True, typ="levels").values) #, typ="levels"
actual = np.sum(df_account[p_start:p_end].values)
fig, ax = plt.subplots(figsize=(15, 5))
ax = df_account.ix['2013Q1':].plot(ax=ax)

fig = fit.plot_predict("2015Q4", "2017Q2", ax=ax, plot_insample=False, dynamic=True)
plt.title("{ix_name} | ARMA({p},{d},{q}) - AIC: {aic}".format(ix_name = ix_name, p=pick_p,d=pick_d,q=pick_q,aic=smallest_aic))
```



Discussion:
@craiglathrop218  Thanks for opening the issue. 

My guess is that we can change the signature that we can ignore the irrelevant typ keyword, maybe with a warning that we do.
I haven't looked at the code yet, but I guess that the delegation to ARMA when d=0 is causing the problems.

I guess this is mostly a usability bug, I think it can be worked around by not specifying the irrelevant `type` if d == 1, for example in a model search.

@jseabold 

I was analysing this is issue and I want to discuss my progress.
This is a sample code which causes this error:
`fit = sm.tsa.ARIMA(dta, (0,0,1)).fit()
fit.predict(dynamic=True, typ="levels")`
Now, the problem here is fit should be a object of `ARIMAResultsWrapper` but d=0 causes delegation to ARMA which makes fit of `ARMAResultsWrapper` type.
Now, predict function with typ parameter is not defined for `ARMAResultsWrapper`.

So, there are two possible solution:
1. add typ=None in the signature of `predict` of ARMAResultsWrapper. But then, in this current case ignoring the `typ` arguement makes sense only if the answer is same in `linear` or `levels` typ when d is 0. 
2. implement d=0 case within ARIMA

I am not sure whether I am correct. I want to work on this issue. Which of the two paths should I take?

Hi, It's better to go with number 1. add typ (or **kwds ?) argument to ARMAResultsWrapper and ignore.
I guess, there would be too much code duplication if we handle d=0 inside ARIMA.


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
@@ -698,9 +698,12 @@ def geterrors(self, params):
             errors = e[0][k_ar:]
         return errors.squeeze()
 
-    def predict(self, params, start=None, end=None, exog=None, dynamic=False):
+    def predict(self, params, start=None, end=None, exog=None, dynamic=False,
+                **kwargs):
+        if kwargs and 'typ' not in kwargs:
+            raise TypeError('Unkown extra arguments')
         method = getattr(self, 'method', 'mle')  # do not assume fit
-        #params = np.asarray(params)
+        # params = np.asarray(params)
 
         # will return an index of a date
         start, end, out_of_sample, _ = (
@@ -1483,8 +1486,10 @@ def pvalues(self):
         df_resid = self.df_resid
         return t.sf(np.abs(self.tvalues), df_resid) * 2
 
-    def predict(self, start=None, end=None, exog=None, dynamic=False):
-        return self.model.predict(self.params, start, end, exog, dynamic)
+    def predict(self, start=None, end=None, exog=None, dynamic=False,
+                **kwargs):
+        return self.model.predict(self.params, start, end, exog, dynamic,
+                                  **kwargs)
     predict.__doc__ = _arma_results_predict
 
     def _forecast_error(self, steps):


Test patch:
diff --git a/statsmodels/tsa/tests/test_arima.py b/statsmodels/tsa/tests/test_arima.py
--- a/statsmodels/tsa/tests/test_arima.py
+++ b/statsmodels/tsa/tests/test_arima.py
@@ -2503,3 +2503,17 @@ def test_constant_column_trend():
         model.fit(trend="c")
 
     # FIXME: calling model.fit(trend="nc") raises for orthogonal reasons
+
+
+def test_arima_d0_forecast(reset_randomstate):
+    arparams = np.array([1, -.75])
+    maparams = np.array([1, .65])
+    y = arma_generate_sample(arparams, maparams, 250)
+    mod = ARIMA(y, (1, 0, 1))
+    assert isinstance(mod, ARMA)
+    res = mod.fit(disp=-1)
+    pred = res.predict(start=200, end=300)
+    pred_typ = res.predict(start=200, end=300, typ='linear')
+    assert_allclose(pred, pred_typ)
+    pred_mod = mod.predict(res.params, start=200, end=300, typ='linear')
+    assert_allclose(pred, pred_mod)