Predictive validation: weak.
- Free-running GDP and consumption MAPE are 5.75% and 9.56%; the anchored fit is by construction.
+ Free-running GDP and consumption MAPE are 4.48% and 7.49%; the anchored fit is by construction.
Policy counterfactuals: weak.
One income-tax costing is independently compared with HMRC; trade, labour, prices and parts of household income remain constrained.
Read the validation page →
diff --git a/index.html b/index.html
index 956bc79c..7fe326a9 100644
--- a/index.html
+++ b/index.html
@@ -210,7 +210,7 @@
What the evidence shows—and what it doesn't.
pe-microsimStatutory checks
PolicyEngine’s own tax–benefit microsimulation for the UK and US — the engine behind policyengine.org.
Rules are tested against statute; population totals inherit survey uncertainty. It cannot answer GDP, inflation, interest rates or macro feedback — that is what the models below add.
-
obr-macroAnchored replication
Emulator of the OBR’s UK macroeconometric forecast model.
Tracks the March 2026 EFO to 0.15% GDP MAPE with published anchors; free-running error is 5.75%.
+
obr-macroAnchored replication
Emulator of the OBR’s UK macroeconometric forecast model.
Tracks the March 2026 EFO to 0.15% GDP MAPE with published anchors; free-running error is 4.48%.
boe-svarForecast evaluation
Bank of England structural VAR separating global and domestic shocks.
Reproduces the published decomposition for GDP (37.4% vs ~40%) and falls about 8pp short on CPI (42.3% vs ~50%) once measured the way the paper defines it. Against a random walk with drift, and after adjusting for the 64 tests run, no variable at any horizon shows skill. See the evaluation →
frb-usSoftware replication
The Federal Reserve’s large-scale model of the US economy.
Matches the Fed’s pyfrbus to within the Fed’s own two releases’ disagreement (~1×10⁻⁸); no predictive claim.
us-hankPublished replication
Heterogeneous-agent New Keynesian model of US households.
Hits every Auclert et al. (2021) calibration target; responses are first-order and stylized.
diff --git a/integration/modal_app.py b/integration/modal_app.py
index cd267f7d..5cafb30b 100644
--- a/integration/modal_app.py
+++ b/integration/modal_app.py
@@ -129,7 +129,7 @@
BOE_URL = "https://github.com/PolicyEngine/boe-var-model"
FRB_URL = "https://github.com/PolicyEngine/us-frb-model"
HANK_URL = "https://github.com/PolicyEngine/us-hank-model"
-OBR_REVISION = "85ada9be070a34a4a4a0a65d92f8f148a476ccb1"
+OBR_REVISION = "9c4b595f3b60b305459ba8c91eac5bc69fd0ffc8"
BOE_REVISION = "42cbcbb728b55b3f416764568fa8f3aef68a6730"
FRB_REVISION = "2508a2d3ee7d078fd82f38bc17567e4433489913"
HANK_REVISION = "19a8e5e5cd8e7120fbbd2e3de3c5b63509824f3c"
diff --git a/integration/pyproject.toml b/integration/pyproject.toml
index b8a909e9..1bb8d538 100644
--- a/integration/pyproject.toml
+++ b/integration/pyproject.toml
@@ -49,7 +49,7 @@ Issues = "https://github.com/PolicyEngine/macro/issues"
# particular, frbus includes model.xml and LONGBASE.TXT inside its wheel, so a
# clean non-editable installation is a supported access path.
models = [
- "obr-macro-model @ git+https://github.com/PolicyEngine/obr-macroeconomic-model@85ada9be070a34a4a4a0a65d92f8f148a476ccb1",
+ "obr-macro-model @ git+https://github.com/PolicyEngine/obr-macroeconomic-model@9c4b595f3b60b305459ba8c91eac5bc69fd0ffc8",
"boe_var @ git+https://github.com/PolicyEngine/boe-var-model@42cbcbb728b55b3f416764568fa8f3aef68a6730",
"frbus @ git+https://github.com/PolicyEngine/us-frb-model@2508a2d3ee7d078fd82f38bc17567e4433489913",
"us-hank-model @ git+https://github.com/PolicyEngine/us-hank-model@19a8e5e5cd8e7120fbbd2e3de3c5b63509824f3c",
diff --git a/integration/src/policyengine_macro/capabilities.py b/integration/src/policyengine_macro/capabilities.py
index b306b4e2..01357f4d 100644
--- a/integration/src/policyengine_macro/capabilities.py
+++ b/integration/src/policyengine_macro/capabilities.py
@@ -204,7 +204,7 @@ def _quality(level: str, evidence: str, next_gate: str) -> dict:
),
"predictive_validation": _quality(
"weak",
- "Free-running GDP and consumption MAPE are 5.75% and 9.56%; the "
+ "Free-running GDP and consumption MAPE are 4.48% and 7.49%; the "
"anchored fit is by construction.",
"Pass rolling-origin historical-vintage tests against simple "
"benchmarks and first-release outturns.",
diff --git a/integration/src/policyengine_macro/core.py b/integration/src/policyengine_macro/core.py
index d8c01edb..587fec1b 100644
--- a/integration/src/policyengine_macro/core.py
+++ b/integration/src/policyengine_macro/core.py
@@ -136,12 +136,33 @@ def _import_boe_var():
"description": "Corporation tax (main) rate",
"units": "rate change in decimal (e.g. -0.05 = 5pp cut from 25% to 20%)",
"investment_closure": True,
+ # The investment closure's stabiliser anchors the LEVEL, not the
+ # deviation, and the deviation does not converge at any horizon: for a
+ # sustained +5pp rise |delta_IF| runs £97m at q3, £2,876m at q12 and
+ # £43,387m at q25, growing 1.21-1.27x every quarter for 25 quarters.
+ # Truncating the shock from 12 quarters to 8 barely moves the q12
+ # response, so the number is carried by accumulated drift rather than
+ # by the tax rate. The 12-quarter default is not where this settles;
+ # it is where the magnitude still looks plausible.
+ "caveat": (
+ "the response does not converge: it compounds at roughly "
+ "25%/quarter with no steady state, so read the sign and the "
+ "first few quarters, not the level or the cumulative total"
+ ),
},
{
"var": "CGIPS",
"description": "Nominal central government investment (feeds real GGI via the GGIPS/GGIDEF chain)",
"units": "£m nominal per quarter (e.g. 3000 ≈ £2.5bn real per quarter)",
"investment_closure": False,
+ # Measured: delta_IF is exactly 0.0 in all twelve quarters and the
+ # residual GDP effect goes negative (-0.047 by q12) against the OBR's
+ # published 1.0. The channel is not weak, it is absent.
+ "caveat": (
+ "this channel is dead under the demand closure: business "
+ "investment does not respond at all and the residual GDP effect "
+ "is wrong-signed. Do not use it to score capital spending"
+ ),
},
]
@@ -203,7 +224,16 @@ def obr_shock(
rows = _obr_result_rows(df)
shocked = rows[: int(periods)]
peak = max(rows, key=lambda r: abs(r["pct_gdp"]))
- return {
+ # A lever whose channel is dead or non-convergent must say so in the
+ # payload, not only in a docstring nobody reads over MCP. Of the four
+ # fiscal instruments here exactly one contains behaviour: CGG is an
+ # accounting identity (multiplier exactly 1.0000, flat, against the OBR's
+ # published 0.6), CGIPS is dead, TCPRO never converges, and the
+ # household-income lever is the only one with a response worth reading.
+ caveat = next(
+ (v.get("caveat") for v in OBR_VARIABLES if v["var"] == var), None
+ )
+ result = {
"name": name,
"provenance": _provenance(
model_id="obr-emulator",
@@ -222,6 +252,9 @@ def obr_shock(
"peak_pct_gdp": peak["pct_gdp"],
"peak_period": peak["period"],
}
+ if caveat:
+ result["caveat"] = caveat
+ return result
# ---------------------------------------------------------------------------
diff --git a/integration/tests/test_wiring.py b/integration/tests/test_wiring.py
index 6d249521..6b8cfb90 100644
--- a/integration/tests/test_wiring.py
+++ b/integration/tests/test_wiring.py
@@ -404,3 +404,22 @@ def test_cli_score_still_rejects_a_genuinely_unknown_model(runner):
assert res.exit_code != 0
assert "Traceback" not in res.output
assert "model must be one of" in res.output
+
+
+def test_obr_shock_carries_the_lever_caveat_in_the_payload():
+ """Two of the four OBR levers do not work, and the payload must say so.
+
+ Measured in the model repo: CGIPS moves business investment by exactly
+ zero in all twelve quarters and leaves a wrong-signed residual, and TCPRO
+ compounds at roughly 25%/quarter with no steady state. A docstring does
+ not reach an MCP caller reading a JSON result, so the caveat travels with
+ the numbers.
+ """
+ from policyengine_macro import core
+
+ levers = {v["var"]: v for v in core.obr_list_variables()}
+ assert levers["TCPRO"]["caveat"], "the non-convergent lever declares no caveat"
+ assert levers["CGIPS"]["caveat"], "the dead lever declares no caveat"
+ # CGG has its own documented "~1 by construction" reading on the site and
+ # is not caveated here; asserting that keeps this test honest about scope.
+ assert "caveat" not in levers["CGG"]
diff --git a/obr/code/index.html b/obr/code/index.html
index 3716e050..54f8766b 100644
--- a/obr/code/index.html
+++ b/obr/code/index.html
@@ -170,8 +170,8 @@
Shock a variable, read the deviation.
levers — set these (exogenous)
CGGGovernment consumption — spending shocks, £m per quarter
-
CGIPSCentral government investment — public investment, £m per quarter (nominal)
-
TCPROCorporation tax rate — rate, e.g. −0.05 for a 5pp cut
+
CGIPSCentral government investment — public investment, £m per quarter (nominal). Dead channel: business investment does not respond at all and the residual GDP effect is wrong-signed, against the OBR’s published 1.0. Do not score capital spending with it
+
TCPROCorporation tax rate — rate, e.g. −0.05 for a 5pp cut. Does not converge: the response compounds at roughly 25% a quarter with no steady state, so read the sign and the first few quarters, never the level or the cumulative total
HHDI_ADDFACTORExternally costed household reform — virtual instrument, quarterly £m; positive revenue lowers HHDI via a held add-factor
R / GILT / RXBank Rate · gilt yields · exchange rate — monetary & market assumptions
@@ -218,8 +218,8 @@
Shock a variable, read the deviation.
levers — set these (exogenous)
CGGGovernment consumption — spending shocks, £m per quarter
-
CGIPSCentral government investment — public investment, £m per quarter (nominal)
-
TCPROCorporation tax rate — rate, e.g. −0.05 for a 5pp cut
+
CGIPSCentral government investment — public investment, £m per quarter (nominal). Dead channel: business investment does not respond at all and the residual GDP effect is wrong-signed, against the OBR’s published 1.0. Do not score capital spending with it
+
TCPROCorporation tax rate — rate, e.g. −0.05 for a 5pp cut. Does not converge: the response compounds at roughly 25% a quarter with no steady state, so read the sign and the first few quarters, never the level or the cumulative total
HHDI_ADDFACTORExternally costed household reform — virtual instrument, quarterly £m; positive revenue lowers HHDI via a held add-factor
R / GILT / RXBank Rate · gilt yields · exchange rate — monetary & market assumptions
Microsimulation supplies the direct cost; this model returns the feedback.
→Connection. Static-costing bridge, both hosted: PolicyEngine computes the direct Exchequer effect of a statutory reform; score_reform injects it through the declared HHDI_ADDFACTOR point and this model returns the economy-wide second round.
→Worked example. 1p on the basic rate from April 2026: direct yield £6.46bn in 2026; GDP −0.020% on impact, deepening to −0.058% by 2027Q4 (full walkthrough → score a reform).
-
→Validation.Anchored to the March 2026 EFO (0.15% GDP MAPE) — but anchored accuracy is a by-construction invariant, not a forecast claim: free-running, the same equations miss GDP by 5.75%. Checked against HMRC’s ready reckoner (£6.46bn vs £6.9bn).
+
→Validation.Anchored to the March 2026 EFO (0.15% GDP MAPE) — but anchored accuracy is a by-construction invariant, not a forecast claim: free-running, the same equations miss GDP by 4.48%. Checked against HMRC’s ready reckoner (£6.46bn vs £6.9bn).
→Results. Run it from any connected client; every score carries its assumptions and data vintage.
Excellent anchored. Weak free-running. Both published.
free-running
- 5.75% MAPE
+ 4.48% MAPEreal GDP; 4 of 11 computed in band — report-only
@@ -126,7 +126,7 @@
Excellent anchored. Weak free-running. Both published.
Free-running
De-seeded, add-factors off. The raw structural dynamics with no OBR judgement.
-
Weak, and reported as such. GDP 5.75%, consumption 9.56%, household income 14.15%, business investment 16.12%, company profits 79.80%. The model contracts 1–2%/yr while the EFO grows.
+
Weak, and reported as such. GDP 4.48%, consumption 7.49%, household income 6.27%, business investment 15.73%, company profits 63.29%. The model contracts while the EFO grows.
@@ -282,7 +282,7 @@
Against the OBR's own forecast, and HMRC's reckoner.
@@ -327,35 +327,39 @@
Against the OBR's own forecast, and HMRC's reckoner.
The honest scorecard. The free-running row is the one
that matters for anyone tempted to read the 0.15% as forecasting skill.
The same equations that track the EFO to 0.15% when anchored miss it
- by 5.75% free-running — precisely the gap the OBR's
+ by 4.48% free-running — precisely the gap the OBR's
own add-factor judgement closes in the official process, and the
reason reform deltas are always scored against the anchored baseline
rather than the raw one. The free-running score is de-seeded, with
passthrough variables excluded, and is published report-only.
- Across the full scorecard only 4 of the 11 computed headline
- variables land within band (real GDP, consumption, the trade
- balance, and the trivial employment identity); of the full 21-line
- scorecard, 10 lines are passthroughs held at the OBR value. The
- worst line is company profits at 79.80% MAPE on the
- March baseline (54.57% on the paper's November vintage), which
+ Across the full scorecard 6 of the 11 computed headline
+ variables land within band (real GDP, consumption, both
+ household-income lines, the trade balance, and the trivial employment
+ identity); of the full 21-line scorecard, 10 lines are passthroughs
+ held at the OBR value. The
+ worst line is company profits at 63.29% MAPE on the
+ March baseline, which
traces to a single unpublished constant in households' operating
surplus OSHH — the paper documents and regression-gates
it rather than re-tuning it, since tuning it would be fitting to the
answer. Other lines that moved on re-anchoring, reported rather than
smoothed: the free-running current account widened from 2.76 to
- 4.17% of GDP and is now over band; RPI improved from
- 2.03pp to 1.71pp; business investment worsened from
- 15.48% to 16.12%; the two household-income
- lines stand at 14.15% and 13.86%.
+ 3.60% of GDP and is now over band; RPI improved from
+ 2.03pp to 1.71pp; business investment stands at
+ 15.73%; the two household-income lines stand at
+ 6.27% and 6.03%. Every figure in this paragraph moved when the
+ OSHH ONS anchor landed upstream, and this page had gone
+ on publishing the pre-anchor ones — which understated the model's
+ accuracy on every line.
- Current March 2026 EFO baseline. Real GDP, £bn/qtr, 2025Q1–2027Q4. The anchored path (0.15% MAPE) sits on top of the EFO; the same equations free-running — de-seeded, no add-factors — contract away from it (5.75% MAPE). Computed from papers/obr-macro/figures/fig_free_running_data.csv and fig_anchored_data.csv, regenerated on 21 July 2026.
+ Current March 2026 EFO baseline. Real GDP, £bn/qtr, 2025Q1–2027Q4. The anchored path (0.15% MAPE) sits on top of the EFO; the same equations free-running — de-seeded, no add-factors — contract away from it (4.48% MAPE). Computed from papers/obr-macro/figures/fig_free_running_data.csv and fig_anchored_data.csv, regenerated on 12 August 2026.
Forecast versus outturn. Comparing one forecast
diff --git a/papers/obr-macro/figures/fig_free_running.pdf b/papers/obr-macro/figures/fig_free_running.pdf
index 9c79a02c..c90e865b 100644
Binary files a/papers/obr-macro/figures/fig_free_running.pdf and b/papers/obr-macro/figures/fig_free_running.pdf differ
diff --git a/papers/obr-macro/figures/fig_free_running_data.csv b/papers/obr-macro/figures/fig_free_running_data.csv
index b9dca0f6..ab49d71a 100644
--- a/papers/obr-macro/figures/fig_free_running_data.csv
+++ b/papers/obr-macro/figures/fig_free_running_data.csv
@@ -1,13 +1,13 @@
,GDPM_model,CONS_model,HHDI_model,GDPM_efo,CONS_efo,HHDI_efo
-2025Q1,690992.9612408569,415663.1861982189,395470.8554215652,703435.0,429345.0,483896.0
-2025Q2,690064.4574558692,414284.7278124491,456827.6520898548,704973.0,429692.0,489329.0
-2025Q3,682504.9053481992,407321.4208021562,442651.91540539387,705603.0,431309.0,489031.0
-2025Q4,679217.7429655327,403300.7917593888,450856.9087182827,706873.0854,431735.996,493761.36
-2026Q1,669335.0796969897,392016.10911167425,380694.5880951302,709064.39196474,432363.521,497806.675
-2026Q2,670743.7904103745,392085.3213201746,431117.9577943034,711475.2108974202,433402.28,501643.436
-2026Q3,668452.3099806694,388486.23361647705,431763.6280174015,714178.8166988303,434670.508,504904.318
-2026Q4,666785.4735566229,385390.4601104848,433531.1783981844,717142.6587881305,436147.044,508289.706
-2027Q1,665595.0499860753,383057.54290709173,435672.94582449965,720047.0865562225,437846.999,511577.507
-2027Q2,664683.2112467056,381182.5306251082,438067.19693830475,722869.6711355229,439649.831,514949.525
-2027Q3,663653.83081479,379252.61883668625,440333.4402611372,725688.8628529514,441508.475,518417.48900000006
-2027Q4,663080.9377536196,377752.83704250376,443020.67862184666,728562.5907498491,443414.728,521864.0829999999
+2025Q1,694404.6301766383,419074.85513400025,428871.49559585686,703435.0,429345.0,483896.0
+2025Q2,694493.7051226624,418713.97547924233,492096.16673654737,704973.0,429692.0,489329.0
+2025Q3,688118.2699442019,412934.785398159,479946.9522647471,705603.0,431309.0,489031.0
+2025Q4,685583.2721162075,409666.3209100636,494601.9543338685,706873.0854,431735.996,493761.36
+2026Q1,678334.1920101173,401015.2214248019,427518.02423624403,709064.39196474,432363.521,497806.675
+2026Q2,680495.7841757275,401837.3150855276,472253.41553964955,711475.2108974202,433402.28,501643.436
+2026Q3,678933.6826921239,398967.60632793163,472489.3885262448,714178.8166988303,434670.508,504904.318
+2026Q4,677792.5151012673,396397.50165512913,474696.4595384664,717142.6587881305,436147.044,508289.706
+2027Q1,677128.2532110797,394590.7461320963,477084.4862161981,720047.0865562225,437846.999,511577.507
+2027Q2,676679.6257150497,393178.9450934523,478879.5400344412,722869.6711355229,439649.831,514949.525
+2027Q3,676024.8513143926,391623.6393362889,481110.3763989253,725688.8628529514,441508.475,518417.48900000006
+2027Q4,675802.5728209037,390474.4721097879,483681.23482099245,728562.5907498491,443414.728,521864.0829999999
diff --git a/validation/figures/chart_data.json b/validation/figures/chart_data.json
index a6843e28..29c1792c 100644
--- a/validation/figures/chart_data.json
+++ b/validation/figures/chart_data.json
@@ -1,134 +1,140 @@
{
- "_comment": "Values that are NOT machine-readable in papers/*/figures/ are transcribed here from the papers' LaTeX sources, with an explicit source pointer per value. Everything else is read directly from the papers' committed CSV/JSON data by make_charts.py. Do not edit a number here without changing the cited source.",
- "obr_reform": {
- "source": "papers/obr-macro/sections/comparison.tex, Table tab:comparison panel B (cross-checked against papers/obr-macro/sections/results.tex)",
- "groups": [
- {
- "label": "basic rate +1pp, 2026–27",
- "bars": [
- {
- "name": "ours",
- "value": 6.46,
- "series": 1,
- "source": "comparison.tex panel B / results.tex L18 (PolicyEngine static costing)"
- },
- {
- "name": "HMRC",
- "value": 6.9,
- "series": 2,
- "source": "comparison.tex panel B; HMRC Direct effects of illustrative tax changes, June 2025"
- }
- ]
- },
- {
- "label": "basic rate +1pp, 2028–29",
- "bars": [
- {
- "name": "ours",
- "value": 6.92,
- "series": 1,
- "source": "comparison.tex panel B; interpolated between scored endpoints 6.46 (2026) and 7.38 (2030)"
- },
- {
- "name": "HMRC",
- "value": 8.2,
- "series": 2,
- "source": "comparison.tex panel B; HMRC June 2025 reckoner"
- }
- ]
- }
+ "_comment": "Values that are NOT machine-readable in papers/*/figures/ are transcribed here from the papers' LaTeX sources, with an explicit source pointer per value. Everything else is read directly from the papers' committed CSV/JSON data by make_charts.py. Do not edit a number here without changing the cited source.",
+ "obr_reform": {
+ "source": "papers/obr-macro/sections/comparison.tex, Table tab:comparison panel B (cross-checked against papers/obr-macro/sections/results.tex)",
+ "groups": [
+ {
+ "label": "basic rate +1pp, 2026\u201327",
+ "bars": [
+ {
+ "name": "ours",
+ "value": 6.46,
+ "series": 1,
+ "source": "comparison.tex panel B / results.tex L18 (PolicyEngine static costing)"
+ },
+ {
+ "name": "HMRC",
+ "value": 6.9,
+ "series": 2,
+ "source": "comparison.tex panel B; HMRC Direct effects of illustrative tax changes, June 2025"
+ }
]
- },
- "obr_computed_share": {
- "source": "docs/calibration_scorecard.md in the PolicyEngine/obr-macroeconomic-model repository (March 2026 EFO vintage calibration scorecard); counts cross-checked against papers/obr-macro/sections/calibration.tex Table tab:rawscore (preserved November 2025 study)",
- "total": 21,
- "computed": 11,
- "passthrough": 10,
- "bands_note": "bands: rates ±1.0pp · net balances ±1.5% of GDP · levels ≤10% MAPE",
- "_grades_comment": "The 11 computed variables graded against the bands above. 'identity' is employment, where both inputs are themselves passthrough, so the accounting identity closes trivially and the pass carries no information.",
- "grades": [
- {
- "key": "fair",
- "label": "fair",
- "count": 3,
- "series": 1,
- "in_band": true,
- "examples": [
- "real GDP 5.75 per cent",
- "consumption 9.56 per cent",
- "trade balance 0.70 per cent of GDP"
- ],
- "source": "calibration_scorecard.md, free-running MAPE column"
- },
- {
- "key": "identity",
- "label": "identity",
- "count": 1,
- "series": 2,
- "in_band": true,
- "trivial": true,
- "examples": [
- "employment"
- ],
- "source": "calibration_scorecard.md; employment closes from two passthrough inputs"
- },
- {
- "key": "poor",
- "label": "poor",
- "count": 5,
- "series": 3,
- "in_band": false,
- "examples": [],
- "source": "calibration_scorecard.md, variables outside band but within an order of magnitude"
- },
- {
- "key": "off",
- "label": "off",
- "count": 2,
- "series": 3,
- "in_band": false,
- "examples": [
- "company profits 79.80 per cent",
- "the current account 4.17 per cent of GDP"
- ],
- "source": "calibration_scorecard.md, worst two computed variables"
- }
+ },
+ {
+ "label": "basic rate +1pp, 2028\u201329",
+ "bars": [
+ {
+ "name": "ours",
+ "value": 6.92,
+ "series": 1,
+ "source": "comparison.tex panel B; interpolated between scored endpoints 6.46 (2026) and 7.38 (2030)"
+ },
+ {
+ "name": "HMRC",
+ "value": 8.2,
+ "series": 2,
+ "source": "comparison.tex panel B; HMRC June 2025 reckoner"
+ }
]
- },
- "frbus_residuals": {
- "source": "papers/frb-us/sections/validation.tex, Tables tab:tracking and tab:refnoise",
- "rows": [
- {
- "label": "ours vs LONGBASE (identity — not evidence)",
- "value": 5.6e-17,
- "series": 1,
- "source": "validation.tex tab:tracking, max abs error",
- "note": "init_trac defines add-factors as minus the residuals at the input data, so re-solving reproduces it up to float64 for ANY input — verified: the same test passes at 6.7e-9 on randomly scrambled data. Shown for completeness; it measures arithmetic, not economics."
- },
- {
- "label": "pyfrbus 1.1.1 vs LONGBASE",
- "value": 1.1e-08,
- "series": 3,
- "source": "validation.tex subsec:refnoise prose"
- },
- {
- "label": "ours vs pyfrbus 1.0.0 (shock)",
- "value": 6e-09,
- "series": 1,
- "source": "validation.tex tab:refnoise row 1"
- },
- {
- "label": "ours vs pyfrbus 1.1.1 (shock)",
- "value": 1.4e-08,
- "series": 1,
- "source": "validation.tex tab:refnoise row 2"
- },
- {
- "label": "pyfrbus 1.1.1 vs 1.0.0 — the Fed’s own two releases",
- "value": 1.3e-08,
- "series": 2,
- "source": "validation.tex tab:refnoise row 3"
- }
- ]
- }
+ }
+ ]
+ },
+ "obr_computed_share": {
+ "source": "docs/calibration_scorecard.md in the PolicyEngine/obr-macroeconomic-model repository, regenerated 2026-08-12 after the OSHH ONS anchor landed (PR #22); the previous figures here predated that anchor and understated the model's accuracy across the board",
+ "total": 21,
+ "computed": 11,
+ "passthrough": 10,
+ "bands_note": "bands: rates \u00b11.0pp \u00b7 net balances \u00b11.5% of GDP \u00b7 levels \u226410% MAPE",
+ "_grades_comment": "The 11 computed variables graded against the bands above. 'identity' is employment, where both inputs are themselves passthrough, so the accounting identity closes trivially and the pass carries no information.",
+ "grades": [
+ {
+ "key": "fair",
+ "label": "fair",
+ "count": 5,
+ "series": 1,
+ "in_band": true,
+ "examples": [
+ "real GDP 4.48 per cent",
+ "consumption 7.49 per cent",
+ "household income 6.27 per cent",
+ "real household income 6.03 per cent",
+ "trade balance 0.69 per cent of GDP"
+ ],
+ "source": "calibration_scorecard.md, free-running MAPE column"
+ },
+ {
+ "key": "identity",
+ "label": "identity",
+ "count": 1,
+ "series": 2,
+ "in_band": true,
+ "trivial": true,
+ "examples": [
+ "employment"
+ ],
+ "source": "calibration_scorecard.md; employment closes from two passthrough inputs"
+ },
+ {
+ "key": "poor",
+ "label": "poor",
+ "count": 3,
+ "series": 3,
+ "in_band": false,
+ "examples": [
+ "business investment 15.73 per cent",
+ "the unemployment rate 1.01 percentage points",
+ "RPI inflation 1.71 percentage points"
+ ],
+ "source": "calibration_scorecard.md, variables outside band but within an order of magnitude"
+ },
+ {
+ "key": "off",
+ "label": "off",
+ "count": 2,
+ "series": 3,
+ "in_band": false,
+ "examples": [
+ "company profits 63.29 per cent",
+ "the current account 3.60 per cent of GDP"
+ ],
+ "source": "calibration_scorecard.md, worst two computed variables"
+ }
+ ]
+ },
+ "frbus_residuals": {
+ "source": "papers/frb-us/sections/validation.tex, Tables tab:tracking and tab:refnoise",
+ "rows": [
+ {
+ "label": "ours vs LONGBASE (identity \u2014 not evidence)",
+ "value": 5.6e-17,
+ "series": 1,
+ "source": "validation.tex tab:tracking, max abs error",
+ "note": "init_trac defines add-factors as minus the residuals at the input data, so re-solving reproduces it up to float64 for ANY input \u2014 verified: the same test passes at 6.7e-9 on randomly scrambled data. Shown for completeness; it measures arithmetic, not economics."
+ },
+ {
+ "label": "pyfrbus 1.1.1 vs LONGBASE",
+ "value": 1.1e-08,
+ "series": 3,
+ "source": "validation.tex subsec:refnoise prose"
+ },
+ {
+ "label": "ours vs pyfrbus 1.0.0 (shock)",
+ "value": 6e-09,
+ "series": 1,
+ "source": "validation.tex tab:refnoise row 1"
+ },
+ {
+ "label": "ours vs pyfrbus 1.1.1 (shock)",
+ "value": 1.4e-08,
+ "series": 1,
+ "source": "validation.tex tab:refnoise row 2"
+ },
+ {
+ "label": "pyfrbus 1.1.1 vs 1.0.0 \u2014 the Fed\u2019s own two releases",
+ "value": 1.3e-08,
+ "series": 2,
+ "source": "validation.tex tab:refnoise row 3"
+ }
+ ]
+ }
}