Modernise OG-UK: new PolicyEngine API, 8-sector calibration, OBR-grounded TPI charts#63
Conversation
- Fix map_transition_to_real_world: use period-0 anchor scale factor so baseline levels carry the full growth path rather than collapsing to a flat constant each period - Add scripts/run_tpi_and_export.py: runs SS+TPI for baseline and a 1pp basic rate reform, exports results to tpi_results.xlsx with optional pre-2026 ONS/OBR historical rows (light yellow) prepended to the baseline sheet - Add scripts/tpi_charts_plotly.py: single-page 2×3 chart showing five variables as % of GDP and GDP in £bn; baseline = OBR Nov 2025 EFO outturn + forecast; reform = OBR baseline × TPI % change from model; dashed reform line only, grey dotted boundary at outturn/forecast split
Extend chart baseline back to 2000-01 by fetching ONS YBHA/NPQS/ABJQ calendar-year series and converting to fiscal years via the existing _fy_from_calendar() helper. OBR table 1.4/1.2 data takes priority from 2008-09 onwards; ONS rows are only prepended for earlier years. Also extend hardcoded _fy_tax_revenue() back to 2000-01 using HMRC outturn data, and update x-axis range to use HIST_START_FY constant.
- Recalibrate adjustment_factor_for_cit_receipts from 0.309 → 1.1785 to match UK CT/GDP ~3.3% (was underestimating at 0.8% using US default) - Add run_ct_and_export.py: SS+TPI for baseline (cit=0.27) and reform (cit=0.28), exports 3-sheet xlsx with historical actuals + model output - Add ct_charts_plotly.py: 6-panel interactive Plotly charts mapping model % changes onto OBR outturn/forecast baseline - Add ct_tpi_results.xlsx and rendered HTML charts - Add ct_reexport.py (interim correction script, now superseded) Dynamic GE estimate: CT +1pp raises ~£2.3-2.6bn/yr tax revenue vs HMRC static RR of £3.6-4.0bn, with ~£2bn/yr investment drag and £0.5-0.8bn GDP cost in OBR window.
Previously, marginal tax rates were computed by comparing total_income - income_tax before and after a £1 perturbation. This missed NI, UC taper, and benefit interactions — all of which affect the true net income change faced by a household. Switch to hbai_household_net_income (the HBAI poverty measure of disposable income), broadcast from household to person level via map_to_entity(..., how="project"). This captures the full tax-benefit wedge including NI, UC, and other means-tested interactions, giving accurate ETR and MTR estimates for the Gouveia-Strauss tax function estimation. Also remove stale dead-code lines (unused BW variable, a redundant frac_payroll assignment, and two inline comments) and fix years[i] formatting in run_oguk.py to handle fiscal-year string labels.
- Remove scripts/run_ct_and_export.py, ct_reexport.py, ct_charts_plotly.py, ct_charts_changes.html, ct_tpi_results.xlsx, tpi_results.xlsx (all CT +1pp experiment artifacts and binary outputs) - Fix F841: remove unused cons_m/inv_m/gov_m ONS fetches and derived _bn vars in map_transition_to_real_world (oguk/api.py) — only gdp_bn is used now - Fix F541: remove spurious f-prefix from Plotly hovertemplate strings (scripts/tpi_charts_plotly.py)
…m script - run_transition_path() now accepts param_overrides dict for structural parameter shocks (Z, cit_rate, etc.) without needing a PolicyEngine Policy - New scripts/productivity_headroom.py: estimates fiscal headroom from +0.1pp productivity growth via Z (TFP level) shock - Updated SKILL.md with param_overrides docs and g_y_annual warning
Splits the UK economy into 8 production industries calibrated from ONS Blue Book / Supply and Use Table data: Energy (B,D), Manufacturing (C), Construction (F), Trade & Transport (G,H,I), Info & Finance (J,K), Real Estate (L), Business Services (M,N), Public & Other (A,E,O-U). Key additions: - oguk/industry_params.py: sector definitions, GVA shares, capital shares (gamma), energy cost shares, c_min (subsistence consumption), and get_industry_params() returning OG-Core-ready parameters - SS solver switched to Levenberg-Marquardt (lm) for M>1 convergence - Identity I-O matrix (full inter-industry flows cause instability) - Capital shares shrunk toward mean for stability (raw real estate 0.92)
- Sort imports in __init__.py per isort rules (I001) - Rename `I` to `NUM_CONSUMPTION_GOODS` in industry_params.py (E741)
|
Just wanted to flag these points on the multi-sector calibration:
|
|
@vahid-ahmadi Thanks for flagging -- very good points to keep in mind. On your first point, about supply chains, that's right - other than the capital good, no outputs are used by inputs in other industries. This is a limitation from OG-Core. I think it should be updated when we build out trade in goods other than the capital good. |
…O matrix Replace uniform Cobb-Douglas (epsilon=1), flat TFP (Z=1), and identity IO matrix with sector-specific values grounded in ONS data and the capital-labour substitution literature (Chirinko 2008, Knoblach et al. 2020). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Shrink gamma 40% toward aggregate mean (0.35) inside get_industry_params() for solver stability; raw ONS values preserved in _GAMMA - Set epsilon to Cobb-Douglas (1.0) for all sectors: OG-Core TPI produces NaN with any heterogeneous CES elasticities (even 80% shrunk toward 1.0); raw literature values preserved in _EPSILON for future use - Solow-residual TFP (Z) and full IO matrix remain heterogeneous - Remove c_min from api.py strip list (no longer returned by get_industry_params) - Fix tpi_charts_plotly.py: align baseline/reform by fiscal year before computing % changes (baseline xlsx has 10 historical rows that reform lacks, causing row-index misalignment and spurious jumps) - Improve chart readability: horizontal x-axis labels, show every 5th year, rename TME to Gov. Consumption - Reduce Dask workers in run_tpi_and_export.py from os.cpu_count() to 2 with 4GB memory limit for stability Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Y_m, K_m, L_m, p_m (T×M) sector arrays to TransitionPathResult and extract them from OG-Core TPI output - Uncomment c_min in industry_params (required when I=8, was crashing) - Export 12 new sector sheets in tpi_results.xlsx: baseline levels, reform levels, and % changes for output, capital, labour, and prices - Add sector real-world charts to tpi_charts_plotly.py: ONS outturn from 2000 projected forward using OBR GDP growth, with reform line computed as baseline × (1 + model % change) — same approach as the macro charts, no stitching artefacts - Add sector % change summary charts (1×3 subplot) - Regenerated tpi_results.xlsx and tpi_charts.html with full sector data Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
OG-Core assumes the Mth industry produces the capital good. Manufacturing is the natural choice for the UK. Reorder all sector arrays: SECTOR_NAMES, gamma, epsilon, capital stock, workforce jobs, IO matrix (rows + columns), energy cost shares, c_min, and historical outturn data in tpi_charts_plotly.py. Addresses @jdebacker review comment on PR #63. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
These are generated output files that shouldn't be in the repo. Added to .gitignore. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This reverts commit 12f856b.
|
@nikhilwoodruff and @vahid-ahmadi (cc @jdebacker). This PR looks great. I just reviewed and approved it. The only recommendation I have is that we update the version in |
Per @rickecon's review: update version to 0.3.1 in pyproject.toml and oguk/__init__.py, and add CHANGELOG entry documenting the 8-sector multi-industry calibration additions in this PR.
|
Thanks- merging! |



Summary
This PR modernises OG-UK end-to-end: new PolicyEngine API integration, UK macro calibration, 8-sector industry model, and OBR-grounded transition path charts.
Core modernisation
8-sector industry calibration (oguk/industry_params.py)
OBR-grounded TPI charts (scripts/tpi_charts_plotly.py)
TPI export (scripts/run_tpi_and_export.py)
Key model results (1pp basic rate increase)
Test plan