1"""F2-conf-03: Monte Carlo coverage of OLS CIs under heteroskedasticity (fixed design)."""2import json, os3import numpy as np, pandas as pd4from scipy import stats56ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))7df = pd.read_csv(os.path.join(ROOT, "data", "design.csv"))8issues = []9if df[["x", "sigma"]].isna().any().any():10 issues.append({"issue": "missing values", "handling": "none expected; would abort"})11if (df["sigma"] <= 0).any():12 issues.append({"issue": "non-positive sigma", "handling": "flagged"})13if len(df) != 30 or not np.array_equal(df["i"].values, np.arange(1, 31)):14 issues.append({"issue": "row count/index not 1..30", "handling": "flagged"})1516ALPHA, BETA, R, SEED = 1.0, 0.5, 2000, 2026103017x = df["x"].to_numpy(float); sig = df["sigma"].to_numpy(float); n = len(x)18X = np.column_stack([np.ones(n), x])19XtXi = np.linalg.inv(X.T @ X)20A = XtXi @ X.T # (2, n): beta_hat = A @ y21tcrit = stats.t.ppf(0.975, n - 2)2223# (c) exact sd: Var(beta_hat) = sum_i a_i^2 sigma_i^2, a_i = (x_i - xbar)/Sxx24sd_exact = float(np.sqrt(np.sum(A[1] ** 2 * sig ** 2)))2526rng = np.random.default_rng(SEED)27eps = rng.standard_normal((R, n))28Y = ALPHA + BETA * x + sig * eps # (R, n)29B = Y @ A.T # (R, 2)30resid = Y - B @ X.T31s2 = (resid ** 2).sum(1) / (n - 2)32se_conv = np.sqrt(s2 * XtXi[1, 1])33hc0 = (resid ** 2) @ (A[1] ** 2) # sandwich variance for slope34se_hc1 = np.sqrt(hc0 * n / (n - 2))35bh = B[:, 1]36cov_conv = float(np.mean(np.abs(bh - BETA) <= tcrit * se_conv))37cov_hc1 = float(np.mean(np.abs(bh - BETA) <= tcrit * se_hc1))38mcse = float(np.sqrt(0.95 * 0.05 / R))39res = {40 "task_id": "F2-conf-03",41 "coverage_conventional": cov_conv,42 "coverage_hc1": cov_hc1,43 "sd_beta_exact": sd_exact,44 "sd_beta_mc": float(np.std(bh, ddof=1)),45 "mean_se_conventional": float(se_conv.mean()),46 "conventional_ci_undercovers": bool(cov_conv < 0.95 - 3 * mcse),47 "n_replications": R,48 "n_obs_per_replication": n,49 "feasibility": "complete",50 "feasibility_reason": None,51 "data_issues": issues,52 "n_input_rows": {"design.csv": int(len(df))},53 "random_seed": SEED,54 # auxiliary55 "mcse_binomial_at_095": mcse,56 "mcse_coverage_conventional": float(np.sqrt(cov_conv * (1 - cov_conv) / R)),57 "mcse_coverage_hc1": float(np.sqrt(cov_hc1 * (1 - cov_hc1) / R)),58 "mean_se_hc1": float(se_hc1.mean()),59 # sqrt of exact E[s^2]*(X'X)^-1_22, E[s^2] = tr(M Sigma)/(n-2); upper bound for E[se_conv] (Jensen)60 "sqrt_exact_E_var_conv": float(np.sqrt(np.trace((np.eye(n) - X @ A) @ np.diag(sig**2)) / (n - 2) * XtXi[1, 1])),61 "t_crit": float(tcrit),62}63with open(os.path.join(ROOT, "out", "results.json"), "w") as f:64 json.dump(res, f, indent=2)65print(json.dumps(res, indent=2))66