Solution: Stock Beta via OLS — Numerical Example
Exercise: Stock Beta via OLS: Numerical Example
Parts 1–3
import numpy as np
rng = np.random.default_rng(0)
T = 504
r_m = 0.0005 + 0.012 * rng.standard_normal(T)
eps = 0.01 * rng.standard_normal(T)
r_s = 0.0001 + 1.3 * r_m + eps
# OLS estimates
m_bar, s_bar = r_m.mean(), r_s.mean()
beta_hat = np.sum((r_m - m_bar)*(r_s - s_bar)) / np.sum((r_m - m_bar)**2)
alpha_hat = s_bar - beta_hat * m_bar
print(f"alpha_hat = {alpha_hat:.5f} (true: 0.0001)")
print(f"beta_hat = {beta_hat:.3f} (true: 1.3)")
# alpha_hat = 0.00014 (true: 0.0001)
# beta_hat = 1.322 (true: 1.3)
# residual noise estimate
residuals = r_s - alpha_hat - beta_hat * r_m
sigma_hat = np.sqrt(np.sum(residuals**2) / (T - 2))
print(f"sigma_hat = {sigma_hat:.5f} (true: 0.01)")
# sigma_hat = 0.00989 (true: 0.01)
# SE of beta_hat
SE_beta = sigma_hat / np.sqrt(np.sum((r_m - m_bar)**2))
print(f"SE(beta) = {SE_beta:.3f}")
# SE(beta) = 0.037
# 95% CI
CI = (beta_hat - 1.96 * SE_beta, beta_hat + 1.96 * SE_beta)
print(f"95% CI = [{CI[0]:.3f}, {CI[1]:.3f}]")
# 95% CI = [1.249, 1.394]with 95% CI .
Part 4
-
Beta vs 1.0: CI does not contain . We reject the null "beta = 1" at 5% significance. The stock has a statistically significant "high beta" character.
-
Beta vs 1.3: CI contains . We do not reject the null "beta = 1.3"; the estimate is consistent with the true value.
Minimum to distinguish from at 5%. We need , i.e. . Using with , :
So roughly trading days suffice to distinguish from at 5% significance — about 6 weeks of data. In practice this number is often much higher due to autocorrelation in returns (Newey-West correction inflates SE) and regime changes.
Takeaways
- OLS delivers consistent, unbiased estimates under i.i.d. gaussian noise — with standard errors matching the closed-form formula.
- SE of beta shrinks as and as . More data and higher market volatility both tighten the estimate. This is why regressions on calm periods are noisier than on volatile ones.
- Beta estimates have non-trivial uncertainty. A 2-year estimate with SE means "beta could plausibly be anywhere from 1.25 to 1.4." This matters in risk budgeting; don't treat as exact.
- Real-world beta estimation is harder. Autocorrelated returns, time-varying beta, outliers, and non-gaussian tails all break the Gauss-Markov assumptions. Robust regression, rolling windows, and Kalman filtering are the standard fixes.