Lesson 6.6: From One Series to Many: Vector Autoregression (VAR) Models

We now make a monumental leap from modeling single time series to modeling entire systems of interconnected variables. This lesson introduces the Vector Autoregression (VAR) model, the multivariate generalization of the AR model. VAR allows us to capture the rich, dynamic interplay between multiple time series, moving beyond simple correlation to analyze concepts like causality and shock propagation.

Part 1: The Limits of Univariate Models

The ARIMA and GARCH models we mastered in Module 5 are powerful tools for understanding a single time series in isolation. However, economic and financial variables do not exist in a vacuum. The price of oil is not independent of the value of the US dollar. A central bank's interest rate decisions affect stock market returns, which in turn affect consumer spending.

Treating these as separate univariate problems is to ignore the fundamental feedback loops that govern the system. A simple regression might tell us that XX influences YY, but what if YY also influences XX? This bidirectional relationship is beyond the scope of the models we have learned so far.

The Core Problem: A Interconnected Financial System

Consider a simple system of two variables: the daily returns of the S&P 500 (Rsp500R_{sp500}) and the daily change in the VIX volatility index (ΔVIX\Delta VIX).

  • A univariate AR model for S&P 500 returns would only use past S&P 500 returns to forecast the future: Rsp500,t=f(Rsp500,t1,)R_{sp500, t} = f(R_{sp500, t-1}, \dots).
  • A univariate model for VIX changes would only use past VIX changes.
  • This approach completely misses the well-known dynamic: a large negative stock return today often leads to a spike in the VIX tomorrow, and a high VIX level today often signals nervous markets and can influence future stock returns.

To capture these cross-variable dynamics and feedback loops, we need to model the variables together as a single, unified system. This is the purpose of the Vector Autoregression model.

Part 2: The VAR(p) Model Specification

A VAR model is a system of equations where each variable is regressed on its own lagged values and the lagged values of all other variables in the system. The "Vector" in its name comes from the use of vector and matrix algebra to represent this system compactly.

A Simple Bivariate VAR(1) Model

Let's consider a system with two variables, y1,ty_{1,t} and y2,ty_{2,t}. A VAR(1) model consists of two distinct regression equations:

Equation 1: Predicts y1y_1 using past values of both y1y_1 and y2y_2.

y1,t=c1+ϕ11,1y1,t1+ϕ12,1y2,t1+ϵ1,ty_{1,t} = c_1 + \phi_{11,1} y_{1,t-1} + \phi_{12,1} y_{2,t-1} + \epsilon_{1,t}

Equation 2: Predicts y2y_2 using past values of both y1y_1 and y2y_2.

y2,t=c2+ϕ21,1y1,t1+ϕ22,1y2,t1+ϵ2,ty_{2,t} = c_2 + \phi_{21,1} y_{1,t-1} + \phi_{22,1} y_{2,t-1} + \epsilon_{2,t}
  • The coefficients ϕii,l\phi_{ii,l} capture the variable's own-lag dynamics (the AR part).
  • The coefficients ϕij,l\phi_{ij,l} (where iji \ne j) are the crucial new terms. They capture the influence of the ll-th lag of variable jj on the current value of variable ii.
  • The error terms ϵ1,t\epsilon_{1,t} and ϵ2,t\epsilon_{2,t} are assumed to be white noise, but they can be contemporaneously correlated, Cov(ϵ1,t,ϵ2,t)0\text{Cov}(\epsilon_{1,t}, \epsilon_{2,t}) \ne 0.

The VAR(p) Model in Matrix Form

We can write this system much more elegantly using matrices. Let yt\mathbf{y}_t be a vector of our KK variables at time tt.

yt=c+Φ1yt1+Φ2yt2++Φpytp+ϵt\mathbf{y}_t = \mathbf{c} + \mathbf{\Phi}_1 \mathbf{y}_{t-1} + \mathbf{\Phi}_2 \mathbf{y}_{t-2} + \dots + \mathbf{\Phi}_p \mathbf{y}_{t-p} + \bm{\epsilon}_t

For our bivariate VAR(1) example:

[y1,ty2,t]=[c1c2]+[ϕ11,1ϕ12,1ϕ21,1ϕ22,1][y1,t1y2,t1]+[ϵ1,tϵ2,t]\begin{bmatrix} y_{1,t} \\ y_{2,t} \end{bmatrix} = \begin{bmatrix} c_1 \\ c_2 \end{bmatrix} + \begin{bmatrix} \phi_{11,1} & \phi_{12,1} \\ \phi_{21,1} & \phi_{22,1} \end{bmatrix} \begin{bmatrix} y_{1,t-1} \\ y_{2,t-1} \end{bmatrix} + \begin{bmatrix} \epsilon_{1,t} \\ \epsilon_{2,t} \end{bmatrix}

Key Assumptions: For a VAR model to be useful, all variables in the system must be stationary. If they are non-stationary (I(1)), we must either difference them or use the more advanced VECM model we will learn about later.

Part 3: The New Toolkit - Granger Causality and IRFs

A fitted VAR model is a dense system of coefficients, which can be difficult to interpret directly. The real power of VAR analysis comes from two specialized tools that allow us to understand the model's dynamics.

Tool 1: Granger Causality

Granger causality is a statistical, not a philosophical, definition of causality. It asks a simple question: "Does knowing the past of variable XX help me make a better forecast of variable YY, even after I already know the entire past of YY?"

In our bivariate VAR(1), we say that y2y_2 **Granger-causes** y1y_1 if the coefficient ϕ12,1\phi_{12,1} is statistically significantly different from zero. We test this with a simple F-test on the relevant coefficients.

Tool 2: Impulse Response Functions (IRFs)

An Impulse Response Function is the most important tool for VAR analysis. It traces out the dynamic impact of a one-time shock to one of the variables on the future paths of all variables in the system.

It answers the question: "If a shock of one standard deviation hits variable XX today, what is the effect on variable YY over the next 10 periods?"

The Problem of Identification: A raw shock to ϵ1,t\epsilon_{1,t} might be correlated with a shock to ϵ2,t\epsilon_{2,t}. To trace out a "pure" shock to one variable, we need to make an ordering assumption. The standard method for this is the **Cholesky decomposition** of the covariance matrix of the errors, which assumes that the first variable in the ordering contemporaneously affects all others, the second affects all but the first, and so on. The ordering of variables in a VAR model matters for the IRF.

Part 4: Python Implementation - A Macroeconomic VAR

Analyzing a Macro System with a VAR Model

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
from statsmodels.tsa.api import VAR

# --- 1. Load and Prepare Data ---
# Use the famous Macroeconomic Data from statsmodels
data = sm.datasets.macrodata.load_pandas().data
data = data[['infl', 'unemp', 'tbilrate']].copy()
# Take the first difference to ensure stationarity
data_diff = data.diff().dropna()

# --- 2. Select the VAR Order (p) ---
# We can use information criteria to select the optimal lag order
model_for_selection = VAR(data_diff)
# results_aic = model_for_selection.select_order(maxlags=10, ic='aic')
# print(results_aic.summary()) # Let's assume AIC suggests p=1

# --- 3. Fit the VAR(1) Model ---
model = VAR(data_diff)
results = model.fit(1) # Fit with 1 lag
print(results.summary())

# --- 4. Granger Causality Test ---
# Does unemployment Granger-cause inflation?
gc_test = results.test_causality('infl', ['unemp'], kind='f')
print("\nGranger Causality Test (unemp -> infl):")
print(gc_test.summary())
# A low p-value suggests it does.

# --- 5. Impulse Response Function (IRF) ---
# How does a shock to the treasury bill rate affect unemployment?
irf = results.irf(periods=20)
# The plot traces the response of each variable to an impulse in each variable.
irf.plot(orth=True, response='unemp', impulse='tbilrate')
plt.title('Response of Unemployment to a T-Bill Rate Shock')
plt.xlabel('Periods after shock')
plt.ylabel('Change in Unemployment')
plt.grid(True, alpha=0.3)
plt.show()

# --- 6. Forecast ---
# Forecast the next 10 quarters
lag_order = results.k_ar
forecast = results.forecast(data_diff.values[-lag_order:], steps=10)

# The output is an array of forecasts for each variable
print("\n10-Quarter Forecast (Differenced Data):")
print(forecast)

What's Next? Finding Long-Run Balance

The VAR model is a powerful tool for analyzing the short-run dynamics of stationary systems. We built it by differencing our non-stationary macro data. But in doing so, we may have thrown away valuable information about the **long-run relationships** between the levels of the variables.

For example, economic theory suggests that two interest rates with different maturities should not drift arbitrarily far apart from each other forever; there is a long-run equilibrium relationship that anchors them. Differencing the data ignores this anchor.

In the next lesson, we will introduce the concept of **Cointegration**—a statistical test for the existence of these stable, long-run equilibrium relationships between non-stationary time series.

Up Next: Finding Long-Run Relationships: Cointegration