# Why do my Forecast vs Actual Graph using ARIMA look weird?

I tried using ARIMA method to forecast yearly Wind speed data, using Diky fuller test P-value is below 0.05 hence I use the original data instead of differential. The data amounts 730, 2 sets of data for 1 day.

from statsmodels.tsa.arima_model import ARIMA

# 1,0,2 ARIMA Model
model = ARIMA(df, order=(1,0,2))
model_fit = model.fit(disp=0)
print(model_fit.summary())


This code gives me MA.L2.wind_speed: coeff= 0.1657, std error= 0.042, P>|z|=0

So I think I am good with this p, d and q value

model_fit.plot_predict(dynamic=False)
plt.show()


The actual vs fitting data does not look bad, but the issue comes from Out-of-time Validation graph

It looks too much different with the actual data. I use this code to for the forecast.

train = df[:620]

test = df[620:]

# Build Model
# model = ARIMA(train, order=(3,2,1))
model = ARIMA(train, order=(1, 0, 2))
fitted = model.fit(disp=-1)

# Forecast
fc, se, conf = fitted.forecast(110, alpha=0.05)  # 95% conf

# Make as pandas series
fc_series = pd.Series(fc, index=test.index)
lower_series = pd.Series(conf[:, 0], index=test.index)
upper_series = pd.Series(conf[:, 1], index=test.index)


What should I do to fix the forecast?

EDIT: Below is the picture of ACF and PCF I used to decide P and Q Value

P comes from Partial correlation that while I could not see the significance line, lag 1 has shown to be above it and safe enough to be used, CMIIW.

Q uses Auto correlation, I simply chose 2 because there are several lags above the line, so if 2 does not give good error I would change it into other numbers.

The Estimates from ARMA models are as follow: constant = 3.8709

ar.L1.wind_speed = 0.5320

ma.L1.wind_speed = -0.2129

ma.L2.wind_speed = 0.1657

• You fitted an ARIMA(1,0,2) model, so you should have one AR and two MA parameter estimates, plus apparently also an intercept. Can you edit your post to include these estimates? Also, are your data available somewhere online? – Stephan Kolassa Apr 21 at 16:46
• Thanks for commenting, I am kinda new with this but I figure you are asking about how I got P and Q value? I made estimates from ACF and PCF graph, I edit my questions to show them. As for the data, it is not available online but I am willing to share after editing some parts so it would only show the data values. – Iyo Widiastomo Apr 21 at 17:09
• No, I am not asking about how you set the AR and MA orders. These orders determine the number of parameters, and I was asking about the estimates for these parameters. Also, you can't use (P)ACF to determine ARMA orders if both $p$ and $q$ are larger than zero. I would recommend you take a look at Forecasting: Principles and Practice (2nd ed.) by Athanasopoulos & Hyndman and consider an automatic ARIMA fitter, like auto.arima() in the forecast package for R. – Stephan Kolassa Apr 21 at 17:41
• I see, the coeff from the ARMA model right? I edited them on the last part of my Question. Also thank you for the link. – Iyo Widiastomo Apr 21 at 18:05

It looks exactly as I would expect this kind of a model should forecast the mean.

This is an AR(1) model (ignoring MA terms here). It's of the form: $$x_t=c+\phi_1 x_{t-1}+\varepsilon_t$$

After a few steps its forecast becomes a straight line at $$\bar\mu=\frac c {1-\phi_1}$$ level. Even if you include MA terms the long run forecast is the same, only variance changes a bit. Information about the world at $$I_{t-1}=x_{t-1}$$ is lost at the rate of $$(1-\phi_1)^h$$ with $$h$$ being a period of forecast horizon. After a few steps none of the past matters except the long run mean $$\bar\mu$$

ARIMA models are great for short term forecasting, and also are useful to handle strong seasonality. They don't have a lot of structure, and are generally boring in long term forecasts without seasonality

• Thank you but if it is possible could you explain the c, ϕ1, xt and others in your formula? I am really new, so I could only understand that I need to add seasonality in my codes. I do not understand on how would those formula explain the line in the graph become complete linear. – Iyo Widiastomo Apr 21 at 18:18
• you need to understand the meaning of the output from your function in order to use it. show what this statement prints in your code: print(model_fit.summary()) I bet the constant is around 2. – Aksakal Apr 21 at 18:21
• @IyoWidiastomo since you are using Python statsmodels it is no wonder you are confused because they design the output to confuse its users. In my answer $c/(1-\phi_1)$ correspond to constant in your output. Ar(1) coefficient $\phi_1$ is ar.L1 in your output – Aksakal Apr 21 at 19:38

I'll be hand-wavy but your outputs are fine for an ARIMA. The main difference between your two graphs of fitted and out of sample forecasts are that you are feeding actual past values in the top graph but your forecast uses past forecast values to forecast. Simple ARIMA orders will never have the bips and bops that your actual data has in it's forecast in a long forecast horizon. If there is some sense of seasonality or something you could:

1. De-seasonalize it and fit arima then add back in seasonality
2. Fit a SARIMAX which also comes with Statmodels
3. Fit some other model like a holt-winters or fbprophet

I personally recommend number 3!

And if there is no real seasonality then what the ARIMA has done is essentially cut through the noise and shown you the level of your inputs which is a reasonable thing to do.

• I see, so basically I need to add seasonality right? – Iyo Widiastomo Apr 21 at 18:15
• @IyoWidiastomo if it has it yeah. Is this data you can share? Otherwise looks like you have 730 days of the wind data so you could try a seasonal model and just pass in the seasonality of 365 for yearly. If you add this but it is basically just noise then it will add some waviness but not much and you are probably better off with a nonseasonal model. You could do a traditional test for seasonality but I recommend you peruse the book that has been mentioned and stick to more plug and play models for now like fbprophet. – Tylerr Apr 21 at 19:09
• This data is actually for 365 days, it is just that on one day 2 data of wind speed at Day and Night are observed, making the total amount of data to be 730. I do not mind sharing it but I probably could only share the value but not the date or place. I have another question though, about seasonality, I consider Wind speed as seasonality because of seasonal wind, but am I mistaking the meaning of seasonality in forecast model with my example? – Iyo Widiastomo Apr 21 at 21:32
• @IyoWidiastomo ah that is a more complicated question and if possible it may be easier to split it up and do night time as one data set and day time as another. And by Seasonality I mean any persistent effects that would be observed every n periods, so for yearly data it would occur 'about' every 365 days. A large wrinkle with your data is that you only have 1 year of it, so you have to be very careful about seasonality, preferably you would want multiple instances of the same day per year. – Tylerr Apr 22 at 1:16