Arte SheetsLearn. Try. Understand.

Econometrics & Causal Inference

Durbin-Wu-Hausman Control-Function Residual Endogeneity Test

Test regressor endogeneity in Excel and Arte Sheets by augmenting the structural equation with first-stage IV residuals v_hat = X - X_hat and computing the exact DWH t- and F-statistics.

Turn endogeneity testing into a transparent first-stage residual check

Instead of inverting singular covariance matrices, the Durbin-Wu-Hausman (DWH) control-function regression tests whether regressor X is endogenous in two transparent steps: (1) regress X on exogenous instrument Z to extract first-stage fitted values X_hat and reduced-form residuals v_hat = X - X_hat; (2) estimate the augmented regression Y = alpha + beta_CF * X + phi_CF * v_hat + e. Remarkably, beta_CF numerically equals the exact 2SLS slope, and testing H_0: phi_CF = 0 tests whether OLS (beta_OLS) differs systematically from 2SLS!

Verify on a 6-unit dataset where Z = {-3, -2, -1, 1, 2, 3} (B2:B7), X = {-5, -6, -1, 3, 2, 7} (C2:C7), and Y = {3, -2, 11, 17, 10, 21} (D2:D7). First-stage slope is 2.0000, leaving v_hat = {1, -2, 1, 1, -2, 1} with SS_v = 12. Naive OLS gives upward-biased beta_OLS = 204 / 124 = 1.6452, whereas 2SLS and the control function recover exact structural beta_2SLS = 1.5000 with residual endogeneity loading phi_CF = 1.5000, SE(phi_CF) = SQRT(31 / 252) = 0.3507, and t_DWH = 4.2767 (F_DWH = 18.2903)!

Estimator / DiagnosticSpreadsheet RelationshipVerified Result
Naive OLS Slope (beta_OLS)SLOPE(Y, X)1.6452 (Endogeneity Bias)
Consistent 2SLS / CF Slope (beta_2SLS)COV(Z, Y) / COV(Z, X)1.5000 (True Causal Slope)
Control-Function Loading (phi_CF)Slope on v_hat controlling for X1.5000
DWH Endogeneity t-Statisticphi_CF / SE(phi_CF) (df = N - 3 = 3)4.2767 (F = 18.2903)

Control-Function Residual Loading phi_CF and 2SLS Slope Formula

Because X_hat and v_hat = X - X_hat are orthogonal by OLS normal equations, SS_Xhat = pi_1^2 * SS_Z, SS_v = SS_X - SS_Xhat, and COV(v_hat, Y) = COV(X, Y) - pi_1 * COV(Z, Y) — giving an exact closed-form phi_CF = (S_vY / SS_v) - beta_2SLS using pure scalar SUMPRODUCT and VAR_P moments!

=LET(z_col, B2:B7, x_col, C2:C7, y_col, D2:D7, n_obs, ROWS(z_col), ss_z, VAR_P(z_col) * n_obs, IF(ss_z <= 1E-9, "Invalid DWH Design", LET(pi_1, SLOPE(x_col, z_col), ss_x, VAR_P(x_col) * n_obs, ss_xh, pi_1^2 * ss_z, ss_v, ss_x - ss_xh, IF(OR(ss_xh <= 1E-9, ss_v <= 1E-9), "Invalid DWH Design", LET(b_2sls, SLOPE(y_col, z_col) / pi_1, s_xy, SUMPRODUCT(x_col, y_col) - n_obs * AVERAGE(x_col) * AVERAGE(y_col), s_zy, SUMPRODUCT(z_col, y_col) - n_obs * AVERAGE(z_col) * AVERAGE(y_col), gam_v, (s_xy - pi_1 * s_zy) / ss_v, ROUND(gam_v - b_2sls, 4))))))

Exact Durbin-Wu-Hausman Endogeneity t-Statistic Formula

Use a hint-first prompt when checking degrees of freedom: "Explain why augmenting Y on X with v_hat uses df = N - 3 = 3 in a bivariate IV model and why Var(phi_CF) = s^2 * (1/SS_v + 1/SS_Xhat)."

=LET(z_col, B2:B7, x_col, C2:C7, y_col, D2:D7, n_obs, ROWS(z_col), ss_z, VAR_P(z_col) * n_obs, IF(OR(n_obs <= 3, ss_z <= 1E-9), "Invalid DWH Design", LET(pi_1, SLOPE(x_col, z_col), ss_x, VAR_P(x_col) * n_obs, ss_y, VAR_P(y_col) * n_obs, ss_xh, pi_1^2 * ss_z, ss_v, ss_x - ss_xh, IF(OR(ss_xh <= 1E-9, ss_v <= 1E-9), "Invalid DWH Design", LET(b_2sls, SLOPE(y_col, z_col) / pi_1, s_xy, SUMPRODUCT(x_col, y_col) - n_obs * AVERAGE(x_col) * AVERAGE(y_col), s_zy, SUMPRODUCT(z_col, y_col) - n_obs * AVERAGE(z_col) * AVERAGE(y_col), gam_v, (s_xy - pi_1 * s_zy) / ss_v, phi_cf, gam_v - b_2sls, sse_cf, MAX(0, ss_y - b_2sls^2 * ss_xh - gam_v^2 * ss_v), s2_cf, sse_cf / (n_obs - 3), se_phi, SQRT(s2_cf * (1 / ss_v + 1 / ss_xh)), ROUND(phi_cf / se_phi, 4))))))

Try the example

Use the original values or change them to test your understanding.

Further reading