diff --git a/analysis/PERSISTENCE_BACKTEST.md b/analysis/PERSISTENCE_BACKTEST.md new file mode 100644 index 0000000..8057fd4 --- /dev/null +++ b/analysis/PERSISTENCE_BACKTEST.md @@ -0,0 +1,27 @@ + + +# Distributional backtest of next-year rate predictions + +Expanding-window backtest over target years 2016-2024 (FY2021 dropped), 424 state-years per construction, reconstructed-rate scale. + +| construction | mean CRPS | pinball | log score | 50% cover | 90% cover | mean SD | +|---|---:|---:|---:|---:|---:|---:| +| static | 0.9914 | 0.5117 | -4.7344 | 0.1981 | 0.4835 | 0.5706pp | +| static_fair | 0.9426 | 0.4896 | -2.8617 | 0.3066 | 0.6415 | 0.8069pp | +| widened | 0.9003 | 0.4701 | -2.0101 | 0.4646 | 0.8137 | 1.2005pp | +| rao_yu | 0.8778 | 0.4587 | -1.9318 | 0.4953 | 0.8491 | 1.2908pp | +| static_official_1p1 (sensitivity) | 0.911 | 0.4749 | -2.2021 | 0.4151 | 0.7807 | 1.1pp | +| static_fair_official_1p1 (sensitivity) | 0.9009 | 0.4709 | -1.9547 | 0.5778 | 0.9009 | 1.5556pp | + +The sampling-only construction's nominal 90% intervals cover 48% of realized next-year rates; adding persistence terms to the variance alone lifts coverage to 81% at about double the predictive width, and the full model reaches 85%. Winners by year sit in the artifact; the full model's edge concentrates in large-movement years. + +## In bill terms + +Pricing bills with the simulator's election semantics (FY 2028 keys to the elected minimum of the locked FY 2025 rate and the simulated FY 2026 measurement, zero when either crosses the delay test; FY 2029 keys to FY 2026 alone): the median state's FY 2029 most-likely-bucket probability falls from 0.8377 under sampling-only to 0.5883 with persistence in the variance. National FY 2028 bill SD: $782,146,777 static versus $907,069,987 widened; FY 2029: $837,370,254 versus $1,007,179,598 (no cross-state correlation modeled). + +## Caveats + +- Reconstructed rates at the fixed real threshold, not official rates; sampling variances are the i.i.d. cell bootstrap, which runs smaller than published design SEs (~1.1pp average) — the sensitivity rows rerun the static family at that scale. +- The penalty translation's innovation variance is estimated on the reconstructed panel and applied to official-scale rates: the additive-wedge evidence supports transferring level shifts in percentage points; extending the transfer to a variance component is an additional stated assumption. +- All three constructions carry the national year level from the last observed year, so common national shifts handicap each equally and depress all coverage numbers together. +- Normal predictive forms throughout; the bootstrap-vs-normal tier-odds gap is second-order at state sample sizes. diff --git a/analysis/persistence_backtest.py b/analysis/persistence_backtest.py new file mode 100644 index 0000000..f0ab3aa --- /dev/null +++ b/analysis/persistence_backtest.py @@ -0,0 +1,417 @@ +"""Backtest: which predictive distribution for next-year state rates scores best. + +Three constructions, each producing Normal(mean, sd) per state-year and fit +only on years before the target (expanding window, FY2021 dropped per the +coding audit): + + static : mean = last year's rate; var = mean cell sampling variance + (the published-CI construction repurposed as a forecast) + widened : mean = last year's rate; var = sampling + AR(1) innovation + (no shrinkage; persistence enters the variance only) + rao_yu : mean = year level + BLUP; var = conditional process + sampling + (the full persistence model) + +The national year level is carried from the last observed year for all three +constructions identically, so common national shifts handicap each equally. +Scores: CRPS (normal closed form), pinball loss over 19 quantiles, log +score, and central-interval coverage. Reconstructed-rate scale throughout. +This evaluates distributional calibration and sharpness; it makes no claim +about any construction's fitness for its authors' own question. +""" + +from __future__ import annotations + +import hashlib +import json +import platform +import sys +from pathlib import Path +from typing import Any + +import numpy as np +from scipy import stats + +from analysis import event_study, persistence +from snap_qc_sim.simulate import tier_of + +OUT = Path(__file__).with_name("persistence_backtest_results.json") +MOVEMENT_PATH = Path(__file__).with_name("fy2025_movement.json") +ISSUANCE_PATH = Path(__file__).with_name("issuance_fy2024.json") +PERSISTENCE_RESULTS = Path(__file__).with_name("persistence_results.json") +BILL_DRAWS = 20_000 +MEMO_OUT = Path(__file__).with_name("PERSISTENCE_BACKTEST.md") +APPROACHES = ("static", "static_fair", "widened", "rao_yu") +#: Sensitivity rows at the published average design-SE scale (~1.1pp, +#: Bauer-Schanzenbach 2026); per-state official SEs are not in the repo. +SENSITIVITY = ("static_official_1p1", "static_fair_official_1p1") +OFFICIAL_SE_PP = 1.1 +QS = np.round(np.arange(0.05, 0.951, 0.05), 2) +MIN_HISTORY_YEARS = 4 + + +def raw_inputs_available() -> bool: + return persistence.raw_inputs_available() + + +def _crps_normal(y: float, mu: float, sd: float) -> float: + z = (y - mu) / sd + return float( + sd + * (z * (2 * stats.norm.cdf(z) - 1) + 2 * stats.norm.pdf(z) - 1 / np.sqrt(np.pi)) + ) + + +def _pinball(y: float, mu: float, sd: float) -> float: + q = mu + sd * stats.norm.ppf(QS) + return float(np.mean(np.where(y >= q, QS * (y - q), (1 - QS) * (q - y)))) + + +def compute_artifact() -> dict[str, Any]: + wide = persistence.build_rate_panel() + rng = np.random.default_rng(persistence.SEED) + v = persistence.cell_sampling_variances(rng).reindex( + index=wide.index, columns=wide.columns + ) + years = list(wide.columns) + rows: dict[str, list[dict[str, Any]]] = {k: [] for k in (*APPROACHES, *SENSITIVITY)} + fits_by_target: dict[str, dict[str, float]] = {} + for target in years: + hist = [y for y in years if y < target] + if len(hist) < MIN_HISTORY_YEARS: + continue + history = wide[hist] + vh = v[hist] + x = history.sub(history.mean(axis=0), axis=1) + c, counts, mean_v = persistence.autocovariances(x, vh) + fit = persistence.fit_components(c, counts, mean_v) + a, b, rho = fit["sigma_alpha_sq"], fit["sigma_u_sq"], fit["rho"] + fits_by_target[str(target)] = { + "sigma_alpha_sq": round(a, 4), + "sigma_u_sq": round(b, 4), + "rho": rho, + } + mu_last = float(history[hist[-1]].mean()) + gap = target - hist[-1] + innovation = b * (1 - rho ** (2 * gap)) + for state in wide.index: + y_true = float(wide.loc[state, target]) + vbar = float(vh.loc[state].mean()) + y_prev = float(history.loc[state, hist[-1]]) + cov = persistence._state_covariance(hist, fit, vh.loc[state]) + gaps = np.abs(np.array(hist, float) - target) + cross = a + b * rho**gaps + weights = np.linalg.solve(cov, cross) + mean_cond = float(weights @ x.loc[state].to_numpy()) + var_cond = float(max(a + b - cross @ weights, 0.0)) + preds = { + "static": (y_prev, float(np.sqrt(vbar))), + # Fair static: predicting T from the T-1 value involves two + # sampling draws (the anchor's and the target's). + "static_fair": (y_prev, float(np.sqrt(2 * vbar))), + "widened": (y_prev, float(np.sqrt(vbar + innovation))), + "rao_yu": (mu_last + mean_cond, float(np.sqrt(var_cond + vbar))), + "static_official_1p1": (y_prev, OFFICIAL_SE_PP), + "static_fair_official_1p1": ( + y_prev, + float(OFFICIAL_SE_PP * np.sqrt(2)), + ), + } + for name, (mu, sd) in preds.items(): + z = abs(y_true - mu) + rows[name].append( + { + "target_year": target, + "state": state, + "crps": round(_crps_normal(y_true, mu, sd), 6), + "pinball": round(_pinball(y_true, mu, sd), 6), + "log_score": round(float(stats.norm.logpdf(y_true, mu, sd)), 6), + "in_50": bool(z <= 0.674 * sd), + "in_90": bool(z <= 1.645 * sd), + "predictive_sd_pp": round(sd, 4), + } + ) + + def summary(cells: list[dict[str, Any]]) -> dict[str, Any]: + arr = lambda key: np.array([c[key] for c in cells], dtype=float) + return { + "n_state_years": len(cells), + "mean_crps": round(float(arr("crps").mean()), 4), + "mean_pinball": round(float(arr("pinball").mean()), 4), + "mean_log_score": round(float(arr("log_score").mean()), 4), + "coverage_50": round(float(arr("in_50").mean()), 4), + "coverage_90": round(float(arr("in_90").mean()), 4), + "mean_predictive_sd_pp": round(float(arr("predictive_sd_pp").mean()), 4), + } + + penalty = penalty_translation(np.random.default_rng(persistence.SEED + 1)) + + per_year = {} + targets = sorted({c["target_year"] for c in rows["static"]}) + for t in targets: + per_year[str(t)] = { + k: round( + float(np.mean([c["crps"] for c in rows[k] if c["target_year"] == t])), 4 + ) + for k in APPROACHES + } + per_year[str(t)]["winner"] = min(APPROACHES, key=lambda k: per_year[str(t)][k]) + + return { + "schema_version": 1, + "interpretation": ( + "expanding-window distributional backtest on reconstructed state " + "rates; scores calibration and sharpness of three Normal " + "predictive constructions for next-year rates; the national year " + "level is carried identically for all three; no claim about any " + "construction's fitness for its authors' own question" + ), + "target_years": targets, + "summary": {k: summary(rows[k]) for k in APPROACHES}, + "sensitivity_official_se_scale": {k: summary(rows[k]) for k in SENSITIVITY}, + "per_year_mean_crps": per_year, + "penalty_translation": penalty, + "fits_by_target_year": fits_by_target, + "quantile_grid": [float(q) for q in QS], + "min_history_years": MIN_HISTORY_YEARS, + "environment": { + "python": sys.version.split()[0], + "platform": platform.platform(), + "numpy": np.__version__, + "seed": persistence.SEED, + }, + "input_hashes": { + "coding_consistency": hashlib.sha256( + event_study.AUDIT_PATH.read_bytes() + ).hexdigest(), + "fy2025_movement": hashlib.sha256(MOVEMENT_PATH.read_bytes()).hexdigest(), + "issuance_fy2024": hashlib.sha256(ISSUANCE_PATH.read_bytes()).hexdigest(), + "persistence_results": hashlib.sha256( + PERSISTENCE_RESULTS.read_bytes() + ).hexdigest(), + "raw_by_fiscal_year": { + str(y): json.loads(event_study.AUDIT_PATH.read_text())["years"][str(y)][ + "source" + ]["sha256"] + for y in persistence.YEARS_USED + }, + }, + } + + +def penalty_translation(rng: np.random.Generator) -> dict[str, Any]: + """Election-correct FY2028 and FY2029 bill pricing per state. + + Semantics mirror the simulator's verified election machinery + (app/public/app.js electionStats, 7 USC 2013(a)(2)(B)): the FY2028 + bill keys to the elected minimum of the locked FY2025 official rate + and the simulated FY2026 measurement, and pays zero whenever EITHER + year crosses the delay test (rate x 1.5 >= 20, mechanical and + election-independent); the FY2029 bill keys to the FY2026 rate alone + and pays zero when FY2026 itself crosses. FY2026 draws center on the + locked FY2025 official rate under two constructions: static (the + state's sampling SD) and widened (sampling variance plus the + committed persistence fit's one-year AR(1) innovation, no + shrinkage). The innovation variance is estimated on the + reconstructed-rate panel and applied to official-scale rates; the + additive-wedge result supports transferring level shifts in + percentage points, and extending that transfer to a variance + component is an additional stated assumption. State draws are + independent; the national SD models no cross-state correlation. + """ + movement = json.loads(MOVEMENT_PATH.read_text()) + issuance = json.loads(ISSUANCE_PATH.read_text())["states"] + fit = json.loads(PERSISTENCE_RESULTS.read_text())["fit"] + innovation = fit["sigma_u_sq_pp2"] * (1 - fit["rho"] ** 2) + delay = lambda r: r * 1.5 >= 20 + states: dict[str, Any] = {} + totals: dict[str, dict[str, list[tuple[float, float]]]] = { + "static": {"fy2028": [], "fy2029": []}, + "widened": {"fy2028": [], "fy2029": []}, + } + for row in sorted(movement["states"], key=lambda r: r["state"]): + code = row["state"] + dollars = issuance.get(code) + if dollars is None: + continue + fy25, sd0 = row["fy2025"], row["sampling_sd_fy2024_pp"] + lock_share = 0.0 if delay(fy25) else float(tier_of(fy25)) + out: dict[str, Any] = { + "fy2025_official": fy25, + "fy2025_delay": bool(delay(fy25)), + "issuance_fy2024_dollars": dollars, + } + for name, sd in ( + ("static", sd0), + ("widened", float(np.sqrt(sd0**2 + innovation))), + ): + draws = np.clip(fy25 + rng.standard_normal(BILL_DRAWS) * sd, 0.0, None) + crossed = draws * 1.5 >= 20 + zero28 = delay(fy25) | crossed + elected = np.minimum(draws, fy25) + share28 = np.where(zero28, 0.0, np.array([tier_of(r) for r in elected])) + share29 = np.where(crossed, 0.0, np.array([tier_of(r) for r in draws])) + bill28 = share28 / 100 * dollars + bill29 = share29 / 100 * dollars + p_bucket_29 = { + **{ + str(s): round(float(((share29 == s) & ~crossed).mean()), 4) + for s in (0, 5, 10, 15) + }, + "delay_0": round(float(crossed.mean()), 4), + } + out[name] = { + "predictive_sd_pp": round(sd, 4), + "fy2028": { + "expected_bill_dollars": round(float(bill28.mean())), + "sd_bill_dollars": round(float(bill28.std())), + }, + "fy2029": { + "p_bucket": p_bucket_29, + "modal_bucket_probability": round(max(p_bucket_29.values()), 4), + "expected_bill_dollars": round(float(bill29.mean())), + "sd_bill_dollars": round(float(bill29.std())), + }, + } + totals[name]["fy2028"].append((float(bill28.mean()), float(bill28.var()))) + totals[name]["fy2029"].append((float(bill29.mean()), float(bill29.var()))) + out["lock_share_pct"] = lock_share + states[code] = out + national = { + name: { + year: { + "expected_total_dollars": round(sum(m for m, _ in vals)), + "sd_total_dollars_no_correlation": round( + float(np.sqrt(sum(vv for _, vv in vals))) + ), + } + for year, vals in years.items() + } + for name, years in totals.items() + } + modal_med = { + name: round( + float( + np.median( + [ + s[name]["fy2029"]["modal_bucket_probability"] + for s in states.values() + ] + ) + ), + 4, + ) + for name in ("static", "widened") + } + return { + "innovation_variance_pp2": round(float(innovation), 4), + "states": states, + "national": national, + "median_modal_bucket_probability_fy2029": modal_med, + } + + +def _memo(a: dict[str, Any]) -> str: + s = a["summary"] + lines = [ + "", + "", + "# Distributional backtest of next-year rate predictions", + "", + ( + f"Expanding-window backtest over target years " + f"{a['target_years'][0]}-{a['target_years'][-1]} (FY2021 dropped), " + f"{s['static']['n_state_years']} state-years per construction, " + "reconstructed-rate scale." + ), + "", + "| construction | mean CRPS | pinball | log score | 50% cover | 90% cover | mean SD |", + "|---|---:|---:|---:|---:|---:|---:|", + ] + for k in APPROACHES: + r = s[k] + lines.append( + f"| {k} | {r['mean_crps']} | {r['mean_pinball']} | " + f"{r['mean_log_score']} | {r['coverage_50']} | {r['coverage_90']} | " + f"{r['mean_predictive_sd_pp']}pp |" + ) + for k in SENSITIVITY: + r = a["sensitivity_official_se_scale"][k] + lines.append( + f"| {k} (sensitivity) | {r['mean_crps']} | {r['mean_pinball']} | " + f"{r['mean_log_score']} | {r['coverage_50']} | {r['coverage_90']} | " + f"{r['mean_predictive_sd_pp']}pp |" + ) + lines += [ + "", + ( + "The sampling-only construction's nominal 90% intervals cover " + f"{round(100 * s['static']['coverage_90'])}% of realized next-year " + "rates; adding persistence terms to the variance alone lifts " + f"coverage to {round(100 * s['widened']['coverage_90'])}% at about " + "double the predictive width, and the full model reaches " + f"{round(100 * s['rao_yu']['coverage_90'])}%. Winners by year sit " + "in the artifact; the full model's edge concentrates in " + "large-movement years." + ), + "", + "## In bill terms", + "", + ( + f"Pricing bills with the simulator's election semantics " + f"(FY 2028 keys to the elected minimum of the locked FY 2025 " + f"rate and the simulated FY 2026 measurement, zero when either " + f"crosses the delay test; FY 2029 keys to FY 2026 alone): the " + f"median state's FY 2029 most-likely-bucket probability falls " + f"from " + f"{a['penalty_translation']['median_modal_bucket_probability_fy2029']['static']} " + f"under sampling-only to " + f"{a['penalty_translation']['median_modal_bucket_probability_fy2029']['widened']} " + f"with persistence in the variance. National FY 2028 bill SD: " + f"${a['penalty_translation']['national']['static']['fy2028']['sd_total_dollars_no_correlation']:,} " + f"static versus " + f"${a['penalty_translation']['national']['widened']['fy2028']['sd_total_dollars_no_correlation']:,} " + f"widened; FY 2029: " + f"${a['penalty_translation']['national']['static']['fy2029']['sd_total_dollars_no_correlation']:,} " + f"versus " + f"${a['penalty_translation']['national']['widened']['fy2029']['sd_total_dollars_no_correlation']:,} " + "(no cross-state correlation modeled)." + ), + "", + "## Caveats", + "", + ( + "- Reconstructed rates at the fixed real threshold, not official " + "rates; sampling variances are the i.i.d. cell bootstrap, which " + "runs smaller than published design SEs (~1.1pp average) — the " + "sensitivity rows rerun the static family at that scale." + ), + ( + "- The penalty translation's innovation variance is estimated on " + "the reconstructed panel and applied to official-scale rates: " + "the additive-wedge evidence supports transferring level shifts " + "in percentage points; extending the transfer to a variance " + "component is an additional stated assumption." + ), + ( + "- All three constructions carry the national year level from the " + "last observed year, so common national shifts handicap each " + "equally and depress all coverage numbers together." + ), + ( + "- Normal predictive forms throughout; the bootstrap-vs-normal " + "tier-odds gap is second-order at state sample sizes." + ), + "", + ] + return "\n".join(lines) + + +def main() -> None: + artifact = compute_artifact() + OUT.write_text(json.dumps(artifact, indent=2, sort_keys=True) + "\n") + MEMO_OUT.write_text(_memo(artifact)) + print(f"wrote {OUT} and {MEMO_OUT}") + + +if __name__ == "__main__": + main() diff --git a/analysis/persistence_backtest_results.json b/analysis/persistence_backtest_results.json new file mode 100644 index 0000000..5a9676f --- /dev/null +++ b/analysis/persistence_backtest_results.json @@ -0,0 +1,2583 @@ +{ + "environment": { + "numpy": "2.5.1", + "platform": "macOS-26.5.1-arm64-arm-64bit-Mach-O", + "python": "3.14.4", + "seed": 20260817 + }, + "fits_by_target_year": { + "2016": { + "rho": 0.775, + "sigma_alpha_sq": 0.0, + "sigma_u_sq": 2.0668 + }, + "2017": { + "rho": 0.795, + "sigma_alpha_sq": 0.0, + "sigma_u_sq": 2.2834 + }, + "2018": { + "rho": 0.795, + "sigma_alpha_sq": 0.0, + "sigma_u_sq": 2.5793 + }, + "2019": { + "rho": 0.82, + "sigma_alpha_sq": 0.0, + "sigma_u_sq": 2.8903 + }, + "2020": { + "rho": 0.785, + "sigma_alpha_sq": 0.5027, + "sigma_u_sq": 2.944 + }, + "2022": { + "rho": 0.835, + "sigma_alpha_sq": 0.0, + "sigma_u_sq": 3.6872 + }, + "2023": { + "rho": 0.8, + "sigma_alpha_sq": 0.8188, + "sigma_u_sq": 3.0525 + }, + "2024": { + "rho": 0.73, + "sigma_alpha_sq": 1.6429, + "sigma_u_sq": 2.5268 + } + }, + "input_hashes": { + "coding_consistency": "3b14f64cc8244811d46a90fc7e9bb9ef949cedc0ba5d941bd194ddfe291fdc14", + "fy2025_movement": "11faaf42081f7eca8676c28a7ed3741d26bcbb46eb6b63c40744fefad82cfd7c", + "issuance_fy2024": "472d944ff48a993944eaa1de655d04cff6a2ded238c6b4267da680353d27c93f", + "persistence_results": "e0c71ea292c6b04da2ab01fda521c594a81705a6b41d98e76c25cbe916b0788b", + "raw_by_fiscal_year": { + "2012": "90968f8f612507a88e1a4e7767f6bc55dba0cb7cffb61766b3de1827c81eb4c0", + "2013": "a2341cb547aed989ca64deb18f79095c0001266c61310f6aded1f0d45cbb4e22", + "2014": "947f290d05c4d949d92f885f43d0fc7c508f288f4ec62737819a47fffc51e9b8", + "2015": "2b2f922eca3188810da93fbcdd0190c198e6d9ecb3efa71c219e0d6023e8a4e3", + "2016": "d5e91c7510456a4e9e14861a7579d80aff6c10687d45095179c87d94c5bcdf00", + "2017": "18e0c7f9b42c26a1c70652d43e461ce0086bdf6749ed7534778bf8f0f5b71ea9", + "2018": "02fcbb4ea4116a162f89e56efc930d1716371a29e0196c551ffd96da72b71e82", + "2019": "0d8302b672529feb87b160d12297fe1adda1703eec0e3a4558f57e278ce12846", + "2020": "8ac8a236e6a99d3b2039e191e6c1891235b0a5c54e3dd518bcc944b4b45ddd08", + "2022": "c795aac12ea67937af3242593280fbc8dd3eb70938f56b7a7badbfd71ac74f5d", + "2023": "9a1028e180028905e55edf3d72f028bc7740acfbc66cad1ccf935c6bb3fd2257", + "2024": "ab6420fa359ab9bcc280a21b9ba7b11172c79c6f7a661718bc6e318f97723fbb" + } + }, + "interpretation": "expanding-window distributional backtest on reconstructed state rates; scores calibration and sharpness of three Normal predictive constructions for next-year rates; the national year level is carried identically for all three; no claim about any construction's fitness for its authors' own question", + "min_history_years": 4, + "penalty_translation": { + "innovation_variance_pp2": 1.1763, + "median_modal_bucket_probability_fy2029": { + "static": 0.8377, + "widened": 0.5883 + }, + "national": { + "static": { + "fy2028": { + "expected_total_dollars": 7834782961, + "sd_total_dollars_no_correlation": 782146777 + }, + "fy2029": { + "expected_total_dollars": 8277014714, + "sd_total_dollars_no_correlation": 837370254 + } + }, + "widened": { + "fy2028": { + "expected_total_dollars": 7174823856, + "sd_total_dollars_no_correlation": 907069987 + }, + "fy2029": { + "expected_total_dollars": 8001522914, + "sd_total_dollars_no_correlation": 1007179598 + } + } + }, + "states": { + "AK": { + "fy2025_delay": true, + "fy2025_official": 23.15, + "issuance_fy2024_dollars": 249618195, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 0, + "modal_bucket_probability": 1.0, + "p_bucket": { + "0": 0.0, + "10": 0.0, + "15": 0.0, + "5": 0.0, + "delay_0": 1.0 + }, + "sd_bill_dollars": 0 + }, + "predictive_sd_pp": 0.8202 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 0, + "modal_bucket_probability": 1.0, + "p_bucket": { + "0": 0.0, + "10": 0.0, + "15": 0.0, + "5": 0.0, + "delay_0": 1.0 + }, + "sd_bill_dollars": 0 + }, + "predictive_sd_pp": 1.3598 + } + }, + "AL": { + "fy2025_delay": false, + "fy2025_official": 9.52, + "issuance_fy2024_dollars": 1733693703, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 173018297, + "sd_bill_dollars": 5505397 + }, + "fy2029": { + "expected_bill_dollars": 190463590, + "modal_bucket_probability": 0.7947, + "p_bucket": { + "0": 0.0, + "10": 0.7947, + "15": 0.2013, + "5": 0.004, + "delay_0": 0.0 + }, + "sd_bill_dollars": 35361844 + }, + "predictive_sd_pp": 0.5748 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 163721365, + "sd_bill_dollars": 27956625 + }, + "fy2029": { + "expected_bill_dollars": 193878967, + "modal_bucket_probability": 0.5433, + "p_bucket": { + "0": 0.0019, + "10": 0.5433, + "15": 0.3479, + "5": 0.1062, + "delay_0": 0.0006 + }, + "sd_bill_dollars": 55391476 + }, + "predictive_sd_pp": 1.2275 + } + }, + "AR": { + "fy2025_delay": false, + "fy2025_official": 8.81, + "issuance_fy2024_dollars": 515343148, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 49981844, + "sd_bill_dollars": 6131281 + }, + "fy2029": { + "expected_bill_dollars": 50242092, + "modal_bucket_probability": 0.9296, + "p_bucket": { + "0": 0.0, + "10": 0.9296, + "15": 0.0101, + "5": 0.0602, + "delay_0": 0.0 + }, + "sd_bill_dollars": 6711094 + }, + "predictive_sd_pp": 0.5204 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 44730497, + "sd_bill_dollars": 11895600 + }, + "fy2029": { + "expected_bill_dollars": 48924102, + "modal_bucket_probability": 0.5826, + "p_bucket": { + "0": 0.0092, + "10": 0.5826, + "15": 0.1628, + "5": 0.2452, + "delay_0": 0.0001 + }, + "sd_bill_dollars": 17001215 + }, + "predictive_sd_pp": 1.203 + } + }, + "AZ": { + "fy2025_delay": false, + "fy2025_official": 10.8, + "issuance_fy2024_dollars": 2015185004, + "lock_share_pct": 15.0, + "static": { + "fy2028": { + "expected_bill_dollars": 286710446, + "sd_bill_dollars": 36943039 + }, + "fy2029": { + "expected_bill_dollars": 286710446, + "modal_bucket_probability": 0.8468, + "p_bucket": { + "0": 0.0, + "10": 0.1525, + "15": 0.8468, + "5": 0.0001, + "delay_0": 0.0006 + }, + "sd_bill_dollars": 36943039 + }, + "predictive_sd_pp": 0.7917 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 263273845, + "sd_bill_dollars": 68549887 + }, + "fy2029": { + "expected_bill_dollars": 263273845, + "modal_bucket_probability": 0.6945, + "p_bucket": { + "0": 0.0002, + "10": 0.2552, + "15": 0.6945, + "5": 0.0191, + "delay_0": 0.0311 + }, + "sd_bill_dollars": 68549887 + }, + "predictive_sd_pp": 1.3428 + } + }, + "CA": { + "fy2025_delay": false, + "fy2025_official": 10.93, + "issuance_fy2024_dollars": 12183085552, + "lock_share_pct": 15.0, + "static": { + "fy2028": { + "expected_bill_dollars": 1742729473, + "sd_bill_dollars": 221024132 + }, + "fy2029": { + "expected_bill_dollars": 1742729473, + "modal_bucket_probability": 0.8649, + "p_bucket": { + "0": 0.0, + "10": 0.1329, + "15": 0.8649, + "5": 0.0003, + "delay_0": 0.0019 + }, + "sd_bill_dollars": 221024132 + }, + "predictive_sd_pp": 0.8292 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 1597933501, + "sd_bill_dollars": 429581954 + }, + "fy2029": { + "expected_bill_dollars": 1597933501, + "modal_bucket_probability": 0.7152, + "p_bucket": { + "0": 0.0001, + "10": 0.2321, + "15": 0.7152, + "5": 0.0135, + "delay_0": 0.0391 + }, + "sd_bill_dollars": 429581954 + }, + "predictive_sd_pp": 1.3652 + } + }, + "CO": { + "fy2025_delay": false, + "fy2025_official": 10.09, + "issuance_fy2024_dollars": 1303172697, + "lock_share_pct": 15.0, + "static": { + "fy2028": { + "expected_bill_dollars": 164844830, + "sd_bill_dollars": 33763617 + }, + "fy2029": { + "expected_bill_dollars": 164844830, + "modal_bucket_probability": 0.5395, + "p_bucket": { + "0": 0.0, + "10": 0.4508, + "15": 0.5395, + "5": 0.0095, + "delay_0": 0.0001 + }, + "sd_bill_dollars": 33763617 + }, + "predictive_sd_pp": 0.9015 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 157348329, + "sd_bill_dollars": 44142245 + }, + "fy2029": { + "expected_bill_dollars": 157348329, + "modal_bucket_probability": 0.5091, + "p_bucket": { + "0": 0.0025, + "10": 0.4107, + "15": 0.5091, + "5": 0.0664, + "delay_0": 0.0114 + }, + "sd_bill_dollars": 44142245 + }, + "predictive_sd_pp": 1.4103 + } + }, + "CT": { + "fy2025_delay": false, + "fy2025_official": 9.08, + "issuance_fy2024_dollars": 892819650, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 84554485, + "sd_bill_dollars": 13765443 + }, + "fy2029": { + "expected_bill_dollars": 90964930, + "modal_bucket_probability": 0.7507, + "p_bucket": { + "0": 0.0002, + "10": 0.7507, + "15": 0.1436, + "5": 0.1055, + "delay_0": 0.0 + }, + "sd_bill_dollars": 22252476 + }, + "predictive_sd_pp": 0.8698 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 78940881, + "sd_bill_dollars": 20226271 + }, + "fy2029": { + "expected_bill_dollars": 90087735, + "modal_bucket_probability": 0.5323, + "p_bucket": { + "0": 0.0128, + "10": 0.5323, + "15": 0.2497, + "5": 0.2044, + "delay_0": 0.0008 + }, + "sd_bill_dollars": 31827618 + }, + "predictive_sd_pp": 1.3903 + } + }, + "DC": { + "fy2025_delay": true, + "fy2025_official": 18.66, + "issuance_fy2024_dollars": 319119173, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 0, + "modal_bucket_probability": 1.0, + "p_bucket": { + "0": 0.0, + "10": 0.0, + "15": 0.0, + "5": 0.0, + "delay_0": 1.0 + }, + "sd_bill_dollars": 0 + }, + "predictive_sd_pp": 1.0358 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 14360, + "modal_bucket_probability": 0.9997, + "p_bucket": { + "0": 0.0, + "10": 0.0, + "15": 0.0003, + "5": 0.0, + "delay_0": 0.9997 + }, + "sd_bill_dollars": 828972 + }, + "predictive_sd_pp": 1.4997 + } + }, + "DE": { + "fy2025_delay": true, + "fy2025_official": 16.0, + "issuance_fy2024_dollars": 254854243, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 3823, + "modal_bucket_probability": 0.9999, + "p_bucket": { + "0": 0.0, + "10": 0.0, + "15": 0.0001, + "5": 0.0, + "delay_0": 0.9999 + }, + "sd_bill_dollars": 382262 + }, + "predictive_sd_pp": 0.6814 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 716778, + "modal_bucket_probability": 0.9812, + "p_bucket": { + "0": 0.0, + "10": 0.0, + "15": 0.0187, + "5": 0.0, + "delay_0": 0.9812 + }, + "sd_bill_dollars": 5185297 + }, + "predictive_sd_pp": 1.2809 + } + }, + "FL": { + "fy2025_delay": false, + "fy2025_official": 12.97, + "issuance_fy2024_dollars": 6548475145, + "lock_share_pct": 15.0, + "static": { + "fy2028": { + "expected_bill_dollars": 680517537, + "sd_bill_dollars": 453154177 + }, + "fy2029": { + "expected_bill_dollars": 680517537, + "modal_bucket_probability": 0.6928, + "p_bucket": { + "0": 0.0, + "10": 0.0, + "15": 0.6928, + "5": 0.0, + "delay_0": 0.3072 + }, + "sd_bill_dollars": 453154177 + }, + "predictive_sd_pp": 0.7176 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 590230436, + "sd_bill_dollars": 478789710 + }, + "fy2029": { + "expected_bill_dollars": 590230436, + "modal_bucket_probability": 0.5942, + "p_bucket": { + "0": 0.0, + "10": 0.01, + "15": 0.5942, + "5": 0.0001, + "delay_0": 0.3957 + }, + "sd_bill_dollars": 478789710 + }, + "predictive_sd_pp": 1.3005 + } + }, + "GA": { + "fy2025_delay": true, + "fy2025_official": 15.21, + "issuance_fy2024_dollars": 3181329856, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 10212069, + "modal_bucket_probability": 0.9786, + "p_bucket": { + "0": 0.0, + "10": 0.0, + "15": 0.0214, + "5": 0.0, + "delay_0": 0.9786 + }, + "sd_bill_dollars": 69057277 + }, + "predictive_sd_pp": 0.9293 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 45445297, + "modal_bucket_probability": 0.9047, + "p_bucket": { + "0": 0.0, + "10": 0.0002, + "15": 0.0951, + "5": 0.0, + "delay_0": 0.9047 + }, + "sd_bill_dollars": 140039552 + }, + "predictive_sd_pp": 1.4283 + } + }, + "GU": { + "fy2025_delay": false, + "fy2025_official": 11.7, + "issuance_fy2024_dollars": 119035771, + "lock_share_pct": 15.0, + "static": { + "fy2028": { + "expected_bill_dollars": 15466615, + "sd_bill_dollars": 5512295 + }, + "fy2029": { + "expected_bill_dollars": 15466615, + "modal_bucket_probability": 0.8052, + "p_bucket": { + "0": 0.0, + "10": 0.0906, + "15": 0.8052, + "5": 0.002, + "delay_0": 0.1022 + }, + "sd_bill_dollars": 5512295 + }, + "predictive_sd_pp": 1.2812 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 13870048, + "sd_bill_dollars": 6659453 + }, + "fy2029": { + "expected_bill_dollars": 13870048, + "modal_bucket_probability": 0.6787, + "p_bucket": { + "0": 0.0004, + "10": 0.1399, + "15": 0.6787, + "5": 0.0143, + "delay_0": 0.1666 + }, + "sd_bill_dollars": 6659453 + }, + "predictive_sd_pp": 1.6786 + } + }, + "HI": { + "fy2025_delay": false, + "fy2025_official": 10.92, + "issuance_fy2024_dollars": 731331421, + "lock_share_pct": 15.0, + "static": { + "fy2028": { + "expected_bill_dollars": 109363301, + "sd_bill_dollars": 3491171 + }, + "fy2029": { + "expected_bill_dollars": 109363301, + "modal_bucket_probability": 0.9908, + "p_bucket": { + "0": 0.0, + "10": 0.0092, + "15": 0.9908, + "5": 0.0, + "delay_0": 0.0 + }, + "sd_bill_dollars": 3491171 + }, + "predictive_sd_pp": 0.3773 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 99667674, + "sd_bill_dollars": 20742694 + }, + "fy2029": { + "expected_bill_dollars": 99667674, + "modal_bucket_probability": 0.7684, + "p_bucket": { + "0": 0.0001, + "10": 0.2074, + "15": 0.7684, + "5": 0.0056, + "delay_0": 0.0185 + }, + "sd_bill_dollars": 20742694 + }, + "predictive_sd_pp": 1.1483 + } + }, + "IA": { + "fy2025_delay": false, + "fy2025_official": 5.34, + "issuance_fy2024_dollars": 528905499, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 3247480, + "modal_bucket_probability": 0.8772, + "p_bucket": { + "0": 0.8772, + "10": 0.0, + "15": 0.0, + "5": 0.1228, + "delay_0": 0.0 + }, + "sd_bill_dollars": 8679537 + }, + "predictive_sd_pp": 0.5782 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 8306461, + "modal_bucket_probability": 0.7015, + "p_bucket": { + "0": 0.7015, + "10": 0.0155, + "15": 0.0001, + "5": 0.2829, + "delay_0": 0.0 + }, + "sd_bill_dollars": 13136175 + }, + "predictive_sd_pp": 1.2291 + } + }, + "ID": { + "fy2025_delay": false, + "fy2025_official": 3.85, + "issuance_fy2024_dollars": 281230283, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 0, + "modal_bucket_probability": 1.0, + "p_bucket": { + "0": 1.0, + "10": 0.0, + "15": 0.0, + "5": 0.0, + "delay_0": 0.0 + }, + "sd_bill_dollars": 0 + }, + "predictive_sd_pp": 0.358 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 445750, + "modal_bucket_probability": 0.9686, + "p_bucket": { + "0": 0.9686, + "10": 0.0003, + "15": 0.0, + "5": 0.0312, + "delay_0": 0.0 + }, + "sd_bill_dollars": 2483564 + }, + "predictive_sd_pp": 1.1421 + } + }, + "IL": { + "fy2025_delay": true, + "fy2025_official": 14.67, + "issuance_fy2024_dollars": 4469341818, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 47665530, + "modal_bucket_probability": 0.9289, + "p_bucket": { + "0": 0.0, + "10": 0.0, + "15": 0.0711, + "5": 0.0, + "delay_0": 0.9289 + }, + "sd_bill_dollars": 172287636 + }, + "predictive_sd_pp": 0.9138 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 114370457, + "modal_bucket_probability": 0.8293, + "p_bucket": { + "0": 0.0, + "10": 0.0003, + "15": 0.1704, + "5": 0.0, + "delay_0": 0.8293 + }, + "sd_bill_dollars": 252118099 + }, + "predictive_sd_pp": 1.4182 + } + }, + "IN": { + "fy2025_delay": false, + "fy2025_official": 9.77, + "issuance_fy2024_dollars": 1435952329, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 143480357, + "sd_bill_dollars": 2869606 + }, + "fy2029": { + "expected_bill_dollars": 168663371, + "modal_bucket_probability": 0.6476, + "p_bucket": { + "0": 0.0, + "10": 0.6476, + "15": 0.3508, + "5": 0.0016, + "delay_0": 0.0 + }, + "sd_bill_dollars": 34466167 + }, + "predictive_sd_pp": 0.5972 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 137804755, + "sd_bill_dollars": 20262399 + }, + "fy2029": { + "expected_bill_dollars": 167866417, + "modal_bucket_probability": 0.5034, + "p_bucket": { + "0": 0.0009, + "10": 0.5034, + "15": 0.4187, + "5": 0.0751, + "delay_0": 0.0019 + }, + "sd_bill_dollars": 44870477 + }, + "predictive_sd_pp": 1.2381 + } + }, + "KS": { + "fy2025_delay": false, + "fy2025_official": 9.44, + "issuance_fy2024_dollars": 408410165, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 40807323, + "sd_bill_dollars": 828800 + }, + "fy2029": { + "expected_bill_dollars": 43207753, + "modal_bucket_probability": 0.8808, + "p_bucket": { + "0": 0.0, + "10": 0.8808, + "15": 0.1176, + "5": 0.0016, + "delay_0": 0.0 + }, + "sd_bill_dollars": 6641131 + }, + "predictive_sd_pp": 0.472 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 38475301, + "sd_bill_dollars": 6702432 + }, + "fy2029": { + "expected_bill_dollars": 44950644, + "modal_bucket_probability": 0.5697, + "p_bucket": { + "0": 0.0021, + "10": 0.5697, + "15": 0.3171, + "5": 0.1105, + "delay_0": 0.0006 + }, + "sd_bill_dollars": 12878663 + }, + "predictive_sd_pp": 1.1828 + } + }, + "KY": { + "fy2025_delay": false, + "fy2025_official": 4.7, + "issuance_fy2024_dollars": 1150201172, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 954667, + "modal_bucket_probability": 0.9834, + "p_bucket": { + "0": 0.9834, + "10": 0.0, + "15": 0.0, + "5": 0.0166, + "delay_0": 0.0 + }, + "sd_bill_dollars": 7347895 + }, + "predictive_sd_pp": 0.6095 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 8652388, + "modal_bucket_probability": 0.8534, + "p_bucket": { + "0": 0.8534, + "10": 0.0039, + "15": 0.0, + "5": 0.1427, + "delay_0": 0.0 + }, + "sd_bill_dollars": 21170795 + }, + "predictive_sd_pp": 1.2441 + } + }, + "LA": { + "fy2025_delay": false, + "fy2025_official": 8.14, + "issuance_fy2024_dollars": 1902455806, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 149842175, + "sd_bill_dollars": 47221298 + }, + "fy2029": { + "expected_bill_dollars": 150146568, + "modal_bucket_probability": 0.5731, + "p_bucket": { + "0": 0.001, + "10": 0.5731, + "15": 0.0032, + "5": 0.4227, + "delay_0": 0.0 + }, + "sd_bill_dollars": 47783994 + }, + "predictive_sd_pp": 0.6924 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 142265645, + "sd_bill_dollars": 56128946 + }, + "fy2029": { + "expected_bill_dollars": 149552051, + "modal_bucket_probability": 0.4681, + "p_bucket": { + "0": 0.0491, + "10": 0.4681, + "15": 0.0766, + "5": 0.4062, + "delay_0": 0.0 + }, + "sd_bill_dollars": 67005020 + }, + "predictive_sd_pp": 1.2868 + } + }, + "MA": { + "fy2025_delay": false, + "fy2025_official": 12.49, + "issuance_fy2024_dollars": 2617666701, + "lock_share_pct": 15.0, + "static": { + "fy2028": { + "expected_bill_dollars": 305861266, + "sd_bill_dollars": 161798400 + }, + "fy2029": { + "expected_bill_dollars": 305861266, + "modal_bucket_probability": 0.7719, + "p_bucket": { + "0": 0.0, + "10": 0.0106, + "15": 0.7719, + "5": 0.0001, + "delay_0": 0.2175 + }, + "sd_bill_dollars": 161798400 + }, + "predictive_sd_pp": 1.0733 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 269299006, + "sd_bill_dollars": 177265424 + }, + "fy2029": { + "expected_bill_dollars": 269299006, + "modal_bucket_probability": 0.6515, + "p_bucket": { + "0": 0.0, + "10": 0.0507, + "15": 0.6515, + "5": 0.0018, + "delay_0": 0.2961 + }, + "sd_bill_dollars": 177265424 + }, + "predictive_sd_pp": 1.5259 + } + }, + "MD": { + "fy2025_delay": false, + "fy2025_official": 13.08, + "issuance_fy2024_dollars": 1498308252, + "lock_share_pct": 15.0, + "static": { + "fy2028": { + "expected_bill_dollars": 133394384, + "sd_bill_dollars": 110341111 + }, + "fy2029": { + "expected_bill_dollars": 133394384, + "modal_bucket_probability": 0.5929, + "p_bucket": { + "0": 0.0, + "10": 0.0009, + "15": 0.5929, + "5": 0.0, + "delay_0": 0.4062 + }, + "sd_bill_dollars": 110341111 + }, + "predictive_sd_pp": 1.0186 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 125370943, + "sd_bill_dollars": 110659416 + }, + "fy2029": { + "expected_bill_dollars": 125370943, + "modal_bucket_probability": 0.5453, + "p_bucket": { + "0": 0.0, + "10": 0.0187, + "15": 0.5453, + "5": 0.0003, + "delay_0": 0.4358 + }, + "sd_bill_dollars": 110659416 + }, + "predictive_sd_pp": 1.4879 + } + }, + "ME": { + "fy2025_delay": false, + "fy2025_official": 10.81, + "issuance_fy2024_dollars": 363838898, + "lock_share_pct": 15.0, + "static": { + "fy2028": { + "expected_bill_dollars": 51756993, + "sd_bill_dollars": 6712322 + }, + "fy2029": { + "expected_bill_dollars": 51756993, + "modal_bucket_probability": 0.8469, + "p_bucket": { + "0": 0.0, + "10": 0.1519, + "15": 0.8469, + "5": 0.0005, + "delay_0": 0.0007 + }, + "sd_bill_dollars": 6712322 + }, + "predictive_sd_pp": 0.7997 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 47639246, + "sd_bill_dollars": 12357277 + }, + "fy2029": { + "expected_bill_dollars": 47639246, + "modal_bucket_probability": 0.7003, + "p_bucket": { + "0": 0.0004, + "10": 0.2494, + "15": 0.7003, + "5": 0.0192, + "delay_0": 0.0308 + }, + "sd_bill_dollars": 12357277 + }, + "predictive_sd_pp": 1.3475 + } + }, + "MI": { + "fy2025_delay": false, + "fy2025_official": 9.89, + "issuance_fy2024_dollars": 3061361572, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 302837540, + "sd_bill_dollars": 22331997 + }, + "fy2029": { + "expected_bill_dollars": 371986045, + "modal_bucket_probability": 0.5268, + "p_bucket": { + "0": 0.0, + "10": 0.5268, + "15": 0.4517, + "5": 0.0214, + "delay_0": 0.0001 + }, + "sd_bill_dollars": 82205961 + }, + "predictive_sd_pp": 0.9195 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 289880327, + "sd_bill_dollars": 51595878 + }, + "fy2029": { + "expected_bill_dollars": 361493228, + "modal_bucket_probability": 0.4678, + "p_bucket": { + "0": 0.0027, + "10": 0.4353, + "15": 0.4678, + "5": 0.0875, + "delay_0": 0.0067 + }, + "sd_bill_dollars": 104036678 + }, + "predictive_sd_pp": 1.4219 + } + }, + "MN": { + "fy2025_delay": false, + "fy2025_official": 12.58, + "issuance_fy2024_dollars": 859038624, + "lock_share_pct": 15.0, + "static": { + "fy2028": { + "expected_bill_dollars": 95033295, + "sd_bill_dollars": 56227220 + }, + "fy2029": { + "expected_bill_dollars": 95033295, + "modal_bucket_probability": 0.728, + "p_bucket": { + "0": 0.0, + "10": 0.0143, + "15": 0.728, + "5": 0.0001, + "delay_0": 0.2577 + }, + "sd_bill_dollars": 56227220 + }, + "predictive_sd_pp": 1.1856 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 84806441, + "sd_bill_dollars": 59478689 + }, + "fy2029": { + "expected_bill_dollars": 84806441, + "modal_bucket_probability": 0.6232, + "p_bucket": { + "0": 0.0001, + "10": 0.0512, + "15": 0.6232, + "5": 0.0024, + "delay_0": 0.3231 + }, + "sd_bill_dollars": 59478689 + }, + "predictive_sd_pp": 1.6068 + } + }, + "MO": { + "fy2025_delay": false, + "fy2025_official": 8.67, + "issuance_fy2024_dollars": 1512570795, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 142174092, + "sd_bill_dollars": 24585207 + }, + "fy2029": { + "expected_bill_dollars": 142873656, + "modal_bucket_probability": 0.8707, + "p_bucket": { + "0": 0.0, + "10": 0.8707, + "15": 0.0092, + "5": 0.1201, + "delay_0": 0.0 + }, + "sd_bill_dollars": 25875825 + }, + "predictive_sd_pp": 0.5732 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 128371883, + "sd_bill_dollars": 37075980 + }, + "fy2029": { + "expected_bill_dollars": 138593081, + "modal_bucket_probability": 0.5769, + "p_bucket": { + "0": 0.0146, + "10": 0.5769, + "15": 0.1351, + "5": 0.2733, + "delay_0": 0.0001 + }, + "sd_bill_dollars": 50109857 + }, + "predictive_sd_pp": 1.2267 + } + }, + "MS": { + "fy2025_delay": false, + "fy2025_official": 9.51, + "issuance_fy2024_dollars": 842267063, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 84058253, + "sd_bill_dollars": 2658150 + }, + "fy2029": { + "expected_bill_dollars": 92514614, + "modal_bucket_probability": 0.7952, + "p_bucket": { + "0": 0.0, + "10": 0.7952, + "15": 0.2008, + "5": 0.004, + "delay_0": 0.0 + }, + "sd_bill_dollars": 17161889 + }, + "predictive_sd_pp": 0.5796 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 79514222, + "sd_bill_dollars": 13618861 + }, + "fy2029": { + "expected_bill_dollars": 94093865, + "modal_bucket_probability": 0.5445, + "p_bucket": { + "0": 0.0017, + "10": 0.5445, + "15": 0.3462, + "5": 0.1067, + "delay_0": 0.0009 + }, + "sd_bill_dollars": 26913151 + }, + "predictive_sd_pp": 1.2297 + } + }, + "MT": { + "fy2025_delay": false, + "fy2025_official": 8.86, + "issuance_fy2024_dollars": 169446871, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 15886068, + "sd_bill_dollars": 2802765 + }, + "fy2029": { + "expected_bill_dollars": 16433381, + "modal_bucket_probability": 0.8105, + "p_bucket": { + "0": 0.0001, + "10": 0.8105, + "15": 0.0646, + "5": 0.1249, + "delay_0": 0.0 + }, + "sd_bill_dollars": 3654006 + }, + "predictive_sd_pp": 0.7535 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 14560570, + "sd_bill_dollars": 4122072 + }, + "fy2029": { + "expected_bill_dollars": 16170739, + "modal_bucket_probability": 0.5458, + "p_bucket": { + "0": 0.0168, + "10": 0.5458, + "15": 0.19, + "5": 0.2469, + "delay_0": 0.0005 + }, + "sd_bill_dollars": 5976487 + }, + "predictive_sd_pp": 1.3206 + } + }, + "NC": { + "fy2025_delay": false, + "fy2025_official": 7.36, + "issuance_fy2024_dollars": 2934626410, + "lock_share_pct": 5.0, + "static": { + "fy2028": { + "expected_bill_dollars": 142373400, + "sd_bill_dollars": 24908872 + }, + "fy2029": { + "expected_bill_dollars": 169672762, + "modal_bucket_probability": 0.7843, + "p_bucket": { + "0": 0.0297, + "10": 0.1858, + "15": 0.0001, + "5": 0.7843, + "delay_0": 0.0 + }, + "sd_bill_dollars": 64211456 + }, + "predictive_sd_pp": 0.7159 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 125411260, + "sd_bill_dollars": 51708565 + }, + "fy2029": { + "expected_bill_dollars": 174470877, + "modal_bucket_probability": 0.5412, + "p_bucket": { + "0": 0.1453, + "10": 0.2928, + "15": 0.0208, + "5": 0.5412, + "delay_0": 0.0 + }, + "sd_bill_dollars": 102240263 + }, + "predictive_sd_pp": 1.2995 + } + }, + "ND": { + "fy2025_delay": false, + "fy2025_official": 9.89, + "issuance_fy2024_dollars": 111448901, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 10832276, + "sd_bill_dollars": 1327515 + }, + "fy2029": { + "expected_bill_dollars": 13402566, + "modal_bucket_probability": 0.4845, + "p_bucket": { + "0": 0.0005, + "10": 0.4845, + "15": 0.4612, + "5": 0.0523, + "delay_0": 0.0014 + }, + "sd_bill_dollars": 3329523 + }, + "predictive_sd_pp": 1.1542 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 10309023, + "sd_bill_dollars": 2285382 + }, + "fy2029": { + "expected_bill_dollars": 12886558, + "modal_bucket_probability": 0.4626, + "p_bucket": { + "0": 0.0067, + "10": 0.4078, + "15": 0.4626, + "5": 0.1093, + "delay_0": 0.0137 + }, + "sd_bill_dollars": 4153481 + }, + "predictive_sd_pp": 1.5838 + } + }, + "NE": { + "fy2025_delay": false, + "fy2025_official": 5.9, + "issuance_fy2024_dollars": 331710249, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 7329138, + "modal_bucket_probability": 0.5588, + "p_bucket": { + "0": 0.5588, + "10": 0.0008, + "15": 0.0, + "5": 0.4404, + "delay_0": 0.0 + }, + "sd_bill_dollars": 8261590 + }, + "predictive_sd_pp": 0.686 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 8624466, + "modal_bucket_probability": 0.5303, + "p_bucket": { + "0": 0.5303, + "10": 0.049, + "15": 0.0006, + "5": 0.42, + "delay_0": 0.0 + }, + "sd_bill_dollars": 9833125 + }, + "predictive_sd_pp": 1.2833 + } + }, + "NH": { + "fy2025_delay": false, + "fy2025_official": 8.85, + "issuance_fy2024_dollars": 154254645, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 14391958, + "sd_bill_dollars": 2630754 + }, + "fy2029": { + "expected_bill_dollars": 14938020, + "modal_bucket_probability": 0.7954, + "p_bucket": { + "0": 0.0001, + "10": 0.7954, + "15": 0.0708, + "5": 0.1337, + "delay_0": 0.0 + }, + "sd_bill_dollars": 3458761 + }, + "predictive_sd_pp": 0.7741 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 13253173, + "sd_bill_dollars": 3750984 + }, + "fy2029": { + "expected_bill_dollars": 14769497, + "modal_bucket_probability": 0.5389, + "p_bucket": { + "0": 0.0168, + "10": 0.5389, + "15": 0.1966, + "5": 0.2475, + "delay_0": 0.0003 + }, + "sd_bill_dollars": 5482101 + }, + "predictive_sd_pp": 1.3325 + } + }, + "NJ": { + "fy2025_delay": false, + "fy2025_official": 6.86, + "issuance_fy2024_dollars": 1925707853, + "lock_share_pct": 5.0, + "static": { + "fy2028": { + "expected_bill_dollars": 86940895, + "sd_bill_dollars": 28502964 + }, + "fy2029": { + "expected_bill_dollars": 91307438, + "modal_bucket_probability": 0.8576, + "p_bucket": { + "0": 0.097, + "10": 0.0454, + "15": 0.0, + "5": 0.8576, + "delay_0": 0.0 + }, + "sd_bill_dollars": 35991566 + }, + "predictive_sd_pp": 0.6659 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 72541415, + "sd_bill_dollars": 41502069 + }, + "fy2029": { + "expected_bill_dollars": 91432609, + "modal_bucket_probability": 0.5645, + "p_bucket": { + "0": 0.2466, + "10": 0.1815, + "15": 0.0073, + "5": 0.5645, + "delay_0": 0.0 + }, + "sd_bill_dollars": 64945182 + }, + "predictive_sd_pp": 1.2727 + } + }, + "NM": { + "fy2025_delay": true, + "fy2025_official": 16.81, + "issuance_fy2024_dollars": 1028090754, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 7711, + "modal_bucket_probability": 1.0, + "p_bucket": { + "0": 0.0, + "10": 0.0, + "15": 0.0001, + "5": 0.0, + "delay_0": 1.0 + }, + "sd_bill_dollars": 1090428 + }, + "predictive_sd_pp": 0.8604 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 871307, + "modal_bucket_probability": 0.9943, + "p_bucket": { + "0": 0.0, + "10": 0.0, + "15": 0.0056, + "5": 0.0, + "delay_0": 0.9943 + }, + "sd_bill_dollars": 11558902 + }, + "predictive_sd_pp": 1.3844 + } + }, + "NV": { + "fy2025_delay": false, + "fy2025_official": 6.22, + "issuance_fy2024_dollars": 1006600692, + "lock_share_pct": 5.0, + "static": { + "fy2028": { + "expected_bill_dollars": 30721453, + "sd_bill_dollars": 24543922 + }, + "fy2029": { + "expected_bill_dollars": 31295216, + "modal_bucket_probability": 0.599, + "p_bucket": { + "0": 0.3896, + "10": 0.0114, + "15": 0.0, + "5": 0.599, + "delay_0": 0.0 + }, + "sd_bill_dollars": 25562741 + }, + "predictive_sd_pp": 0.7827 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 28557262, + "sd_bill_dollars": 24935332 + }, + "fy2029": { + "expected_bill_dollars": 33112130, + "modal_bucket_probability": 0.4795, + "p_bucket": { + "0": 0.4326, + "10": 0.0853, + "15": 0.0026, + "5": 0.4795, + "delay_0": 0.0 + }, + "sd_bill_dollars": 32276726 + }, + "predictive_sd_pp": 1.3375 + } + }, + "NY": { + "fy2025_delay": false, + "fy2025_official": 13.18, + "issuance_fy2024_dollars": 7231611169, + "lock_share_pct": 15.0, + "static": { + "fy2028": { + "expected_bill_dollars": 612842889, + "sd_bill_dollars": 537675760 + }, + "fy2029": { + "expected_bill_dollars": 612842889, + "modal_bucket_probability": 0.5647, + "p_bucket": { + "0": 0.0, + "10": 0.0004, + "15": 0.5647, + "5": 0.0, + "delay_0": 0.4349 + }, + "sd_bill_dollars": 537675760 + }, + "predictive_sd_pp": 0.9334 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 588616991, + "sd_bill_dollars": 537460230 + }, + "fy2029": { + "expected_bill_dollars": 588616991, + "modal_bucket_probability": 0.5346, + "p_bucket": { + "0": 0.0, + "10": 0.0118, + "15": 0.5346, + "5": 0.0003, + "delay_0": 0.4532 + }, + "sd_bill_dollars": 537460230 + }, + "predictive_sd_pp": 1.4309 + } + }, + "OH": { + "fy2025_delay": false, + "fy2025_official": 6.76, + "issuance_fy2024_dollars": 3186433783, + "lock_share_pct": 5.0, + "static": { + "fy2028": { + "expected_bill_dollars": 141477660, + "sd_bill_dollars": 50244716 + }, + "fy2029": { + "expected_bill_dollars": 145086296, + "modal_bucket_probability": 0.8653, + "p_bucket": { + "0": 0.112, + "10": 0.0226, + "15": 0.0, + "5": 0.8653, + "delay_0": 0.0 + }, + "sd_bill_dollars": 56702985 + }, + "predictive_sd_pp": 0.616 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 115707377, + "sd_bill_dollars": 71038705 + }, + "fy2029": { + "expected_bill_dollars": 141867998, + "modal_bucket_probability": 0.5671, + "p_bucket": { + "0": 0.2737, + "10": 0.1541, + "15": 0.005, + "5": 0.5671, + "delay_0": 0.0 + }, + "sd_bill_dollars": 105206470 + }, + "predictive_sd_pp": 1.2473 + } + }, + "OK": { + "fy2025_delay": false, + "fy2025_official": 11.04, + "issuance_fy2024_dollars": 1506326652, + "lock_share_pct": 15.0, + "static": { + "fy2028": { + "expected_bill_dollars": 216824424, + "sd_bill_dollars": 26964160 + }, + "fy2029": { + "expected_bill_dollars": 216824424, + "modal_bucket_probability": 0.8861, + "p_bucket": { + "0": 0.0, + "10": 0.1103, + "15": 0.8861, + "5": 0.0001, + "delay_0": 0.0036 + }, + "sd_bill_dollars": 26964160 + }, + "predictive_sd_pp": 0.8439 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 196745090, + "sd_bill_dollars": 56657706 + }, + "fy2029": { + "expected_bill_dollars": 196745090, + "modal_bucket_probability": 0.7267, + "p_bucket": { + "0": 0.0002, + "10": 0.2088, + "15": 0.7267, + "5": 0.0147, + "delay_0": 0.0496 + }, + "sd_bill_dollars": 56657706 + }, + "predictive_sd_pp": 1.3742 + } + }, + "OR": { + "fy2025_delay": true, + "fy2025_official": 14.14, + "issuance_fy2024_dollars": 1596585242, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 60115426, + "modal_bucket_probability": 0.7489, + "p_bucket": { + "0": 0.0, + "10": 0.0003, + "15": 0.2509, + "5": 0.0, + "delay_0": 0.7489 + }, + "sd_bill_dollars": 103826102 + }, + "predictive_sd_pp": 1.1798 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 73167510, + "modal_bucket_probability": 0.6928, + "p_bucket": { + "0": 0.0, + "10": 0.0048, + "15": 0.3023, + "5": 0.0001, + "delay_0": 0.6928 + }, + "sd_bill_dollars": 110033746 + }, + "predictive_sd_pp": 1.6026 + } + }, + "PA": { + "fy2025_delay": false, + "fy2025_official": 9.21, + "issuance_fy2024_dollars": 4268035433, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 407597384, + "sd_bill_dollars": 61220650 + }, + "fy2029": { + "expected_bill_dollars": 446767279, + "modal_bucket_probability": 0.7267, + "p_bucket": { + "0": 0.0002, + "10": 0.7267, + "15": 0.1835, + "5": 0.0896, + "delay_0": 0.0 + }, + "sd_bill_dollars": 109896401 + }, + "predictive_sd_pp": 0.9023 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 382725407, + "sd_bill_dollars": 92771397 + }, + "fy2029": { + "expected_bill_dollars": 443790324, + "modal_bucket_probability": 0.5199, + "p_bucket": { + "0": 0.0111, + "10": 0.5199, + "15": 0.2862, + "5": 0.1815, + "delay_0": 0.0014 + }, + "sd_bill_dollars": 152617905 + }, + "predictive_sd_pp": 1.4108 + } + }, + "RI": { + "fy2025_delay": false, + "fy2025_official": 12.42, + "issuance_fy2024_dollars": 343066538, + "lock_share_pct": 15.0, + "static": { + "fy2028": { + "expected_bill_dollars": 42397878, + "sd_bill_dollars": 19517887 + }, + "fy2029": { + "expected_bill_dollars": 42397878, + "modal_bucket_probability": 0.8202, + "p_bucket": { + "0": 0.0, + "10": 0.0056, + "15": 0.8202, + "5": 0.0, + "delay_0": 0.1742 + }, + "sd_bill_dollars": 19517887 + }, + "predictive_sd_pp": 0.9556 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 37231296, + "sd_bill_dollars": 22391694 + }, + "fy2029": { + "expected_bill_dollars": 37231296, + "modal_bucket_probability": 0.6915, + "p_bucket": { + "0": 0.0001, + "10": 0.0476, + "15": 0.6915, + "5": 0.0006, + "delay_0": 0.2602 + }, + "sd_bill_dollars": 22391694 + }, + "predictive_sd_pp": 1.4455 + } + }, + "SC": { + "fy2025_delay": false, + "fy2025_official": 8.8, + "issuance_fy2024_dollars": 1293584986, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 122819426, + "sd_bill_dollars": 19498277 + }, + "fy2029": { + "expected_bill_dollars": 124507555, + "modal_bucket_probability": 0.8728, + "p_bucket": { + "0": 0.0, + "10": 0.8728, + "15": 0.0261, + "5": 0.1011, + "delay_0": 0.0 + }, + "sd_bill_dollars": 22552106 + }, + "predictive_sd_pp": 0.6227 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 111843358, + "sd_bill_dollars": 30383236 + }, + "fy2029": { + "expected_bill_dollars": 122942317, + "modal_bucket_probability": 0.5692, + "p_bucket": { + "0": 0.0114, + "10": 0.5692, + "15": 0.1716, + "5": 0.2476, + "delay_0": 0.0002 + }, + "sd_bill_dollars": 43664930 + }, + "predictive_sd_pp": 1.2506 + } + }, + "SD": { + "fy2025_delay": false, + "fy2025_official": 2.47, + "issuance_fy2024_dollars": 180195817, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 0, + "modal_bucket_probability": 1.0, + "p_bucket": { + "0": 1.0, + "10": 0.0, + "15": 0.0, + "5": 0.0, + "delay_0": 0.0 + }, + "sd_bill_dollars": 0 + }, + "predictive_sd_pp": 0.4357 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 14416, + "modal_bucket_probability": 0.9984, + "p_bucket": { + "0": 0.9984, + "10": 0.0, + "15": 0.0, + "5": 0.0016, + "delay_0": 0.0 + }, + "sd_bill_dollars": 360103 + }, + "predictive_sd_pp": 1.1688 + } + }, + "TN": { + "fy2025_delay": false, + "fy2025_official": 9.44, + "issuance_fy2024_dollars": 1623231075, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 162079623, + "sd_bill_dollars": 4438728 + }, + "fy2029": { + "expected_bill_dollars": 173559925, + "modal_bucket_probability": 0.8556, + "p_bucket": { + "0": 0.0, + "10": 0.8556, + "15": 0.1414, + "5": 0.003, + "delay_0": 0.0 + }, + "sd_bill_dollars": 28727246 + }, + "predictive_sd_pp": 0.5217 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 152583721, + "sd_bill_dollars": 27040321 + }, + "fy2029": { + "expected_bill_dollars": 178052217, + "modal_bucket_probability": 0.5689, + "p_bucket": { + "0": 0.0022, + "10": 0.5689, + "15": 0.3138, + "5": 0.1146, + "delay_0": 0.0005 + }, + "sd_bill_dollars": 51436295 + }, + "predictive_sd_pp": 1.2035 + } + }, + "TX": { + "fy2025_delay": false, + "fy2025_official": 9.34, + "issuance_fy2024_dollars": 7332023032, + "lock_share_pct": 10.0, + "static": { + "fy2028": { + "expected_bill_dollars": 725503679, + "sd_bill_dollars": 52564776 + }, + "fy2029": { + "expected_bill_dollars": 783371671, + "modal_bucket_probability": 0.8212, + "p_bucket": { + "0": 0.0, + "10": 0.8212, + "15": 0.1578, + "5": 0.021, + "delay_0": 0.0 + }, + "sd_bill_dollars": 146696392 + }, + "predictive_sd_pp": 0.6606 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 678597062, + "sd_bill_dollars": 135326930 + }, + "fy2029": { + "expected_bill_dollars": 790630374, + "modal_bucket_probability": 0.5502, + "p_bucket": { + "0": 0.0042, + "10": 0.5502, + "15": 0.3056, + "5": 0.1394, + "delay_0": 0.0006 + }, + "sd_bill_dollars": 243040466 + }, + "predictive_sd_pp": 1.2699 + } + }, + "UT": { + "fy2025_delay": false, + "fy2025_official": 5.54, + "issuance_fy2024_dollars": 382660017, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 1650221, + "modal_bucket_probability": 0.9137, + "p_bucket": { + "0": 0.9137, + "10": 0.0, + "15": 0.0, + "5": 0.0862, + "delay_0": 0.0 + }, + "sd_bill_dollars": 5371262 + }, + "predictive_sd_pp": 0.3346 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 6734816, + "modal_bucket_probability": 0.6643, + "p_bucket": { + "0": 0.6643, + "10": 0.0159, + "15": 0.0002, + "5": 0.3195, + "delay_0": 0.0 + }, + "sd_bill_dollars": 9778367 + }, + "predictive_sd_pp": 1.135 + } + }, + "VA": { + "fy2025_delay": false, + "fy2025_official": 12.32, + "issuance_fy2024_dollars": 1766229367, + "lock_share_pct": 15.0, + "static": { + "fy2028": { + "expected_bill_dollars": 233257081, + "sd_bill_dollars": 85654582 + }, + "fy2029": { + "expected_bill_dollars": 233257081, + "modal_bucket_probability": 0.8782, + "p_bucket": { + "0": 0.0, + "10": 0.0034, + "15": 0.8782, + "5": 0.0, + "delay_0": 0.1184 + }, + "sd_bill_dollars": 85654582 + }, + "predictive_sd_pp": 0.8445 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 199526516, + "sd_bill_dollars": 110864755 + }, + "fy2029": { + "expected_bill_dollars": 199526516, + "modal_bucket_probability": 0.721, + "p_bucket": { + "0": 0.0, + "10": 0.0475, + "15": 0.721, + "5": 0.0012, + "delay_0": 0.2303 + }, + "sd_bill_dollars": 110864755 + }, + "predictive_sd_pp": 1.3746 + } + }, + "VI": { + "fy2025_delay": false, + "fy2025_official": 5.36, + "issuance_fy2024_dollars": 70457505, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 712325, + "modal_bucket_probability": 0.7983, + "p_bucket": { + "0": 0.7983, + "10": 0.0004, + "15": 0.0, + "5": 0.2013, + "delay_0": 0.0 + }, + "sd_bill_dollars": 1418871 + }, + "predictive_sd_pp": 0.7676 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 1214511, + "modal_bucket_probability": 0.6787, + "p_bucket": { + "0": 0.6787, + "10": 0.0232, + "15": 0.0001, + "5": 0.298, + "delay_0": 0.0 + }, + "sd_bill_dollars": 1841010 + }, + "predictive_sd_pp": 1.3287 + } + }, + "VT": { + "fy2025_delay": false, + "fy2025_official": 5.38, + "issuance_fy2024_dollars": 148302129, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 1658018, + "modal_bucket_probability": 0.7769, + "p_bucket": { + "0": 0.7769, + "10": 0.0005, + "15": 0.0, + "5": 0.2226, + "delay_0": 0.0 + }, + "sd_bill_dollars": 3098441 + }, + "predictive_sd_pp": 0.8085 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 2583423, + "modal_bucket_probability": 0.6763, + "p_bucket": { + "0": 0.6763, + "10": 0.0242, + "15": 0.0003, + "5": 0.2994, + "delay_0": 0.0 + }, + "sd_bill_dollars": 3901343 + }, + "predictive_sd_pp": 1.3528 + } + }, + "WA": { + "fy2025_delay": false, + "fy2025_official": 6.98, + "issuance_fy2024_dollars": 1920375025, + "lock_share_pct": 5.0, + "static": { + "fy2028": { + "expected_bill_dollars": 87804347, + "sd_bill_dollars": 26856292 + }, + "fy2029": { + "expected_bill_dollars": 95178587, + "modal_bucket_probability": 0.8377, + "p_bucket": { + "0": 0.0856, + "10": 0.0768, + "15": 0.0, + "5": 0.8377, + "delay_0": 0.0 + }, + "sd_bill_dollars": 38679404 + }, + "predictive_sd_pp": 0.7199 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 73699193, + "sd_bill_dollars": 40557779 + }, + "fy2029": { + "expected_bill_dollars": 94938540, + "modal_bucket_probability": 0.5558, + "p_bucket": { + "0": 0.2324, + "10": 0.2022, + "15": 0.0095, + "5": 0.5558, + "delay_0": 0.0 + }, + "sd_bill_dollars": 66003616 + }, + "predictive_sd_pp": 1.3018 + } + }, + "WI": { + "fy2025_delay": false, + "fy2025_official": 5.72, + "issuance_fy2024_dollars": 1363921863, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 20772530, + "modal_bucket_probability": 0.6954, + "p_bucket": { + "0": 0.6954, + "10": 0.0, + "15": 0.0, + "5": 0.3046, + "delay_0": 0.0 + }, + "sd_bill_dollars": 31386420 + }, + "predictive_sd_pp": 0.553 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 30091526, + "modal_bucket_probability": 0.5883, + "p_bucket": { + "0": 0.5883, + "10": 0.0293, + "15": 0.0001, + "5": 0.3823, + "delay_0": 0.0 + }, + "sd_bill_dollars": 37721036 + }, + "predictive_sd_pp": 1.2174 + } + }, + "WV": { + "fy2025_delay": false, + "fy2025_official": 6.69, + "issuance_fy2024_dollars": 565647589, + "lock_share_pct": 5.0, + "static": { + "fy2028": { + "expected_bill_dollars": 24600014, + "sd_bill_dollars": 9517681 + }, + "fy2029": { + "expected_bill_dollars": 25034148, + "modal_bucket_probability": 0.8545, + "p_bucket": { + "0": 0.1302, + "10": 0.0154, + "15": 0.0, + "5": 0.8545, + "delay_0": 0.0 + }, + "sd_bill_dollars": 10289481 + }, + "predictive_sd_pp": 0.6155 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 19770797, + "sd_bill_dollars": 12972308 + }, + "fy2029": { + "expected_bill_dollars": 23946691, + "modal_bucket_probability": 0.5555, + "p_bucket": { + "0": 0.3009, + "10": 0.1394, + "15": 0.0041, + "5": 0.5555, + "delay_0": 0.0 + }, + "sd_bill_dollars": 18617006 + }, + "predictive_sd_pp": 1.2471 + } + }, + "WY": { + "fy2025_delay": false, + "fy2025_official": 3.96, + "issuance_fy2024_dollars": 56701860, + "lock_share_pct": 0.0, + "static": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 67900, + "modal_bucket_probability": 0.976, + "p_bucket": { + "0": 0.976, + "10": 0.0, + "15": 0.0, + "5": 0.0239, + "delay_0": 0.0 + }, + "sd_bill_dollars": 433467 + }, + "predictive_sd_pp": 1.0395 + }, + "widened": { + "fy2028": { + "expected_bill_dollars": 0, + "sd_bill_dollars": 0 + }, + "fy2029": { + "expected_bill_dollars": 259128, + "modal_bucket_probability": 0.9126, + "p_bucket": { + "0": 0.9126, + "10": 0.0039, + "15": 0.0001, + "5": 0.0834, + "delay_0": 0.0 + }, + "sd_bill_dollars": 855926 + }, + "predictive_sd_pp": 1.5023 + } + } + } + }, + "per_year_mean_crps": { + "2016": { + "rao_yu": 0.9074, + "static": 1.0008, + "static_fair": 0.9507, + "widened": 0.8784, + "winner": "widened" + }, + "2017": { + "rao_yu": 0.8219, + "static": 0.8823, + "static_fair": 0.8377, + "widened": 0.7925, + "winner": "widened" + }, + "2018": { + "rao_yu": 0.6908, + "static": 0.6389, + "static_fair": 0.6067, + "widened": 0.5969, + "winner": "widened" + }, + "2019": { + "rao_yu": 0.9082, + "static": 0.9553, + "static_fair": 0.9183, + "widened": 0.8854, + "winner": "widened" + }, + "2020": { + "rao_yu": 0.9035, + "static": 1.2368, + "static_fair": 1.1711, + "widened": 1.0913, + "winner": "rao_yu" + }, + "2022": { + "rao_yu": 1.1138, + "static": 1.3505, + "static_fair": 1.2929, + "widened": 1.2411, + "winner": "rao_yu" + }, + "2023": { + "rao_yu": 0.9178, + "static": 0.9289, + "static_fair": 0.883, + "widened": 0.8585, + "winner": "widened" + }, + "2024": { + "rao_yu": 0.7588, + "static": 0.9381, + "static_fair": 0.8804, + "widened": 0.8582, + "winner": "rao_yu" + } + }, + "quantile_grid": [ + 0.05, + 0.1, + 0.15, + 0.2, + 0.25, + 0.3, + 0.35, + 0.4, + 0.45, + 0.5, + 0.55, + 0.6, + 0.65, + 0.7, + 0.75, + 0.8, + 0.85, + 0.9, + 0.95 + ], + "schema_version": 1, + "sensitivity_official_se_scale": { + "static_fair_official_1p1": { + "coverage_50": 0.5778, + "coverage_90": 0.9009, + "mean_crps": 0.9009, + "mean_log_score": -1.9547, + "mean_pinball": 0.4709, + "mean_predictive_sd_pp": 1.5556, + "n_state_years": 424 + }, + "static_official_1p1": { + "coverage_50": 0.4151, + "coverage_90": 0.7807, + "mean_crps": 0.911, + "mean_log_score": -2.2021, + "mean_pinball": 0.4749, + "mean_predictive_sd_pp": 1.1, + "n_state_years": 424 + } + }, + "summary": { + "rao_yu": { + "coverage_50": 0.4953, + "coverage_90": 0.8491, + "mean_crps": 0.8778, + "mean_log_score": -1.9318, + "mean_pinball": 0.4587, + "mean_predictive_sd_pp": 1.2908, + "n_state_years": 424 + }, + "static": { + "coverage_50": 0.1981, + "coverage_90": 0.4835, + "mean_crps": 0.9914, + "mean_log_score": -4.7344, + "mean_pinball": 0.5117, + "mean_predictive_sd_pp": 0.5706, + "n_state_years": 424 + }, + "static_fair": { + "coverage_50": 0.3066, + "coverage_90": 0.6415, + "mean_crps": 0.9426, + "mean_log_score": -2.8617, + "mean_pinball": 0.4896, + "mean_predictive_sd_pp": 0.8069, + "n_state_years": 424 + }, + "widened": { + "coverage_50": 0.4646, + "coverage_90": 0.8137, + "mean_crps": 0.9003, + "mean_log_score": -2.0101, + "mean_pinball": 0.4701, + "mean_predictive_sd_pp": 1.2005, + "n_state_years": 424 + } + }, + "target_years": [ + 2016, + 2017, + 2018, + 2019, + 2020, + 2022, + 2023, + 2024 + ] +} diff --git a/tests/test_persistence_backtest.py b/tests/test_persistence_backtest.py new file mode 100644 index 0000000..82bdc2c --- /dev/null +++ b/tests/test_persistence_backtest.py @@ -0,0 +1,133 @@ +"""Lock the distributional-backtest artifact and its regeneration.""" + +from __future__ import annotations + +import hashlib +import json +from pathlib import Path + +import pytest + +from analysis import event_study, persistence, persistence_backtest + +ROOT = Path(__file__).resolve().parent.parent +ARTIFACT = ROOT / "analysis" / "persistence_backtest_results.json" + + +@pytest.fixture(scope="module") +def artifact() -> dict: + return json.loads(ARTIFACT.read_text()) + + +def test_summary_domains_and_ordering(artifact) -> None: + s = artifact["summary"] + assert set(s) == set(persistence_backtest.APPROACHES) + for row in s.values(): + assert row["n_state_years"] > 300 + assert 0.0 <= row["coverage_50"] <= row["coverage_90"] <= 1.0 + assert row["mean_crps"] > 0 and row["mean_pinball"] > 0 + assert row["mean_predictive_sd_pp"] > 0 + assert s["widened"]["mean_predictive_sd_pp"] > s["static"]["mean_predictive_sd_pp"] + assert s["rao_yu"]["coverage_90"] >= s["static"]["coverage_90"] + + +def test_per_year_winners_consistent(artifact) -> None: + for year, row in artifact["per_year_mean_crps"].items(): + vals = {k: row[k] for k in persistence_backtest.APPROACHES} + assert row["winner"] == min(vals, key=vals.get), year + + +def test_input_hashes_match_live_files(artifact) -> None: + hashes = artifact["input_hashes"] + audit = hashlib.sha256(event_study.AUDIT_PATH.read_bytes()).hexdigest() + assert hashes["coding_consistency"] == audit + audit_years = json.loads(event_study.AUDIT_PATH.read_text())["years"] + assert hashes["raw_by_fiscal_year"] == { + str(y): audit_years[str(y)]["source"]["sha256"] for y in persistence.YEARS_USED + } + + +def test_penalty_translation_is_internally_consistent(artifact) -> None: + pt = artifact["penalty_translation"] + assert pt["innovation_variance_pp2"] > 0 + for code, row in pt["states"].items(): + for name in ("static", "widened"): + cell = row[name] + p29 = cell["fy2029"]["p_bucket"] + assert sum(p29.values()) == pytest.approx(1.0, abs=5e-3), code + assert cell["fy2029"]["modal_bucket_probability"] == pytest.approx( + max(p29.values()), abs=1e-6 + ) + for year in ("fy2028", "fy2029"): + assert cell[year]["sd_bill_dollars"] >= 0 + assert row["widened"]["predictive_sd_pp"] > row["static"]["predictive_sd_pp"], ( + code + ) + m = pt["median_modal_bucket_probability_fy2029"] + assert m["widened"] <= m["static"] + for name in ("static", "widened"): + for year in ("fy2028", "fy2029"): + nat = pt["national"][name][year] + assert nat["expected_total_dollars"] >= 0 + assert nat["sd_total_dollars_no_correlation"] > 0 + + +def test_statutory_fy2028_semantics(artifact) -> None: + """A state whose locked FY2025 crosses the delay test owes exactly zero + in FY2028 with zero variance under every construction (7 USC + 2013(a)(2)(B); the Illinois case from the sol review).""" + pt = artifact["penalty_translation"] + checked = 0 + for code, row in pt["states"].items(): + if not row["fy2025_delay"]: + continue + for name in ("static", "widened"): + assert row[name]["fy2028"]["expected_bill_dollars"] == 0, code + assert row[name]["fy2028"]["sd_bill_dollars"] == 0, code + checked += 1 + assert checked >= 1 + assert pt["states"]["IL"]["fy2025_delay"] is True + + +def test_sensitivity_rows_present_and_ordered(artifact) -> None: + sens = artifact["sensitivity_official_se_scale"] + assert set(sens) == set(persistence_backtest.SENSITIVITY) + s = artifact["summary"] + assert ( + s["static"]["mean_predictive_sd_pp"] + < s["static_fair"]["mean_predictive_sd_pp"] + < sens["static_fair_official_1p1"]["mean_predictive_sd_pp"] + ) + for row in sens.values(): + assert 0.0 <= row["coverage_50"] <= row["coverage_90"] <= 1.0 + + +def test_penalty_hashes_match_live_files(artifact) -> None: + hashes = artifact["input_hashes"] + for key, path in ( + ("fy2025_movement", "fy2025_movement.json"), + ("issuance_fy2024", "issuance_fy2024.json"), + ("persistence_results", "persistence_results.json"), + ): + live = hashlib.sha256((ROOT / "analysis" / path).read_bytes()).hexdigest() + assert hashes[key] == live, key + + +def test_memo_is_generated_from_the_artifact(artifact) -> None: + memo = (ROOT / "analysis" / "PERSISTENCE_BACKTEST.md").read_text() + assert memo == persistence_backtest._memo(artifact) + + +@pytest.mark.skipif( + not persistence_backtest.raw_inputs_available(), + reason="complete hash-audited mixed-format cache unavailable", +) +def test_raw_regeneration_matches_committed_artifact( + artifact, assert_artifact_values_match +) -> None: + regenerated = persistence_backtest.compute_artifact() + committed = {k: v for k, v in artifact.items() if k != "environment"} + fresh = {k: v for k, v in regenerated.items() if k != "environment"} + fresh = json.loads(json.dumps(fresh, sort_keys=True)) + committed = json.loads(json.dumps(committed, sort_keys=True)) + assert_artifact_values_match(fresh, committed, path="persistence_backtest")