model 02 — OBR macroeconometric model

The OBR's own model, in Python.

A faithful emulator of the Office for Budget Responsibility's published macroeconomic model — 372 structural equations solved simultaneously, the model behind the OBR's official economic forecast. Run fiscal multipliers and tax shocks quarter by quarter, anchored to the official Economic and Fiscal Outlook.

01 — what it is

Not a stylized macro model — the actual one.

The OBR publishes the full equation listing of the model behind its forecasts, but as EViews source that few can run. This project transpiles that listing into Python and solves it, so the model behind the UK's official economic forecast becomes something you can open, shock, and inspect. It runs the OBR's 372 published equations from the October 2025 model code, complete with the accounting identities and behavioural relationships that tie the UK economy together.

This is a structural macroeconometric model — a large simultaneous system of estimated equations — a different lens from the overlapping-generations engine. Where the OLG model derives behaviour from optimising households and firms, this one reproduces the established empirical relationships the official forecaster relies on.

02 — quickstart

Shock a variable, read the multiplier.

Clone the repository and sync the environment — the model needs the bundled OBR equation listing and forecast data, so this one installs from a checkout rather than a bare wheel. Then a reform is one call: pick an exogenous variable, apply a shock, read the deviation from baseline.

git clone https://github.com/PolicyEngine/obr-macroeconomic-model
cd obr-macroeconomic-model && uv sync
from obr_macro import run_reform

# £5bn government spending shock (£1.25bn per quarter, 4 quarters)
results = run_reform(
    name="Fiscal Stimulus",
    var="CGG",        # government consumption (exogenous)
    shock=1250,        # £1.25bn per quarter
    periods=4,
)
print(results[["period", "delta_gdp_bn", "pct_gdp"]])

# a 5pp corporation tax cut, with the investment channel switched on
results = run_reform(
    name="Corp Tax Cut",
    var="TCPRO",       # corporation tax rate (exogenous)
    shock=-0.05,
    periods=12,
    investment_closure=True,
)

run the five bundled scenarios with charts: uv run python -m obr_macro.reform_analysis — a £5bn spending rise, corporation-tax cut and rise, £10bn public investment, and a £10bn austerity cut.

03 — how it works

Transpile, solve, swap the closure.

The engine has three moving parts, each a stage in turning a static equation listing into a live policy tool.

stagewhat it does
Transpiler Converts the OBR's EViews syntax into executable Python, equation by equation.
Gauss–Seidel solver Iterates over the ~370 equations until the simultaneous system converges each quarter — the standard method for large structural macro models.
Closure swap For a shock, inventories (DINV) become the residual and GDP becomes endogenous, so output responds to the policy instead of being fixed.
Deviation mode Solves the shocked and baseline paths and reports the difference, isolating the policy effect from the underlying forecast.
Of the 261 endogenous variables the published listing referenced but the OBR's outlook did not print, 199 had ONS series codes — pulling those observed series gave the circular fiscal and financial sub-blocks real balancing data and stopped them diverging.
04 — the levers

What you shock, what you read.

Reforms enter through the model's exogenous variables; the results come out of its endogenous aggregates. A few of the most useful:

codevariablerole
CGGGovernment consumptionexogenous — spending shocks
CGIPSCentral government investment (nominal)exogenous — public investment
TCPROCorporation tax rateexogenous — tax shocks
GDPMGDP at market pricesendogenous — headline output
CONSPrivate consumptionendogenous
IFTotal investmentendogenous
05 — forecasting

The OBR's own method: held add-factors.

Beyond one-off shocks, the emulator forecasts the way the OBR does: compute the residuals (add-factors) that reconcile the equations to recent data over a base window, hold them constant, and project forward. The result is the model's structural dynamics anchored by those held residuals — a genuine forecast, not a replay of the input.

06 — calibration

Held-add-factor forecast vs the OBR.

Scored against the OBR's published outlook over a projected window, the core real block tracks closely; the financial and profit blocks are harder and reported openly, not hidden.

real GDP 2.2% MAPE within band
consumption 3.6% MAPE within band
current account 0.9% of GDP within band

Held-add-factor forecast, base 2024Q1–2025Q4 projected to 2027Q4, versus the OBR. "Within band" collapses per-metric thresholds — rates within 1.0pp, net balances within 1.5% of GDP, levels within 10% MAPE. Business investment and company profits sit outside band and are documented in the repository's calibration scorecard rather than smoothed over.

Open the model behind the official forecast.