As I already explained in the comment: I think your confusion arises from the difference between sampling/simulating and predicting. For example, doing a 2-step prediction for an $AR(p)$-process,
$$X_{n+1}= \sum_{h \geq 1} \theta_h X_{n+1-h} + \epsilon_{n+1} \\
X_{n+2}= \sum_{h \geq 1} \theta_h X_{n+2-h} + \epsilon_{n+2} = \sum_{h \geq 2} \theta_h X_{n+1-h} + \theta_1 \left( \sum_{h \geq 1} \theta_h X_{n+1-h} + \epsilon_{n+1} \right) + \epsilon_{n+2}$$
What is the best linear prediction? Since we are dealing with linear time series models, answering this essentially amounts to setting all the future $\epsilon_t$ equal to zero, i.e.
$$\widehat{X_{n+1}} = \sum_{h \geq 1} \theta_h X_{n+1-h} \\
\widehat{X_{n+2}}= \sum_{h \geq 2} \theta_h X_{n+1-h} + \theta_1 \left( \sum_{h \geq 1} \theta_h X_{n+1-h} \right)
$$
and so on. Eventually, this will become zero (which is also expected, because with the ACF $\rho(h) = \operatorname{cov}[X_n, X_{n+h}] \to 0$ for $h \to \infty$, this means that $X_{n+h}$ should become independent of the time series up to time $n$, and hence your best guess would be the mean [i.e. a constant]).
Unfortunately I am not particularly familiar with the statsmodels
API (I find the forecast
package in R much nicer to use, statsmodels
seems pretty messy). There seems to be a simulate()
method, but apparently only for the classes under statsmodels.tsa.statespace
(maybe someone can confirm this or prove me wrong). Anyway, I tried to code this by hand, building on your code, just to illustrate the difference:
values = fit.fittedvalues
n = values.shape[0]
h = 100 # number of forecast steps
values = np.concatenate((values, np.zeros(h)), axis=0) # extend time series with zeroes
nlags = len(fit.ar_lags)
# now predict stepwise
for i in range(0, h):
lagged_values = np.concatenate((np.array([1.]), values[(n+i-nlags):(n+i)]), axis=0)
values[n+i] = -(fit.params @ lagged_values) + np.random.normal(0, np.sqrt(fit.sigma2), 1)
plt.plot(values)
plt.plot(fit.predict(1, n+h))
(orange: samples, blue: prediction)
PS: I share your confusion that the coefficients seem to be the negatives of the ones used for generating the samples. There are two different conventions in the literature, and apparently this is inconsistent accross statsmodels
. I am really not fond of this package...
[ Just noticed: The [1.] should then probably be a [-1.]... Doesn't really matter since the intercept is so small. ;) ]