Univariate Time Series Analysis

Kevin Sheppard

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]
intercept 0.0021 0.000 11.315 0.000 0.002 0.002
ar.L1 0.6326 0.010 62.755 0.000 0.613 0.652
sigma2 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"
pd.concat([h1, fast_h1], axis=1).head()
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()