model 01 — OBR macroeconometric model · obr-macro · UK · hosted
UK fiscal reform, quarter by quarter.
Run selected UK tax and spending scenarios and trace GDP, consumption, and investment over 3–5 years against the March 2026 EFO baseline. Borrowing is not yet returned by the PolicyEngine Macro adapter.
An open Python implementation of the OBR's published equations.
The OBR's model is a computational representation of the UK National Accounts — first built by HM Treasury in 1970 and jointly maintained by the OBR and the Treasury since 2010. The OBR publishes its full equation listing, but as EViews source that few can run. This project transpiles that listing to Python and solves it: 372 published equations in 17 thematic groups over 636 variables — 383 solved by the model (roughly 29 econometrically estimated, 216 identities, and 138 calibrated or technical relationships) and 253 exogenous inputs, which are the judgements and assumptions you get to change.
It is a structural macroeconometric model in the HM Treasury / Cowles-Commission tradition. Where the OLG model derives behaviour from optimising households and firms, this one reproduces the estimated relationships the official forecaster actually relies on.
papers/obr-macro/figures/current_outlook.csv.Transpile, solve, swap the closure.
| stage | what it does |
|---|---|
| Transpile | Rewrites every EViews line — dlog(), @elem, lags like X(-1), error-correction terms — into an equivalent Python expression, compiled once per solve. |
| Initialise | Loads history from the OBR's detailed forecast tables. Of the 261 endogenous variables the listing referenced but the outlook did not print, 199 had ONS series codes; a vendored 348-series ONS snapshot supplies them, giving the circular fiscal and financial sub-blocks real balancing data. |
| Gauss–Seidel solve | The equations depend on each other, so each quarter is solved simultaneously: cycle, update, repeat to convergence. Quarters then solve sequentially forward. A twelve-quarter anchored solve takes roughly 30–40 seconds single-threaded; a reform run is two such solves. |
| Anchor | Add-factors — the residuals reconciling each behavioural equation to data — are set so the baseline reproduces the published EFO. This is the OBR's own device, used the OBR's own way. |
| Closure swap | The GDP identity is switched off in the OBR file, so for a shock GDPM is swapped in and inventories (DINV) become the residual — output responds to the policy instead of being fixed. |
| Shock & compare | Solves shocked and baseline paths with identical structure and reports the difference, isolating the policy effect from the underlying forecast. |
For forecasting rather than one-off shocks, the emulator fits
add-factors over a base window of 2024Q1–2025Q4,
holds them constant, and projects to
2027Q4 with exogenous inputs extrapolated
(seasonal cash series at their trailing annual mean). Scenario solves run twelve quarters, 2025Q1–2027Q4.
The anchored horizon extends to 2031Q1 (GDP reproduced
to 0.29% at 2031Q1); anchored unemployment (LFSUR) is
unreliable beyond 2027Q4, drifting to 0.9% against the EFO's 4.1% by 2031Q1.
Shock a variable, read the deviation.
The package installs straight from GitHub — the equation listing, the March 2026 EFO forecast tables, and the ONS snapshot ship inside it, so there is no data step. A reform is one call: pick an exogenous variable, apply a shock, read the deviation from baseline.
pip install git+https://github.com/PolicyEngine/obr-macroeconomic-modelfrom obr_macro import run_reform
# £5bn/yr government spending shock (£1.25bn per quarter)
results = run_reform(
name="Fiscal Stimulus",
var="CGG", # government consumption (exogenous)
shock=1250, # £1.25bn per quarter, in £m
periods=12,
)
print(results[["period", "delta_gdp_bn", "pct_gdp"]])
# ΔGDP ≈ £1.25bn in the impact quarter, near-flat thereafter —
# under the demand closure the impact multiplier is ~1 by construction
two solves, so about a minute. run the five bundled scenarios with
charts via python -m obr_macro.reform_analysis — a £5bn
spending rise, a 5pp corporation-tax cut and rise, £10bn public
real investment (~£3bn nominal CGIPS per quarter), and a £10bn
austerity cut. Charts land in outputs/.
Reforms enter through the 253 exogenous inputs; results come out of the 383 the model solves. The test is simply whether a variable has its own equation. The most useful levers:
| code | variable | role & units |
|---|---|---|
CGG | Government consumption | exogenous — spending shocks, £m per quarter |
CGIPS | Central government investment (nominal) | exogenous — public investment, £m per quarter |
TCPRO | Corporation tax rate | exogenous — rate, e.g. −0.05 for a 5pp cut |
HHDI_ADDFACTOR | Externally costed household reform | virtual instrument — quarterly £m; positive revenue raised lowers HHDI through a held add-factor |
R / GILT / RX | Bank Rate · gilt yields · exchange rate | exogenous — monetary & market assumptions |
GDPM | GDP at market prices | endogenous — headline output |
CONS | Private consumption | endogenous |
IBUS / IF | Business / total investment | endogenous |
LFSUR | Unemployment rate | endogenous — rate, pp |
the full searchable glossary — all 636 codes with descriptions, ONS series and equations — is the model package's variable and equation references.
Second-round effects on a static costing.
The emulator's designed job is the second half of the official workflow: microsimulation supplies the direct Exchequer effect, the macro model supplies the economy-wide feedback. A static-costing bridge wires PolicyEngine's microsimulation into the emulator so a statutory reform can be scored end to end.
Worked example — 1p on the basic rate of income tax from April 2026,
scored 2026–2030. PolicyEngine puts the direct yield at
£6.46bn in 2026, rising to £7.38bn by
2030; HMRC's June 2025 ready reckoner puts 1p at £6.9bn in
2026–27 rising to about £8.2bn by 2028–29, so the static costing sits inside the
official range, toward its lower end. Converted to a positive quarterly
revenue-costing path of £1.62bn to £1.85bn, the
HHDI_ADDFACTOR adapter applies the corresponding negative
held add-factor to household disposable income. Propagated through the
consumption function, GDP falls 0.020% (−£0.14bn) on impact in
2026Q1, deepening to 0.058% (−£0.40bn) by 2027Q4 on the
March 2026 baseline — the sign
and order of magnitude the OBR's own indirect-effect conventions
imply.
Excellent anchored. Weak free-running. Both published.
There are three configurations and they earn very different levels of trust. Anchored is a by-construction invariant, not a forecast claim: the add-factors absorb the tracking error, which is exactly what anchoring means, and CI hard-fails the build if it slips.
| configuration | what it is | how it scores |
|---|---|---|
| Anchored | Add-factors on, matched to the March 2026 EFO. The configuration every reform score uses. | GDP 0.15% MAPE, consumption 0.25% over 2025Q1–2027Q4; the horizon extends to 2031Q1, where GDP is reproduced to 0.29% (anchored unemployment is unreliable beyond 2027Q4). Hard-gated in CI, alongside finiteness and a 0.5%-of-GDP expenditure-identity check. Structural sign invariants gated too. |
| Held add-factors | Add-factors fitted 2024Q1–2025Q4, held flat, projected to 2027Q4 — a genuine forecast. Scored over 2026Q1–2027Q4 on the March 2026 baseline. | GDP 0.37%, consumption 0.33%; 6 of 8 computed variables within band. (The working paper's November-2025-vintage scorecard, over its own longer window, reports GDP 2.2% and consumption 3.6%.) |
| 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. |
"In band" collapses per-metric thresholds — rates within 1.0pp, net balances within 1.5% of GDP, levels within 10% MAPE. Two caveats travel with the forecast configuration: it is initialised at the EFO values it is scored against, and its add-factor base window extends into quarters that are themselves OBR forecast rather than outturn, so the held add-factors partly encode "agree with the OBR". Full scorecards in the working paper; charts and source data in validation.
This is an independent implementation built from the OBR's published model code and forecast data. It is not produced, maintained, or endorsed by the Office for Budget Responsibility, and its results should not be presented as official OBR estimates.
What is broken, and what is merely absent.
| limit | detail |
|---|---|
| Two household-income equations never fire | The listing's only bare log() left-hand sides — log(HHTFA) and log(NDIVHH) — do not execute, because their right-hand-side inputs MAJGDP and CORP are absent from the databank entirely. The profits → dividends → household-income channel therefore does not run: a 5pp corporation-tax rise moves FYCPR by −£1,780m while ΔNDIVHH is exactly zero. A parser fix landed and is numerically inert; reviving the channel needs a CORP series, a calibration decision we have not made. Every published figure is computed with these channels inert. |
| Impact multiplier ~1 by construction | Under the demand closure a spending shock lands directly in the GDP identity and the behavioural second round is largely inactive. The OBR's published impact multiplier for current spending is 0.6. |
| Corporation-tax closure is specialised | The investment closure activates the published TCPRO → cost-of-capital → investment chain and is available through obr_shock. It reconstructs the business-investment equation from the OBR's commented, truncated published line, anchors its level with held add-factors, and freezes MSGVA, PIF, and PIRHH to a shared tracking path to prevent uncalibrated feedback. CI hard-gates the expected sign and a £50bn-per-quarter bound; this is a controlled scenario closure, not a fully calibrated supply block. |
| Passthrough channels | Exports, imports and CPI are exogenous in this setup, held at the OBR value. They score 0.00% error without being behavioural wins — 10 of 21 scorecard lines are passthroughs and are labelled as such. |
| Approximated add-factors | Recent corrections are averaged and held flat. The OBR's judgemental, quarter-by-quarter add-factors are not reproduced. |
| Vintage | October 2025 equation listing, March 2026 EFO, current-vintage ONS series. Where the ONS has revised history the identities don't close exactly, and that slack lands in the add-factors. The working paper's results remain a November 2025 EFO vintage study. |
| No behavioural micro | Aggregate equations only. Distributional questions belong to PolicyEngine. |