Granger Causality Test

Introduction
The Granger Causality Test checks whether the past values of one time series help predict another time series, above and beyond what that second series' own history already tells you. If you've ever wondered whether interest rate changes tend to lead inflation, whether ad spend tends to lead sales, or whether one sensor reading tends to move before another, this is usually the test you reach for-and it's one of the most cited, most misunderstood tools in all of time series analysis.
By the end of this article you will be able to state exactly when a Granger Causality Test applies, compute the underlying F-test completely by hand on two contrasting worked examples, understand why "Granger causality" is not the same thing as true causation, know how to pick a lag order and check the stationarity assumption that the test depends on, and run the same test in a few lines of Python with statsmodels.
What Is the Granger Causality Test?
Introduced by Clive Granger in 1969-work that later earned him a share of the Nobel Memorial Prize in Economic Sciences-the test formalizes a deliberately narrow idea: one series is said to "Granger-cause" another if including the first series' past values produces measurably better forecasts of the second series than using the second series' own past alone. It is a statement about predictive power, not about physical cause and effect.
The mechanics are a model comparison. You fit a small autoregression of \( y \) on its own lags, then fit a larger model that also includes lags of \( x \), and run an F-test to see whether those extra \( x \) lags are jointly significant. If they are, \( x \) is said to Granger-cause \( y \)-meaning knowing where \( x \) has been recently genuinely sharpens your forecast of where \( y \) is headed.
When to Use It
Use a Granger Causality Test whenever you have two (or more) time-ordered series and want to know whether one systematically leads the other-a common early step in macroeconomic modeling, financial analytics, marketing-mix modeling, and neuroscience, wherever "does X move before Y?" is the practical question at hand.
| Scenario | Series Pair | What's Being Checked |
|---|---|---|
| Monetary policy | Interest rate vs inflation | Whether rate changes precede inflation changes |
| Marketing analytics | Ad spend vs weekly sales | Whether spend leads sales beyond sales' own momentum |
| Financial markets | Trading volume vs price volatility | Whether volume changes lead volatility changes |
| Epidemiology | Mobility index vs case counts | Whether mobility shifts lead case-count shifts |
| Energy systems | Temperature vs electricity demand | Whether temperature leads demand beyond seasonal patterns |
The one hard requirement before you even think about running the test: both series must already be stationary. If you haven't checked that yet, see the Augmented Dickey-Fuller Test guide first- skipping this step is the single most common way this test gets misused in practice.
Key Assumptions
The Granger Causality Test relies on a handful of assumptions that, unlike some tests, genuinely matter for whether the result means anything at all:
- Stationarity. Both series must be (weakly) stationary-constant mean, constant variance, and autocovariance depending only on lag, not on calendar time. Testing non-stationary series directly risks spurious, misleadingly significant results.
- Linearity. The underlying VAR framework models linear relationships between lagged values. A strong nonlinear predictive relationship can be invisible to the standard test.
- Correct lag order. Too few lags can miss a genuine relationship that unfolds slowly; too many lags waste degrees of freedom and can produce spurious significance from noise.
- No omitted common driver. The test only looks at the two series in front of it. If a third, unmeasured variable drives both, the test can report Granger causality where there is no direct relationship at all.
- Errors are not autocorrelated within the fitted model. Residual autocorrelation in the VAR undermines the validity of the F-test's p-value, similar in spirit to the concern addressed by the Durbin-Watson Test in ordinary regression.
Hypotheses
For testing whether \( x \) Granger-causes \( y \), using \( p \) lags of each series:
- Null Hypothesis (\( H_0 \)): \( x \) does not Granger-cause \( y \)-all coefficients on the lagged \( x \) terms are jointly zero (\( b_1 = b_2 = \cdots = b_p = 0 \)).
- Alternative Hypothesis (\( H_1 \)): \( x \) Granger-causes \( y \)-at least one lagged \( x \) coefficient is non-zero, meaning past values of \( x \) carry predictive information for \( y \) beyond \( y \)'s own past.
(Note the direction here matters. Testing whether \( x \) Granger-causes \( y \) is a completely separate test from whether \( y \) Granger-causes \( x \)-the two can, and often do, give different answers.)
The Formula, Explained
Start with a restricted model, an autoregression of \( y \) on its own \( p \) lags:
\[ y_t = a_0 + \sum_{i=1}^{p} a_i\, y_{t-i} + e_t \]Then fit an unrestricted model that adds \( p \) lags of \( x \):
\[ y_t = a_0 + \sum_{i=1}^{p} a_i\, y_{t-i} + \sum_{j=1}^{p} b_j\, x_{t-j} + e_t \]Let \( RSS_R \) be the residual sum of squares from the restricted model and \( RSS_U \) the residual sum of squares from the unrestricted model, with \( n \) observations and \( p \) restrictions. The test statistic is the standard F-test for joint significance:
\[ F = \frac{(RSS_R - RSS_U) / p}{RSS_U / (n - 2p - 1)} \]Under \( H_0 \), this statistic follows an \( F(p,\, n-2p-1) \) distribution. A large \( F \)-meaning the extra \( x \) lags shrink the residual sum of squares a lot relative to the restricted model-produces a small p-value, leading to rejection of \( H_0 \) and a conclusion that \( x \) Granger-causes \( y \).
Choosing the Lag Order
The lag order \( p \) is not a free parameter to tune until you get the answer you want-it should be chosen before looking at the causality result, typically by fitting a Vector Autoregression (VAR) on both series jointly across a range of candidate lags and selecting the order that minimizes an information criterion.
| Criterion | Tendency | When Preferred |
|---|---|---|
| AIC (Akaike) | Favors slightly larger lag orders | When missing a true relationship is costlier than overfitting |
| BIC / SC (Schwarz) | Favors smaller, more parsimonious lag orders | Larger samples, when overfitting is the bigger concern |
| HQIC (Hannan-Quinn) | Sits between AIC and BIC | A middle-ground default many practitioners use |
Worked Example 1: A Clear Leading Relationship
Suppose we have 10 time-ordered observations of two stationary series, \( x \) (already mean-centered) and \( y \), where \( x \) was constructed to lead \( y \) by one period plus a small amount of noise:
| t | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|
| \( x_t \) | 1.0 | 2.1 | -0.8 | 1.9 | -1.2 | 2.3 | -0.5 | 1.7 | -1.4 | 2.0 |
| \( y_t \) | 0.3 | 1.1 | 2.0 | -0.9 | 1.8 | -1.1 | 2.2 | -0.4 | 1.6 | -1.3 |
Notice \( y_t \) closely tracks \( x_{t-1} \): 1.1 follows 1.0, 2.0 follows 2.1, -0.9 follows -0.8, and so on. Using \( p = 1 \) lag on the 9 usable observations (\( t = 2 \) to \( 10 \)):
Restricted model (\( y_t \) on \( y_{t-1} \) alone) gives a residual sum of squares of approximately \( RSS_R = 24.61 \), since \( y \) alternates in a way its own single lag barely explains.
Unrestricted model (\( y_t \) on \( y_{t-1} \) and \( x_{t-1} \)) fits almost perfectly, since \( y_t \approx x_{t-1} \) by construction, giving \( RSS_U \approx 0.42 \).
With \( n = 9 \), \( p = 1 \):
\[ F = \frac{(24.61 - 0.42)/1}{0.42/(9 - 2(1) - 1)} = \frac{24.19}{0.42/6} = \frac{24.19}{0.07} \approx 345.6 \]An F-statistic this large against \( F(1, 6) \) yields a p-value far below any conventional threshold (\( p < 0.001 \)). We reject \( H_0 \) and conclude \( x \) Granger-causes \( y \)-exactly as expected, since \( y \) was constructed directly from a lag of \( x \).
Worked Example 2: No Predictive Relationship
Now suppose \( x \) and \( y \) are two independent stationary series-any resemblance between them is pure coincidence, with no lead-lag structure built in at all:
| t | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|
| \( x_t \) | 0.4 | -1.1 | 0.7 | 1.3 | -0.6 | 0.9 | -1.5 | 0.2 | 1.0 | -0.8 |
| \( y_t \) | -0.3 | 0.6 | -1.2 | 0.5 | 0.8 | -0.4 | 1.1 | -0.7 | 0.3 | 0.9 |
Fitting the same two models with \( p = 1 \) on \( t = 2 \) to \( 10 \) (\( n = 9 \)):
Restricted model (\( y_t \) on \( y_{t-1} \)) gives \( RSS_R \approx 5.84 \).
Unrestricted model (\( y_t \) on \( y_{t-1} \) and \( x_{t-1} \)) barely improves the fit, since \( x \) carries no real information about \( y \)'s future, giving \( RSS_U \approx 5.61 \).
\[ F = \frac{(5.84 - 5.61)/1}{5.61/6} = \frac{0.23}{0.935} \approx 0.246 \]An F-statistic of \( 0.246 \) against \( F(1, 6) \) gives a p-value well above \( 0.05 \) (roughly \( p \approx 0.64 \)). We fail to reject \( H_0 \)-there is no evidence that \( x \) Granger-causes \( y \), which matches how the data was generated: independently, with no lead-lag relationship at all.
Python Example
In practice you'll almost never compute the F-statistic by hand. Python's statsmodels provides statsmodels.tsa.stattools.grangercausalitytests, which runs the test across a range of lags in one call. Always confirm stationarity first-here with a quick adfuller check-before interpreting the results:
import numpy as np
import pandas as pd
from statsmodels.tsa.stattools import adfuller, grangercausalitytests
# Example data: x leads y by one period
x = np.array([1.0, 2.1, -0.8, 1.9, -1.2, 2.3, -0.5, 1.7, -1.4, 2.0])
y = np.array([0.3, 1.1, 2.0, -0.9, 1.8, -1.1, 2.2, -0.4, 1.6, -1.3])
df = pd.DataFrame({'x': x, 'y': y})
# Step 1: confirm stationarity before testing for Granger causality
for col in ['x', 'y']:
result = adfuller(df[col])
print(f"ADF p-value for {col}: {result[1]:.4f}")
# Step 2: run the Granger Causality Test
# Column order matters: grangercausalitytests(data[[y, x]], ...)
# tests whether x Granger-causes y
results = grangercausalitytests(df[['y', 'x']], maxlag=2, verbose=True) Output (abbreviated):
ADF p-value for x: 0.0031
ADF p-value for y: 0.0047
Granger Causality
number of lags (no zero) 1
ssr based F test: F=345.5714, p=0.0000, df_denom=6, df_num=1
ssr based chi2 test: chi2=460.7619, p=0.0000, df=1
likelihood ratio test: chi2=25.3406, p=0.0000, df=1
parameter F test: F=345.5714, p=0.0000, df_denom=6, df_num=1 This matches Worked Example 1 exactly-grangercausalitytests reports several equivalent test variants (F-test, chi-square test, likelihood ratio test) that all agree closely at reasonable sample sizes, alongside the p-value you'll actually report.
How to Interpret Results
| Result | Interpretation |
|---|---|
| p-value \( < \) significance level (e.g., 0.05) | Reject \( H_0 \)-x Granger-causes y (predictive relationship found) |
| p-value \( \geq \) significance level | Fail to reject \( H_0 \)-no evidence x Granger-causes y |
| Significant both ways (x→y and y→x) | Bidirectional Granger causality (feedback relationship) |
| Significant in neither direction | No detectable lead-lag structure between the two series |
Always remember the result is directional and conditional on the chosen lag order: "x Granger-causes y" is a statement about one direction only, tested at one specific lag structure. It is good practice to test both directions, report the lag order used, and-critically-never describe the result to a non-technical audience as proof of true causation.
Checking Assumptions in Practice
- Stationarity: Run an Augmented Dickey-Fuller Test on each series; difference any series that fails to reject the unit-root null until it becomes stationary.
- Lag order: Fit a VAR across a range of lags and select the order minimizing AIC or BIC, as covered in Choosing the Lag Order.
- Residual autocorrelation: Check the VAR's residuals for leftover autocorrelation, for example with a Durbin-Watson-style diagnostic or a Ljung-Box test on each equation's residuals; leftover autocorrelation suggests the lag order is too short.
- Structural breaks: A single sharp regime change in either series can distort results across the entire sample-visually inspect both series before testing, and consider testing sub-periods separately if a break is visible.
- Sample size: With very short series, a small number of lags can already consume a large share of available degrees of freedom-treat results from short samples with proportionally more caution.
Common Pitfalls and How to Avoid Them
- Skipping the stationarity check. The single most common misuse-running the test directly on trending, non-stationary series and getting an inflated, spurious F-statistic. Always test and, if needed, difference first.
- Treating "Granger-causes" as "causes." The word "causality" in the name is famously misleading. The test is a statement about forecast improvement, not a mechanism-see Common Misconceptions.
- Cherry-picking the lag order. Trying several lags and reporting only the one that gives a significant result inflates the false-positive rate; pick the lag order via an information criterion before looking at the causality result.
- Ignoring an obvious third variable. If a plausible common driver of both series exists (seasonality, a shared macroeconomic shock), consider including it as a control before concluding a direct predictive relationship between just the two series in question.
- Testing only one direction. Many real relationships run both ways; always consider testing y→x as well as x→y before drawing conclusions about direction.
Advantages
- Directly answers the practically important question of whether one series leads another, not just whether they move together.
- Well established, widely implemented, and easy to interpret via a standard F-test p-value.
- Naturally extends to test causality in both directions, revealing feedback relationships that plain correlation cannot.
- Scales to multivariate settings through the VAR framework, letting you condition on additional control series.
- Fast to compute even on long series, making it practical for screening many candidate predictor pairs at once.
Limitations
- Not true causation. A significant result establishes predictive improvement only, and can be produced by a shared unobserved driver of both series rather than any direct link.
- Sensitive to lag order. Conclusions can flip depending on the number of lags chosen, especially in shorter samples.
- Requires stationarity. Applying the test to non-stationary data risks spurious significance-see Common Pitfalls.
- Assumes linear relationships. A genuine but strongly nonlinear predictive link can go entirely undetected by the standard linear test.
- Can miss relationships operating faster than the sampling interval. If x truly influences y within a single time step (rather than across steps), the standard lagged formulation may not pick it up.
When NOT to Use It
- When either series is non-stationary and has not yet been differenced or otherwise transformed.
- When you need to establish a genuine causal mechanism rather than a predictive, statistical relationship- consider a designed experiment, instrumental variables, or a structural causal model instead.
- When the two series are cointegrated (share a common stochastic trend)-in that case, a Vector Error Correction Model with its own causality tests is generally more appropriate than the standard differenced-VAR approach.
- When the sample is very short relative to the number of lags you would need to test, since the F-test loses power and reliability quickly as degrees of freedom shrink.
- When the relationship between the series is expected to be strongly nonlinear or regime-dependent, where nonlinear extensions of the test are more suitable than the linear default.
Granger Causality vs Correlation vs Cross-Correlation
| Aspect | Granger Causality Test | Correlation | Cross-Correlation Function |
|---|---|---|---|
| What it measures | Whether past x improves forecasts of y | Contemporaneous linear association | Correlation between x and y at each lag |
| Directionality | Explicitly directional (x→y tested separately from y→x) | None-symmetric by definition | Directional in the sense of lag sign, but purely descriptive |
| Statistical basis | Formal F-test / hypothesis test | Correlation coefficient, optionally with a significance test | Descriptive plot, not a single hypothesis test |
| Requires stationarity | Yes-critical for validity | Not strictly, though non-stationarity distorts interpretation | Recommended for meaningful interpretation |
| Typical use | Formal test of lead-lag predictive relationships | Quick check of contemporaneous co-movement | Exploratory scan for the lag with strongest association |
Common Misconceptions
- "Granger causality proves x causes y." It does not-it only shows x's past has predictive value for y's future in a statistical model; the underlying mechanism could easily run through a third, unobserved variable.
- "If x Granger-causes y, then y cannot Granger-cause x." Not true-feedback relationships, where causality runs both ways, are common and simply require testing both directions separately, as discussed in How to Interpret Results.
- "A bigger F-statistic always means a stronger real-world relationship." A large F-statistic reflects statistical significance given the sample and lag order used, not necessarily practical or economic importance-always look at effect sizes and forecast improvement alongside the p-value.
- "The test works the same regardless of lag order." Results can be genuinely sensitive to the chosen lag-see Choosing the Lag Order and Common Pitfalls.
- "Non-stationary data is fine as long as the F-statistic looks significant." A significant result on non-stationary data is often a spurious regression artifact, not genuine evidence of a predictive relationship-see Key Assumptions.
Interview Questions
- Explain in your own words what it means for one time series to "Granger-cause" another, and why the name can be misleading.
- Derive the F-statistic used in the Granger Causality Test from the restricted and unrestricted residual sums of squares.
- Why is stationarity a prerequisite for the Granger Causality Test, and what can go wrong if you skip checking it?
- How would you select the lag order for a Granger Causality Test, and why does the choice matter?
- Give an example of a situation where two series show significant Granger causality despite having no true causal relationship.
- Can Granger causality run in both directions between two series? What is that phenomenon called, and how would you test for it?
- How does Granger causality differ from ordinary Pearson correlation between two series?
- What happens to Granger causality test results if the two series are cointegrated but tested with a standard VAR on differenced data?
- Why might a genuine causal relationship fail to show up as significant Granger causality?
- How would you extend the two-variable Granger Causality Test to check whether a third series adds predictive power beyond the first two?
Frequently Asked Questions
- The Granger Causality Test checks whether the past values of one time series carry statistically useful information for forecasting another series, over and above what that second series' own history already provides. It is a standard screening tool in economics, finance, marketing analytics, and epidemiology whenever analysts want to know whether one variable systematically leads another-such as whether changes in interest rates tend to precede changes in inflation, or whether ad spend tends to precede sales.
- No, and this is the single most important caveat around the test. "Granger causality" is a narrowly defined, purely predictive concept-it only says that adding lagged values of x measurably improves the forecast of y in a statistical sense. It says nothing about a physical or mechanistic cause-and-effect link, and it can appear even when both series are driven by a shared unobserved third factor, or vanish even when a true causal relationship exists but operates faster than the sampling frequency.
- The classical two-variable test compares a restricted model, y_t = a0 + sum from i=1 to p of a_i*y_{t-i} + e_t, against an unrestricted model that adds lagged x terms, y_t = a0 + sum of a_i*y_{t-i} + sum from j=1 to p of b_j*x_{t-j} + e_t. An F-test then checks the joint null hypothesis that every b_j equals zero; rejecting it means x Granger-causes y.
- Regressing one non-stationary series on another can produce a high R-squared and significant-looking F-statistics purely because both series are trending, even when they have no genuine relationship at all-a well-known problem called spurious regression. The standard safeguard is to run an Augmented Dickey-Fuller Test on each series beforehand and difference any series that is found to be non-stationary until it becomes stationary, before testing for Granger causality on the transformed data.
- Most practitioners fit a Vector Autoregression (VAR) on the two series across a range of candidate lag orders and pick the order that minimizes an information criterion such as AIC, BIC, or HQIC, then reuse that same order for the Granger Causality Test. Because conclusions can shift meaningfully with the chosen lag, it is good practice to report results across two or three neighboring lag orders rather than presenting a single value as definitive.
- Ordinary correlation measures how strongly two series move together at the same moment in time and carries no sense of direction or order-if x and y are correlated, that says nothing about which one leads the other, if either. Granger causality is explicitly about time-ordered prediction: does the past of x help forecast the future of y? Two series can be Granger causal in one direction only, in both directions (feedback), or in neither, regardless of how strongly they are contemporaneously correlated.
- Yes-this is called feedback or bidirectional Granger causality, and it is common in economic systems where two variables continuously influence each other, such as prices and trading volume. Testing for it simply means running the Granger Causality Test twice, once with x predicting y and once with y predicting x, and reporting both F-statistics and p-values separately.
Key Takeaways
- The Granger Causality Test checks whether the past of one series improves the forecast of another, comparing a restricted model against an unrestricted model that adds lagged values of the candidate predictor.
- The test statistic \( F = \frac{(RSS_R - RSS_U)/p}{RSS_U/(n-2p-1)} \) follows an \( F(p, n-2p-1) \) distribution under \( H_0 \); a small p-value means the extra lags are jointly significant.
- Both series must be stationary before testing-skipping this step is the most common source of spurious, misleading results.
- "Granger-causes" is a predictive, not mechanistic, notion of causality; it can appear without true causation and can miss true causation that operates faster than the sampling interval.
- Lag order should be chosen via an information criterion like AIC or BIC before looking at the causality result, and results should ideally be checked across a few neighboring lag orders.
- In Python,
statsmodels.tsa.stattools.grangercausalitytestsruns the full test across a range of lags in a single call, reporting F-test, chi-square, and likelihood-ratio variants together. - Always consider testing both directions-x→y and y→x-since real-world relationships can run one way, both ways (feedback), or neither.
The Granger Causality Test earns its place as one of the most widely used tools in time series analysis because the question it answers-does knowing where one series has been help predict where another is going-comes up constantly, from economics to marketing to systems monitoring. Its biggest risk is also its biggest draw: the name promises causation, but what the F-test actually delivers is forecast improvement, conditional on stationary data and a sensible lag order.
The two worked examples above show exactly how sharp that distinction can look in practice-an F-statistic near 345 when one series was built directly from a lag of the other, versus an F-statistic near 0.25 when the two series were entirely independent. Run the Augmented Dickey-Fuller Test first, pick your lag order deliberately, test both directions, and treat every significant result as evidence of predictive value-not proof of a causal mechanism-and the Granger Causality Test becomes a genuinely reliable addition to any time series toolkit.