Regression Analysis for Financial Relationships › Diagnosing Regression Problems
Quantitative FinanceAll chapters Regression Analysis for Financial Relationships › Diagnosing Regression ProblemsOne section · Sections in this chapter5 / 12 ↓
The validity of OLS inference depends on several assumptions about the error term. With financial time series data, these assumptions are frequently violated, leading to incorrect standard errors and misleading hypothesis tests. Understanding these assumptions and knowing how to detect their violations is essential for producing reliable results. Failing to address these issues can lead to false confidence in spurious relationships or obscure effects that are present.
The Classical Assumptions
The Gauss-Markov assumptions for OLS include:
- Linearity: The relationship between and is linear
- Exogeneity: (errors are uncorrelated with explanatory variables)
- Homoskedasticity: (constant error variance)
- No autocorrelation: for (errors are uncorrelated across observations)
- Normality: (required for exact inference in small samples)
When these assumptions hold, OLS is the Best Linear Unbiased Estimator (BLUE); no other linear unbiased estimator has smaller variance. This optimality result justifies the widespread use of OLS. However, when assumptions are violated, the BLUE property fails, and either the estimates themselves become biased or the standard errors become unreliable.
Heteroskedasticity
Heteroskedasticity occurs when the error variance changes across observations. In finance, this is common: volatility varies over time, as we explored in Chapter 18 on GARCH models. Periods of market stress have higher return volatility than calm periods. The variance of returns during the 2008 financial crisis was many times higher than during the calm period of 2005-2006. This time-varying volatility directly translates into heteroskedastic errors in regression models.
Heteroskedasticity doesn't bias the coefficient estimates, but it makes the standard errors incorrect, invalidating hypothesis tests. The OLS formula for standard errors assumes constant variance, so when variance varies, these standard errors are wrong. They might be too small (leading to false positives) or too large (leading to false negatives), depending on the pattern of heteroskedasticity.
# Create data with heteroskedasticity (volatility increases with market magnitude)
np.random.seed(123)
market_het = np.random.normal(0.0004, 0.012, 500)
# Error variance increases with absolute market return
heterosked_errors = np.random.normal(0, 0.01 + 0.5 * np.abs(market_het), 500)
stock_het = 0.0001 + 1.2 * market_het + heterosked_errors
# Fit regression
X_het = sm.add_constant(market_het)
model_het = sm.OLS(stock_het, X_het).fit()
residuals_het = model_het.residThe Breusch-Pagan test formally tests for heteroskedasticity by regressing squared residuals on the explanatory variables:
from statsmodels.stats.diagnostic import het_breuschpagan
# Breusch-Pagan test
bp_stat, bp_pval, _, _ = het_breuschpagan(model_het.resid, model_het.model.exog)Breusch-Pagan Test for Heteroskedasticity: Test statistic: 5.5053 p-value: 0.0190
The low p-value indicates we reject the null hypothesis of homoskedasticity, confirming the presence of time-varying volatility in our synthetic data.
Let's visualize heteroskedasticity by plotting residuals against fitted values:


Autocorrelation
Autocorrelation occurs when errors are correlated across time periods. This is particularly problematic in financial time series because returns often exhibit short-term momentum or mean-reversion patterns in their volatility. When today's error is correlated with yesterday's error, the observations are not truly independent. This reduces the effective sample size: 500 correlated observations contain less information than 500 independent observations.
The Durbin-Watson statistic tests for first-order autocorrelation:
where:
- : Durbin-Watson statistic
- : residual at time
- : number of observations
The numerator sums squared differences between adjacent residuals. If errors are positively correlated, , making the differences small and low (closer to 0). If errors are uncorrelated, the differences are as large as the errors themselves, and the expected value is 2. If errors are negatively correlated, consecutive residuals tend to have opposite signs, making the differences large and high (closer to 4).
Values near 2 indicate no autocorrelation, values below 2 indicate positive autocorrelation, and values above 2 indicate negative autocorrelation.
from statsmodels.stats.stattools import durbin_watson
# Generate data with autocorrelated errors
np.random.seed(456)
market_ac = np.random.normal(0.0004, 0.012, 500)
# Create AR(1) errors with persistence parameter 0.3
ar_coef = 0.3
errors_ac = np.zeros(500)
errors_ac[0] = np.random.normal(0, 0.015)
for t in range(1, 500):
errors_ac[t] = ar_coef * errors_ac[t - 1] + np.random.normal(0, 0.015)
true_beta_ac = 1.2
stock_ac = 0.0001 + true_beta_ac * market_ac + errors_ac
# Fit regression
X_ac = sm.add_constant(market_ac)
model_ac = sm.OLS(stock_ac, X_ac).fit()
# Durbin-Watson test
dw_stat = durbin_watson(model_ac.resid)
dw_original = durbin_watson(model.resid)Durbin-Watson Test for Autocorrelation: Autocorrelated data: DW statistic: 1.4305 Original data (no autocorrelation): DW statistic: 1.9979
The Durbin-Watson statistic differs significantly from 2 in the autocorrelated sample, signaling the presence of serial correlation.
We can also examine the autocorrelation function of the residuals:


Multicollinearity
Multicollinearity arises when explanatory variables are highly correlated with each other. While not strictly a violation of OLS assumptions, it inflates standard errors and makes coefficient estimates unstable. The fundamental problem is identification: when two variables move together, it becomes difficult to determine which one is driving the effect. Mathematically, the matrix approaches singularity, making its inverse unstable.
The Variance Inflation Factor (VIF) quantifies multicollinearity:
where:
- : Variance Inflation Factor for variable
- : R-squared from regressing variable on all other explanatory variables
If variable is highly correlated with other predictors, approaches 1, causing the denominator to approach zero and to become very large. This mathematically quantifies how much the variance of the estimated coefficient is inflated due to collinearity. A VIF of 5 means the variance is five times what it would be if the variable were uncorrelated with other predictors, making the standard error about 2.2 times larger.
A VIF above 5 or 10 suggests problematic multicollinearity.
from statsmodels.stats.outliers_influence import variance_inflation_factor
# Create correlated factors (simulating market, size, and value factors)
np.random.seed(789)
n = 500
# Market factor
factor_market = np.random.normal(0.0004, 0.012, n)
# Size factor (moderately correlated with market)
factor_size = 0.5 * factor_market + np.random.normal(0, 0.008, n)
# Value factor (slightly correlated with both)
factor_value = (
0.3 * factor_market + 0.2 * factor_size + np.random.normal(0, 0.006, n)
)
# Create DataFrame
factors_df = pd.DataFrame(
{"market": factor_market, "size": factor_size, "value": factor_value}
)
# Add constant
X_multi = sm.add_constant(factors_df)
# Calculate VIF for each variable
vif_data = pd.DataFrame()
vif_data["Variable"] = X_multi.columns
vif_data["VIF"] = [
variance_inflation_factor(X_multi.values, i)
for i in range(X_multi.shape[1])
]Variance Inflation Factors:
------------------------------
market : 2.02
size : 1.63
value : 1.82
Correlation matrix of factors:
market size value
market 1.000 0.593 0.646
size 0.593 1.000 0.528
value 0.646 0.528 1.000