Two-universe calibration (ONS frame + HMRC registered subset), full regeneration, and paper revision - #46
Merged
Merged
Conversation
…gistered subset (#37) Data: rebuild the ONS tables from the raw workbooks with scripts/etl_ons_tables.py (Table 8 turnover, Table 3 employment, both enterprises). The 2023-24 employment CSV had reproduced Table 18 (local units, 3,173,660 sites); the 2024-25 tables came from a different sheet with rounding differences. A test asserts the two tables agree to disclosure rounding and that the CSVs match the ETL. Calibration: every target row is declared on one universe. Frame rows (population, employment, near-threshold shape) contribute 1 for ONS-frame enterprises and 0 for the HMRC negative/zero traders, which are now appended BEFORE calibration; HMRC rows (all 8 turnover bands, sectors, liability by band) contribute a per-band registration propensity p_b = HMRC count / frame mass (0.89 below the threshold, 0.51-1.00 above). The population target is the full ONS total; the employment targets partition it. Flags: assign_vat_flags returns (vat_scope, vat_registered) by seeded weighted selection per band to the HMRC counts; below the threshold every frame firm is registrable and the HMRC count is registered. Output gains vat_scope and in_frame columns. Consumers: validate/report score HMRC dimensions on registered rows and ONS dimensions on frame rows; static, dynamic, reform-menu and dominated-region code price in-scope firms only. Static model: turnover and liability are aged together against nominal thresholds, growth is indexed to each vintage's data year, baseline voluntary registrants stay registered, and a threshold rise releases firms only below the deregistration threshold (gap £2,000). Also: flat-50% marginal taper variant sharing the linear design's £141,667 band top; marginal buncher reported for delta in {0, 0.4, 0.6}; dynamic results note derived from the table; make reproduce target; README updates. Refs #37, #39, #40, #32. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…with the checked artifact The width a = T*·tau/(1-tau) is proportional to the threshold, so raising T* to £100,000 widens the dominated region to £25,000 (£100k–£125k); the text said the £21,250 band was "transported" unchanged. Cascade the correction to the intro, static section and conclusion. Replace the reduced-rate primary/secondary band counts, which came from an older run, with the values in results/dominated_region_mass.txt, and use one baseline count (156,700) instead of 157,000 and 147,700 in the same section. Round £21,562.50 to £21,563. Refs #32 (finding 2, minor 1), #40. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…he code defines them Section 6 described a mass-conservation restriction that locates y_R endogenously and wrote excess bunching as the integral of the counterfactual density. The code sums the positive part of f_obs - f_cf below the threshold for E, searches for y_R only up to the window edge (censored at £100k in the headline run, where Delta_R = 0), and normalises b_LLAT over both sides of the threshold. Say so, and drop the b ≈ Δy*/y* relation that matches neither statistic. Refs #38, #32 (finding 5). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…to the region-confined convention With deductible share delta the untaxed optimum is n(1-delta)^e, not n, so say so and align the ability-recovery statement with the flat-optimum equation (and note the code sets delta = 0 in the anchor). Recast the "every potential crosser optimally stops at the new threshold" paragraph: the region-confined solve clips released firms at the new notch by construction, so the invariance is a property of the maintained status convention, not a computed global-optimum result. Refs #39, #32 (finding 4). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… table, drop orphan bib entry Replace "the honest reading" and "spectacular" with neutral wording; point Figure 1(a) at the ONS 2024 bulletin and name the table (the input is the 2024 workbook, not 2023); add the reduced-rate costs and the bunching readback to the conclusion's summary table; remove the uncited keenmintz2004 entry. Refs #41, #32 (minor 7, 9, 11), #8. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…paper Static model: explicit registration rule (in-scope firms registered at/above the threshold; data-year registrants retained down to the £2,000 deregistration gap; voluntary registrants unchanged where never required; fixed-preference and LLAT-retention conventions as labelled sensitivities); anchor differences the two regimes each year. Dynamic layer drops out-of-scope rows; marginal buncher solved under formulation A with the unregistered choice capped at the threshold. Sector targets allocate HMRC's 'Unknown' turnover band proportionally. The dominated- region artifact labels its in-scope E separately from the Section 6 frame E. Regenerated: synthetic populations (not committed), calibration report, static sweep and anchor, bunching inference and figures, notch, dynamic results and figures, reform menu, dominated-region masses, verification reports, recovery test, seed sensitivity; figures synced to paper/figures. Paper: data section rewritten around the two universes (Table 3/8 enterprise units, registration propensity, scope and registration flags, calibration table in Appendix A); static section restated with the registration rule, ageing convention, deregistration threshold, anchor sensitivities, frame-confined cut rows, and the constant-50% taper alongside the linear design; dominated-region section gives the U(m) band-top frontier; behavioural section reports n_H(e, delta); bunching section adds the 2024-25 coarse-band readback; intro/conclusion/summary table renumbered; literature on size-based thresholds and firm microsimulation added. Paper workflow now uploads the rendered PDF as an artifact. Closes #37. Refs #32, #38, #39, #40, #41. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This was referenced Sep 4, 2026
…al run, resync static figures The displayed R(T) now matches StaticVATModel._registered (voluntary registrants unchanged only where never required; data-year registrants gap-protected). The anchor prose and Figure 4 caption describe the headline that overshoots HMRC in every release year rather than the superseded fixed-preference run. Static figures re-synced after the last rule change; README anchor bullet and seed-dispersion numbers updated; 2024-25 y_R marked censored; Figure 3 caption says in-scope counts. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… scope artefact Review of PR #46 found that from 2025-26 on no data-year mandatory registrant is released by the £85k->£90k anchor (all have aged past the £88k deregistration point); 84% of released liability belongs to data-year voluntary registrants aged across £85k. The paper now says so, presents the fixed-preference convention as the co-equal lower bound, and the static dump prints the decomposition. The 64% in-scope share above £10m is described as a uniform-draw artefact of the open ONS 5000+ band, not a PAYE/exempt share. Sweep caption and README describe the voluntary rule as implemented; README row count corrected; two unreferenced figures referenced; CUDA device bug in the weighted selector fixed; propensity test pins per-band values; ageing test covers a voluntary registrant crossing T0. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This was referenced Sep 6, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Resolves the universe incompatibility in #37 by calibrating on two declared universes, regenerates every checked artifact, and revises the manuscript to match. This is the single regeneration María asked for; PRs #42–#45 are cherry-picked onto this branch so their text lands once.
Two decisions taken (both flagged in #39 as mine to make):
p_b = HMRC count / frame mass(0.89 below the threshold; 0.51–1.00 above, the remainder being PAYE-only/exempt enterprises). HMRC negative/zero traders are appended before calibration as an out-of-frame stratum. The 2023-24 employment CSV is rebuilt from Table 3 (enterprises) viascripts/etl_ons_tables.py, which also sources both vintages' turnover tables from Table 8; a test asserts the two tables agree to disclosure rounding and that the CSVs match the extract.anchor_reformandthreshold_sweepnow use one rule.What changed in the results
Why the big moves:
taper_band_top,make_schedule_taper_flat, tests).Fresh-reviewer items folded in
Deregistration threshold (1), taper band-top frontier (2), 2024-25 coarse-band bunching readback in Section 6 (3), stale "smooth-counterfactual sweep" text (4), literature additions Keen–Mintz, Kanbur–Keen, Dharmapala–Slemrod–Wilson, Mirrlees Review, BizTax (5), δ-dependent n_H (6), retention as a bound given HMRC's ~zero below-threshold liability (7), sector targets vs negative/zero traders (8), by-construction band accuracy stated (9), dominated-band claim rewritten (10), ageing factors and the [£70k,£130k] re-optimisation window stated (11), population statement (12), pass-through and FRS conventions stated (15).
Reproduction
make reproduceruns ETL → both vintages → every artifact → figure sync (reproduce-heavyadds seed sensitivity and placebo B). All 70 tests pass; ruff clean. No quarto locally: the Paper workflow renders the PDF and now uploads it as an artifact (paper-pdf);paper/main.pdfshould be replaced from that artifact before merge.Not done here (tracked)
results/populace_ledger_comparison.txtNOTE is pinned by a test and still cites the old scores (Reproduction and claim synchronisation: one reproduce command, claim manifest, and stale README/results notes #40).--check(Reproduction and claim synchronisation: one reproduce command, claim manifest, and stale README/results notes #40).Closes #37. Refs #32, #38, #39, #40, #41.
🤖 Generated with Claude Code