# Forecasting¶

• One-step forecast
$$E_t[Y_{t+1}]$$
• Multi-step forecast
$$E_t[Y_{t+h}]$$
• Forecasts are recursively computed

• First compute $E_t[Y_{t+1}]$ which depends on the $\mathcal{F}_t$ information $Y_t, Y_{t-1}, \ldots, \hat{\epsilon}_{t}, \hat{\epsilon}_{t-1} \ldots$
• Then compute $E_t[Y_{t+2}]$ which depends on $E_t[Y_{t+1}]$ and $\mathcal{F}_t$ information
• Repeat until $E_t[Y_{t+h}]$
• Forecasts from covariance stationary time series are mean reverting

# AR(1) Model Fitting¶

$$Y_t = \phi_0 + \phi_1 Y_{t-1} + \epsilon_t$$
In [5]:
res = SARIMAX(m2_growth, order=(1, 0, 0), trend="c").fit()
summary(res)

coef std err z P>|z| [0.025 0.975] 0.0021 0.000 11.315 0.000 0.002 0.002 0.6326 0.010 62.755 0.000 0.613 0.652 1.221e-05 1.85e-07 65.856 0.000 1.18e-05 1.26e-05

# Forecasts¶

$$\mathrm{E}_t[Y_{t+h}] = \phi_0 + \phi_1 \mathrm{E}_t[Y_{t+h-1}] + \mathrm{E}_t[\epsilon_{t+h}]$$
In [6]:
fcast = res.forecast(12)
plot(fcast, y=-2)


# Manually Constructing Forecasts¶

• Forecasts are directly computes using the recursive form
$$\mathrm{E}_t[Y_{t+h}] = \phi_0 + \phi_1 \mathrm{E}_t[Y_{t+h-1}] + \mathrm{E}_t[\epsilon_{t+h}]$$
• Rules for computing $E_t[Y_{t+h}]$
1. $\mathrm{E}_t[\epsilon_{t+h}]=0$ if $h>0$
2. $\mathrm{E}_t[\epsilon_{t+h}]=\hat{\epsilon}_{t+h}$ if $h\leq 0$
3. $\mathrm{E}_t[Y_{t+h}]=Y_{t+h}$ if $h\leq 0$
4. Replace $\mathrm{E}_t[Y_{t+h-j}]$ with its value previously computed
In [7]:
p0 = res.params["intercept"]
p1 = res.params["ar.L1"]
direct = pd.Series(np.zeros(12), index=fcast.index)
for i in range(12):
if i == 0:
direct[i] = p0 + p1 * m2_growth.iloc[-1]
else:
direct[i] = p0 + p1 * direct[i - 1]


# Manual Forecasts¶

In [8]:
plot(direct)


# Recursive Forecast Construction¶

• Simple to construct forecasts recursively
In [9]:
t = m2_growth.shape[0]
half = t // 2

forecasts = []
res = SARIMAX(m2_growth.iloc[:half], order=(1, 0, 0), trend="c").fit()
forecasts.append(res.forecast(1))
for i in range(half, t):
res = res.extend(m2_growth.iloc[i : i + 1])
forecasts.append(res.forecast(1))
h1 = pd.concat(forecasts)
h1.name = "h1"


# Fast one-step forecast construction¶

• extend using second half and use get_prediction()
In [10]:
res2 = SARIMAX(m2_growth.iloc[:half], order=(1, 0, 0), trend="c").fit()
res2 = res2.extend(m2_growth.iloc[half:])
fast_h1 = res2.get_prediction().predicted_mean
fast_h1.name = "fast_h1"

Out[10]:
h1 fast_h1
1990-06-01 0.001715 0.001715
1990-07-01 0.004789 0.004789
1990-08-01 0.004279 0.004279
1990-09-01 0.005718 0.005718
1990-10-01 0.004645 0.004645

# Forecasts and Realizations¶

In [12]:
fig, ax = plt.subplots(1, 1)
h1.plot(ax=ax)
_ = realizations.plot(ax=ax)


# Forecast Errors¶

• 1-step should be a $WN$ process
• $h$-step should be at most a $MA(h-1)$
In [14]:
fe = (realizations - h1).dropna()
plot(fe, 13)


# Forecast Error Autocorrelation¶

• 1-step should be a $WN$ process
• $h$-step should be at most a $MA(h-1)$
In [16]:
acf_pacf_plot(fe, 24, size=-2)


# Multi-step Forecasts¶

• Multi-step forecasts are recursively generated
In [18]:
multistep_forecast_plot()