diff --git a/README.md b/README.md index 46d2d6f..fa09424 100644 --- a/README.md +++ b/README.md @@ -144,22 +144,43 @@ firm-microsim-report | Calibrated dimension | 85k (2023-24) | 90k (2024-25) | | --- | ---: | ---: | -| HMRC turnover bands | 93.0% | 92.7% | -| ONS population | 91.1% | 94.2% | -| Employment bands | 78.2% | 89.7% | -| Sector distribution | 92.5% | 94.5% | -| VAT liability by band | 94.6% | 81.4% | -| **Overall (5 calibrated dimensions)** | **89.9%** | **90.5%** | +| HMRC turnover bands | 93.8% | 93.1% | +| ONS population | 90.3% | 92.6% | +| Employment bands | 77.9% | 92.4% | +| Sector distribution | 92.7% | 94.2% | +| VAT liability by band (6 calibrated bands) | 91.3% | 92.0% | +| **Overall (5 calibrated dimensions)** | **89.2%** | **92.8%** | **VAT liability by *sector*** is **not** a calibration target — it is reported as -an informational diagnostic only (47.1% / 44.5%). The model fixes firm inputs -and sets liability = turnover − input but does not yet calibrate the -**input/output tax structure**, so per-sector net liability is structurally -unhittable and is gated off via +an informational diagnostic only, and neither is the **below-threshold +(£1-to-Threshold) liability band**: its HMRC total is remitted by voluntary +registrants (input-reclaim traders averaging ~£2,150 net) whom the +standard-rate-on-value-added liability model does not represent, so calibrating +it against the whole below-threshold population distorts near-threshold +weights (see the paper's data section). The model draws per-firm input +shares (mean value-added share ≈ 40%) and sets net liability +`v = 0.20 × (turnover − input)` — the standard rate applied to value added — but +does not yet calibrate the **input/output tax structure by sector**, so +per-sector net liability is structurally unhittable and is gated off via `Config.calibrate_vat_liability_sector = False`. Restoring it after input/output calibration is tracked in issues [#1](https://github.com/PolicyEngine/firm-microsim-paper/issues/1) and -[#2](https://github.com/PolicyEngine/firm-microsim-paper/issues/2). +[#2](https://github.com/PolicyEngine/firm-microsim-paper/issues/2). An earlier +build set `v = turnover − input` (no 0.20 factor); the correction and its +consequences are documented in +[#15](https://github.com/PolicyEngine/firm-microsim-paper/issues/15) and the +paper's Section 5. + +## Fast iteration builds + +`firm-microsim --fast` runs the full pipeline on a stratified sample (~15% of +rows: 30% inside the £15k–£150k analysis window, 5% outside, per-stratum +floors), carrying the thinned mass as base weights so every calibration target +remains a true total. A vintage builds in ~15 seconds instead of ~13 minutes; +headline aggregates reproduce the full build within ~0.3% and local bunching +statistics within ~5%. Use for development only — release artifacts are +full-size. Generator-seed sensitivity of the full build is recorded in +`results/seed_sensitivity.txt` (E ±2%, reform costs ±£1m across seeds). ## Populace/Ledger migration check @@ -196,13 +217,17 @@ The current reference comparison shows exact parity between the Ledger-backed targets and the paper's processed 2024-25 numeric inputs: six normalized source tables checked, zero mismatches, max numeric difference 0. It does **not** exactly replicate the paper's generated synthetic population: Populace's shared optimizer -lands at 93.8% overall accuracy under its own validator versus the paper's 90.5%, -but that overall pair is **not like-for-like**: HMRC turnover-band accuracy uses -different band sets, and sector distribution reflects different calibration-target -definitions. The directly comparable rows are ONS population, employment bands, -and VAT liability by turnover band. The Populace/Ledger path is now based on -merged upstream inputs, while remaining a migration check rather than a silent -replacement for the paper's archived generator/results. +landed at 93.8% overall accuracy under its own validator versus the paper's +then-90.5% (89.4% on the corrected build), but that overall pair is **not +like-for-like**: HMRC turnover-band accuracy uses different band sets, and sector +distribution reflects different calibration-target definitions. The directly +comparable rows are ONS population, employment bands, and VAT liability by +turnover band. **Note:** the pinned Populace snapshot predates this repo's +net-liability correction (issue #15) and inherits the same `v = turnover − input` +mis-scaling; the target-parity result is unaffected (it concerns input tables, +not generated rows), but the Populace generator needs the same fix upstream. The +Populace/Ledger path remains a migration check rather than a silent replacement +for the paper's archived generator/results. ## Figures diff --git a/analysis/recovery_bunching.py b/analysis/recovery_bunching.py index 80885b5..2266851 100644 --- a/analysis/recovery_bunching.py +++ b/analysis/recovery_bunching.py @@ -1,48 +1,32 @@ -"""Recovery / coverage validation for the £85k VAT bunching estimator. - -Referee's point ---------------- -The existing placebo (``analysis/placebo_bunching.py``) shows the estimator -returns NO bunching when there is none by construction (the smoothed Placebo-A -population has b≈0, E≈0). That establishes the estimator does not generate a -FALSE POSITIVE when behaviour is absent. It does NOT, on its own, show the -estimator has POWER to detect a real behavioural response when one IS present. - -The discriminating test the referee asked for is a RECOVERY (coverage) exercise: -inject a behavioural bunching signal of KNOWN magnitude into the synthetic -population, then run the estimator and check whether it recovers that magnitude. - -Design ------- -1. Build a CLEAN, step-free baseline. Starting from the actual £85k synthetic - firms (whose own apparent step is itself mechanical), apply the SAME - Placebo-A reweighting used in the placebo script to obtain a smooth, - no-step population with b≈0, E≈0. This is the null world onto which we - graft a known signal, so the recovered mass is attributable ENTIRELY to the - injection, not to any residual mechanical step. - -2. INJECT a behavioural bunching response of known magnitude E_true. We take a - known share of the smooth counterfactual mass sitting in a donor window just - ABOVE the threshold, ``[T*, T*+DELTA]``, and relocate it to a bunching window - just BELOW the threshold, ``[T*-w, T*]`` — exactly the firm location-choice - the generator lacks. We relocate by reweighting (mass-conserving): scale - donor-window weights down by (1 - p) and add the removed mass to the - bunching window, distributed so it piles up immediately below T* (the - canonical bunching shape). The relocated mass IS the injected excess mass - E_true; we sweep several known magnitudes. - -3. Run the estimator on each injected population and record the recovered - excess mass E_hat and bunching ratio b_hat. - -4. Report a recovery table E_true vs E_hat (and b_hat), assess whether the - estimator is approximately unbiased / has power, and flag any systematic - bias (the polynomial counterfactual + fixed exclusion window are expected to - attenuate the recovered mass somewhat). - -Honesty note ------------- -We report E_hat against E_true plainly. Under/over-recovery is itself a useful -finding about the estimator's calibration and is reported as such. +"""Recovery / power validation for the £85k VAT bunching estimator. + +Purpose +------- +The placebo (``analysis/placebo_bunching.py``) shows the estimator returns no +bunching when none is present by construction (specificity). This exercise +shows the complementary property: when a behavioural relocation of KNOWN +magnitude IS present, the estimator's HEADLINE statistics detect and size it +(power), and its biases are characterised honestly. + +Why this design (and not the previous one) +------------------------------------------ +An earlier version of this harness relocated mass from a donor window +[85, 100) to [75, 85) — both strictly INSIDE the estimator's ±15k exclusion +window [70, 100]. The polynomial counterfactual is fitted only on bins +OUTSIDE that window and rescaled by total mass (which relocation preserves), +so the fitted counterfactual was bit-for-bit identical across all injection +magnitudes: the exercise measured deposit bookkeeping, not estimator power, +and its side statistic ("signed-excess change vs baseline") required knowing +the null world — information a real application never has. + +This version injects a Kleven–Waseem-consistent response: firms relocate to +just below the threshold from a missing-mass region (T*, Y_R_TRUE] that +extends BEYOND the exclusion window, with relocation probability declining +linearly from the threshold to zero at the true marginal buncher Y_R_TRUE. +The counterfactual fit therefore confronts genuinely depressed above-window +bins — exactly the situation with real bunching data — and recovery is scored +with the HEADLINE floored excess mass E and the endogenous marginal-buncher +location y_R, with no reference to the unobservable null. Writes results/recovery_bunching.txt. """ @@ -65,10 +49,11 @@ BIN_WIDTH = 1.0 # Injection geometry (£1,000 units). -DELTA = 15.0 # donor window half-width above T*: firms in [T*, T*+DELTA] may bunch. -W_BUNCH = 10.0 # bunching window below T*: relocated firms land in [T*-W_BUNCH, T*). +Y_R_TRUE = 112.0 # true marginal buncher: missing mass spans (85, 112], + # extending 12k BEYOND the exclusion window top (100). +W_SPIKE = 5.0 # relocated firms land in [T*-W_SPIKE, T*), spike toward T*. -# Known injected magnitudes (firms relocated -> excess mass E_true). +# Known injected magnitudes (weighted firms relocated = true excess mass). E_TRUE_TARGETS = (2000.0, 5000.0, 8000.0) @@ -94,7 +79,8 @@ def build_smooth_baseline(df: pd.DataFrame) -> np.ndarray: log-quadratic density trend on the wings (|y-85| > half), replace the in-window density with that smooth fit, rescale each firm's weight by (smooth / observed) in its bin, and renormalise total mass. Yields b≈0, - E≈0 — the clean null baseline for the recovery test. + E≈0 — the clean null baseline onto which the known signal is grafted, so + recovered mass is attributable entirely to the injection. """ half = 20.0 edges, centres = _bins() @@ -123,90 +109,61 @@ def build_smooth_baseline(df: pd.DataFrame) -> np.ndarray: return new_weight -def inject_bunching( +def inject_kw_bunching( turnover: np.ndarray, weight_base: np.ndarray, e_true: float, ) -> tuple[np.ndarray, float]: - """Relocate ``e_true`` units of mass from just above T* to just below it. - - Mass conservation: we remove a fraction p of the weight currently sitting in - the donor window ``[T*, T*+DELTA]`` (chosen so the removed mass equals - e_true) and re-deposit exactly that mass into the bunching window - ``[T*-W_BUNCH, T*)``, distributed with a triangular profile that peaks at the - bin immediately below T* (the canonical bunching spike). Total weight over - the estimation range is unchanged, so the ONLY change is a true behavioural - relocation across the threshold of known size e_true. - - Returns ``(new_weight, e_actual)`` where ``e_actual`` is the mass actually - relocated (== e_true unless the donor window has insufficient mass, in which - case it is capped at the donor mass and reported). + """Relocate ``e_true`` of mass from (T*, Y_R_TRUE] to just below T*. + + Kleven–Waseem-consistent response: a firm at turnover y in the donor + region (T*, Y_R_TRUE] relocates with probability + ``s * (1 - (y - T*) / (Y_R_TRUE - T*))`` — declining linearly from the + threshold to zero at the true marginal buncher — with the intensity ``s`` + chosen so the relocated mass equals ``e_true`` (capped at s=1 if the donor + region cannot supply it). Relocated mass is deposited into + [T*-W_SPIKE, T*) with a profile spiking toward T*. Total mass over the + estimation range is conserved; the missing-mass region extends beyond the + exclusion window top, as with genuine bunching. + + Returns ``(new_weight, e_actual)``. """ w = weight_base.copy() - donor = (turnover >= T_STAR) & (turnover < T_STAR + DELTA) - donor_mass = float(w[donor].sum()) + donor = (turnover > T_STAR) & (turnover <= Y_R_TRUE) + depth = 1.0 - (turnover[donor] - T_STAR) / (Y_R_TRUE - T_STAR) # 1 at T*, 0 at y_R + donor_capacity = float(np.sum(w[donor] * depth)) - e_actual = min(e_true, donor_mass) - p = e_actual / donor_mass if donor_mass > 0 else 0.0 + s = min(1.0, e_true / donor_capacity) if donor_capacity > 0 else 0.0 + removed = w[donor] * depth * s + e_actual = float(removed.sum()) + w[donor] = w[donor] - removed - # Remove mass from donor firms (scale their weights down by (1 - p)). - w[donor] = w[donor] * (1.0 - p) - - # Deposit e_actual into the bunching window with a triangular profile that - # peaks at the bin just below T*. We operate on firms, so distribute the - # added mass across firms in the window in proportion to a per-bin triangular - # kernel times each firm's base weight (so the within-bin split is sensible). - bunch = (turnover >= T_STAR - W_BUNCH) & (turnover < T_STAR) + bunch = (turnover >= T_STAR - W_SPIKE) & (turnover < T_STAR) if not np.any(bunch): return w, 0.0 - - # Triangular kernel: weight increases linearly toward T* (distance 0 at T*). - dist = T_STAR - turnover[bunch] # in (0, W_BUNCH] - kernel = (W_BUNCH - dist + BIN_WIDTH) # larger near T* - kernel = np.maximum(kernel, 0.0) - base = weight_base[bunch] - alloc = kernel * base + dist = T_STAR - turnover[bunch] # in (0, W_SPIKE] + kernel = np.maximum(W_SPIKE + BIN_WIDTH - dist, 0.0) # peaks just below T* + alloc = kernel * weight_base[bunch] if alloc.sum() <= 0: alloc = np.ones_like(alloc) - add = e_actual * alloc / alloc.sum() - idx = np.where(bunch)[0] - w[idx] = w[idx] + add + w[idx] = w[idx] + e_actual * alloc / alloc.sum() return w, e_actual -def signed_excess_below(r: dict, window_lo: float = DEFAULT_WINDOW) -> float: - """Signed (not floored) excess mass below T* over the exclusion window. - - The headline ``E`` statistic floors the per-bin excess at zero - (``max(f_obs - f_cf, 0)``). When the null baseline sits in a density DEFICIT - just below the threshold (as the smoothed Placebo-A baseline does), that - floor hides the part of an injected spike that merely fills the deficit - back up to the counterfactual. The signed below-threshold excess - ``sum(f_obs - f_cf)`` over ``[T*-window_lo, T*)`` is the correct - coverage quantity: its CHANGE relative to baseline equals the recovered - behavioural mass without the flooring artefact. - """ - c, fo, fc = r["centres"], r["f_obs"], r["f_cf"] - mN = (c >= T_STAR - window_lo) & (c < T_STAR) - return float(np.sum(fo[mN] - fc[mN]) * BIN_WIDTH) - - def estimate(turnover, weight, label, verbose=True) -> dict: r = _run_estimator(turnover, weight, T_STAR) - r["signed_excess"] = signed_excess_below(r) if verbose: print( - f" {label:<34s} b={r['b']:+.4f} E={r['E']:>10,.0f} " - f"signed={r['signed_excess']:>+9,.0f} b_llat={r['b_llat']:.3f} " - f"y_R={r['y_R']:.2f}" + f" {label:<30s} b={r['b']:+.4f} E={r['E']:>10,.0f} " + f"b_llat={r['b_llat']:.3f} y_R={r['y_R']:.2f}" ) return r def main() -> None: print("=" * 84) - print(f" RECOVERY / COVERAGE TEST (vintage {VINTAGE}, threshold £{T_STAR:.0f}k)") + print(f" RECOVERY / POWER TEST (vintage {VINTAGE}, threshold £{T_STAR:.0f}k)") print("=" * 84) df = load_firms(VINTAGE) @@ -215,164 +172,96 @@ def main() -> None: # --- Clean step-free baseline (the null world) ----------------------- w_base = build_smooth_baseline(df) r_base = estimate(t, w_base, "BASELINE (smoothed, null)") - E_base = r_base["E"] - S_base = r_base["signed_excess"] - - donor_mass = float(w_base[(t >= T_STAR) & (t < T_STAR + DELTA)].sum()) - print(f" donor-window mass [85,{85+DELTA:.0f}) available to bunch: {donor_mass:,.0f}") - print( - f" NOTE: the smoothed baseline sits in a signed DEFICIT below £85k " - f"({S_base:+,.0f})," - ) - print( - " so the floored headline E hides mass that merely refills it." - ) - print( - " The primary recovery measure is the CHANGE in signed excess" - ) - print(" below £85k relative to this baseline (deficit-differenced).") - print() - # --- Inject known signals and recover -------------------------------- + # --- Inject known KW-consistent signals and recover ------------------ rows = [] for e_true in E_TRUE_TARGETS: - w_inj, e_act = inject_bunching(t, w_base, e_true) + w_inj, e_act = inject_kw_bunching(t, w_base, e_true) r = estimate(t, w_inj, f"INJECT E_true={e_true:,.0f}") - e_hat = r["E"] # floored headline excess - s_hat = r["signed_excess"] # signed excess below T* - # Recovered behavioural mass = change in signed excess vs baseline. - e_recovered = s_hat - S_base - recov_signed = e_recovered / e_act if e_act > 0 else np.nan - recov_floored = (e_hat - E_base) / e_act if e_act > 0 else np.nan rows.append( { "E_true": e_act, - "E_hat_signed": e_recovered, - "E_hat_floored": e_hat, + "E_hat": r["E"], + "recovery": r["E"] / e_act if e_act > 0 else np.nan, "b_hat": r["b"], "b_llat": r["b_llat"], - "y_R": r["y_R"], - "recovery": recov_signed, - "recovery_floored": recov_floored, + "y_R_hat": r["y_R"], } ) res = pd.DataFrame(rows) print() - print(" Recovery summary (primary = signed-excess change vs baseline):") + print(" Recovery summary (headline floored E, mass-conservation y_R):") for _, row in res.iterrows(): print( - f" E_true={row['E_true']:>8,.0f} E_recovered={row['E_hat_signed']:>8,.0f} " - f"recovery={row['recovery']:.1%} (floored E_hat={row['E_hat_floored']:>7,.0f}, " - f"b_hat={row['b_hat']:+.4f})" + f" E_true={row['E_true']:>8,.0f} E_hat={row['E_hat']:>8,.0f} " + f"recovery={row['recovery']:.1%} y_R_hat={row['y_R_hat']:.1f} " + f"(true {Y_R_TRUE:.0f}) b_hat={row['b_hat']:+.4f}" ) - # --- Verdict --------------------------------------------------------- mean_recov = float(res["recovery"].mean()) - monotonic = bool(np.all(np.diff(res["E_hat_signed"].to_numpy()) > 0)) - - if mean_recov >= 0.85: - bias_word = f"approximately unbiased (recovers ~{mean_recov:.0%} of injected mass)" - else: - bias_word = f"attenuated (recovers ~{mean_recov:.0%} of injected mass on average)" + monotonic = bool(np.all(np.diff(res["E_hat"].to_numpy()) > 0)) # --- Write results --------------------------------------------------- lines = [] - lines.append("RECOVERY / COVERAGE TEST — £85k UK VAT bunching estimator (vintage 2023-24)") - lines.append("=" * 78) - lines.append("") - lines.append("Purpose") - lines.append("-------") lines.append( - "The placebo (results/placebo_bunching.txt) shows the estimator returns no\n" - "bunching when none is present (no false positive). This test shows the\n" - "complementary property: the estimator has POWER to recover a real\n" - "behavioural response of KNOWN magnitude (coverage / recovery)." + "RECOVERY / POWER TEST — £85k UK VAT bunching estimator " + f"(vintage {VINTAGE})" ) + lines.append("=" * 78) lines.append("") - lines.append("Method") + lines.append("Design") lines.append("------") lines.append( - "1. Baseline: take the actual £85k synthetic firms and apply the Placebo-A\n" - " reweighting (smooth log-quadratic density across £85k, no step), giving\n" - f" a null world with b={r_base['b']:+.4f}, headline E={E_base:,.0f}, signed\n" - f" below-threshold excess = {S_base:+,.0f} (a small density DEFICIT).\n" - "2. Injection: relocate a KNOWN mass E_true from a donor window just above\n" - f" the threshold [85, {85+DELTA:.0f}) to a bunching window just below it\n" - f" [{85-W_BUNCH:.0f}, 85), with a triangular profile peaking at £85k.\n" - " This is mass-conserving and is the firm location-choice the generator\n" - " lacks. The relocated mass IS the injected excess mass E_true.\n" - "3. Run the SAME estimator (bunching.model._run_estimator, degree=7,\n" - f" window=±{DEFAULT_WINDOW:.0f}k) and record recovered excess and b_hat.\n" - ) - lines.append("") - lines.append( - "Measurement note. The headline E floors per-bin excess at zero\n" - "(max(f_obs-f_cf,0)). Because the smoothed baseline sits in a signed\n" - "deficit just below £85k, the floor hides the part of an injected spike\n" - "that merely refills that deficit. The PRIMARY recovery quantity is the\n" - "CHANGE in the SIGNED below-threshold excess relative to baseline\n" - "(E_recovered = signed_excess - baseline signed_excess), which is the\n" - "deficit-differenced coverage measure. The floored E_hat is also reported." + "1. Baseline: the £85k synthetic firms under the Placebo-A reweighting\n" + " (smooth log-quadratic density across £85k), a step-free null world:\n" + f" b={r_base['b']:+.4f}, E={r_base['E']:,.0f}, y_R={r_base['y_R']:.2f}.\n" + "2. Injection (Kleven–Waseem-consistent): firms in the donor region\n" + f" (85, {Y_R_TRUE:.0f}] relocate to [{T_STAR - W_SPIKE:.0f}, 85) with probability\n" + " declining linearly from the threshold to zero at the true marginal\n" + f" buncher y_R = {Y_R_TRUE:.0f} — so the missing-mass region extends\n" + f" {Y_R_TRUE - T_STAR - DEFAULT_WINDOW:.0f}k BEYOND the ±{DEFAULT_WINDOW:.0f}k exclusion window, as with\n" + " genuine bunching. Mass is conserved.\n" + "3. Score with the HEADLINE estimator outputs only (floored excess mass\n" + " E, endogenous y_R): no side statistics that require knowing the null." ) lines.append("") lines.append("Results") lines.append("-------") hdr = ( - f"{'E_true':>10s} {'E_recovered':>12s} {'recovery':>9s} " - f"{'E_hat(fl)':>10s} {'b_hat':>8s} {'b_llat':>8s} {'y_R':>7s}" + f"{'E_true':>10s} {'E_hat':>10s} {'recovery':>9s} " + f"{'y_R_hat':>8s} {'b_hat':>8s} {'b_llat':>8s}" ) lines.append(hdr) lines.append("-" * len(hdr)) for _, row in res.iterrows(): lines.append( - f"{row['E_true']:>10,.0f} {row['E_hat_signed']:>12,.0f} " - f"{row['recovery']:>8.1%} {row['E_hat_floored']:>10,.0f} " - f"{row['b_hat']:>+8.4f} {row['b_llat']:>8.3f} {row['y_R']:>7.2f}" + f"{row['E_true']:>10,.0f} {row['E_hat']:>10,.0f} " + f"{row['recovery']:>8.1%} {row['y_R_hat']:>8.2f} " + f"{row['b_hat']:>+8.4f} {row['b_llat']:>8.3f}" ) lines.append("") lines.append( f"Baseline (null, no injection): b={r_base['b']:+.4f} " - f"E={E_base:,.0f} signed_excess={S_base:+,.0f}" + f"E={r_base['E']:,.0f} y_R={r_base['y_R']:.2f}" ) lines.append( - f"Mean recovery across magnitudes: {mean_recov:.1%} " - f"(monotone in E_true: {monotonic})" + f"True marginal buncher: y_R = {Y_R_TRUE:.0f}. " + f"Mean recovery: {mean_recov:.1%} (monotone in E_true: {monotonic})." ) lines.append("") - lines.append("Verdict") + lines.append("Reading") lines.append("-------") lines.append( - f"The estimator HAS POWER: every injected behavioural signal is detected,\n" - f"the recovered excess rises monotonically with E_true " - f"(monotone={monotonic}),\n" - f"and the bunching ratio b_hat moves steadily up from the baseline as the\n" - f"injection grows. Recovery is {bias_word}. The ~10% shortfall is a known,\n" - f"benign attenuation: the degree-7 polynomial counterfactual partially\n" - f"re-absorbs the injected spike and the fixed ±{DEFAULT_WINDOW:.0f}k exclusion window clips\n" - f"its tails, so the estimator slightly UNDER-states a true response — it\n" - f"does not over-state one. Combined with the placebo (no false positive\n" - f"when behaviour is absent), this completes the validation: the estimator\n" - f"has BOTH no-false-positive AND power to detect a genuine location-choice\n" - f"response.\n" - f"\n" - f"Caveat for the floored E. Read on its own, the headline E badly\n" - f"understates small injections (E_hat=0 at E_true=2,000) ONLY because the\n" - f"smoothed baseline starts in a below-threshold deficit that the spike must\n" - f"first refill before any POSITIVE excess registers. This is a property of\n" - f"the flooring, not a failure of power, which is why the signed-excess\n" - f"change is the correct coverage measure." - ) - lines.append("") - lines.append("One-line summary for the paper") - lines.append("------------------------------") - lines.append( - f"In a recovery exercise that injects behavioural bunching of known\n" - f"magnitude (E_true = 2,000/5,000/8,000 firms) into a step-free synthetic\n" - f"population, the estimator detects every signal and recovers ~{mean_recov:.0%} of\n" - f"the injected excess mass (slightly attenuated, never inflated), confirming\n" - f"it has power; together with the placebo's null result this shows the\n" - f"estimator is both specific (no false positive) and sensitive (has power)." + "Recovery below 100% is genuine estimator attenuation, now measured\n" + "rather than asserted: the counterfactual is fitted on bins that include\n" + "the depressed (100, 112] missing-mass region outside the exclusion\n" + "window, pulling the fitted counterfactual down and truncating the\n" + "measured missing mass; the mass-conservation search then places y_R_hat\n" + "accordingly. The estimator under-states a true response and does not\n" + "over-state one; together with the placebo's null result (no false\n" + "positive on a step-free world) this characterises the estimator as\n" + "specific and, with quantified attenuation, sensitive." ) out = RESULTS_DIR / "recovery_bunching.txt" diff --git a/analysis/static_results_dump.py b/analysis/static_results_dump.py new file mode 100644 index 0000000..3f727a0 --- /dev/null +++ b/analysis/static_results_dump.py @@ -0,0 +1,74 @@ +"""Dump the static sweep, anchor comparison, and revenue bases as a text artifact. + +The paper's flagship static table (tab:static_revenue) previously existed only +as figure pixels and an HTML preview; this writes the full machine-readable +numbers to results/static_sweep.txt so every printed row is reproducible. +Also reports the voluntary-retention sensitivity on the anchor reform: the +headline convention deregisters every released firm; the sensitivity retains +the Liu et al. (2021) voluntary-registration share of released-firm liability. +""" + +from __future__ import annotations + +from firm_microsim.config import RESULTS_DIR +from firm_microsim.static.model import StaticVATModel, SWEEP_THRESHOLDS + +LLAT_VOLUNTARY_SHARE = 0.43 # Liu-Lockwood-Almunia-Tam (2021): ~43% below-threshold + + +def main() -> None: + lines = [] + W = lines.append + + sweep_model = StaticVATModel("2024-25") + anchor_model = StaticVATModel("2023-24") + + W("STATIC RESULTS DUMP") + W("=" * 74) + W("") + W("Anchor reform (85k -> 90k, 2023-24 vintage = HMRC's pre-reform basis)") + W("model vs HMRC published costing (Spring Budget 2024), by fiscal year;") + W("baseline column = counterfactual threshold path (85/85/87/89/92k).") + W("-" * 74) + anchor = anchor_model.anchor_reform() + W(anchor.to_string(index=False)) + W("") + W("Voluntary-retention sensitivity (anchor, per year): headline assumes") + W("every released firm deregisters (full liability lost). If the Liu et") + W(f"al. (2021) voluntary share ({LLAT_VOLUNTARY_SHARE:.0%}) of released-firm liability is") + W("retained, the impact scales accordingly:") + for _, row in anchor.iterrows(): + impact = float(row["policyengine_impact_m"]) + W(f" {row['year']}: headline {impact:+,.1f}m -> retention-adjusted " + f"{impact * (1 - LLAT_VOLUNTARY_SHARE):+,.1f}m " + f"(HMRC {float(row['hmrc_impact_m']):+,.0f}m)") + W("") + W("Threshold sweep (2024-25 vintage, GBP 90k baseline, 2025-26 fiscal year)") + W("counterfactual method: smooth above-threshold extrapolation (degree 1)") + W("-" * 74) + sweep = sweep_model.threshold_sweep(year="2025-26") + W(sweep.to_string(index=False)) + W("") + for year in ("2025-26", "2026-27"): + W(f"Total VAT revenue at GBP 90k, {year}: " + f"{sweep_model.total_revenue_bn(year=year):.1f}bn") + W("") + W("Bases and calibration-target comparison") + W("-" * 74) + for vintage, model in (("2023-24", anchor_model), ("2024-25", sweep_model)): + df = model._aged(1.0) + thr = 85_000.0 if vintage == "2023-24" else 90_000.0 + reg = df["turnover"] >= thr + base = float((df.loc[reg, "liab"] * df.loc[reg, "weight"]).sum()) / 1e9 + W(f" {vintage}: registered base (>= threshold, unaged) = {base:.1f}bn") + W("") + W(f"Sweep thresholds: {SWEEP_THRESHOLDS}") + + out = RESULTS_DIR / "static_sweep.txt" + out.write_text("\n".join(lines) + "\n") + print("\n".join(lines)) + print(f"\nWrote {out}") + + +if __name__ == "__main__": + main() diff --git a/build.log b/build.log new file mode 100644 index 0000000..b4665fc --- /dev/null +++ b/build.log @@ -0,0 +1,82 @@ +2026-07-01 22:38:57,889 - INFO - === Generating vintage 2023-24 === +2026-07-01 22:38:57,893 - INFO - Generating synthetic firms (threshold=£85k, seed=42, device=cpu) +2026-07-01 22:38:57,893 - INFO - Loading processed input tables from /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/processed/2023-24 +2026-07-01 22:38:57,903 - INFO - ons_turnover 89 rows +2026-07-01 22:38:57,903 - INFO - ons_employment 89 rows +2026-07-01 22:38:57,903 - INFO - hmrc_population_band 20 rows +2026-07-01 22:38:57,903 - INFO - hmrc_population_sector 89 rows +2026-07-01 22:38:57,903 - INFO - hmrc_liability_band 20 rows +2026-07-01 22:38:57,903 - INFO - hmrc_liability_sector 88 rows +2026-07-01 22:38:57,909 - INFO - ONS total firms: 2,724,775 +2026-07-01 22:38:57,909 - INFO - HMRC VAT-registered firms (latest year): 2,178,960 +2026-07-01 22:38:57,909 - INFO - Generating base firms from ONS structure... +2026-07-01 22:38:58,684 - INFO - Generated 2,724,775 base firms +2026-07-01 22:38:58,724 - INFO - Generating input values... +2026-07-01 22:38:59,106 - INFO - Input/output ratio: mean=0.60 std=0.19; mean value-added share=0.40; firms with negative value added: 0 +2026-07-01 22:38:59,107 - INFO - Assigning employment from ONS distribution... +2026-07-01 22:39:04,341 - INFO - Target matrix shape: (109, 2724775) +2026-07-01 22:39:04,342 - INFO - Targets: 7 turnover + 88 sector + 7 employment + 0 VAT-liability sector + 7 VAT-liability band = 109 +2026-07-01 22:39:04,342 - INFO - Starting multi-objective weight optimization... +2026-07-01 22:39:09,965 - INFO - Iteration 0: loss = 0.191273 +2026-07-01 22:39:22,151 - INFO - Iteration 100: loss = 0.086034 +2026-07-01 22:39:36,420 - INFO - Iteration 200: loss = 0.059742 +2026-07-01 22:39:51,038 - INFO - Iteration 300: loss = 0.055526 +2026-07-01 22:40:10,156 - INFO - Iteration 400: loss = 0.054971 +2026-07-01 22:40:27,410 - INFO - Iteration 500: loss = 0.054763 +2026-07-01 22:40:43,606 - INFO - Iteration 600: loss = 0.054578 +2026-07-01 22:40:59,765 - INFO - Iteration 700: loss = 0.054409 +2026-07-01 22:41:16,027 - INFO - Iteration 800: loss = 0.054307 +2026-07-01 22:41:31,370 - INFO - Iteration 900: loss = 0.054208 +2026-07-01 22:41:45,289 - INFO - Optimization complete. Turnover-band fit: +2026-07-01 22:41:45,289 - INFO - £1_to_Threshold 863339 vs 766560 (87.4%) +2026-07-01 22:41:45,290 - INFO - £Threshold_to_£150k 329587 vs 305320 (92.1%) +2026-07-01 22:41:45,290 - INFO - £150k_to_£300k 363639 vs 334470 (91.3%) +2026-07-01 22:41:45,290 - INFO - £300k_to_£500k 196175 vs 184080 (93.4%) +2026-07-01 22:41:45,290 - INFO - £500k_to_£1m 192288 vs 180500 (93.5%) +2026-07-01 22:41:45,290 - INFO - £1m_to_£10m 250792 vs 235060 (93.3%) +2026-07-01 22:41:45,290 - INFO - Greater_than_£10m 47401 vs 44680 (93.9%) +2026-07-01 22:41:45,290 - INFO - Adding 216,500 zero/negative-turnover firms (HMRC)... +2026-07-01 22:41:45,353 - INFO - Added 216,457 zero-turnover firms +2026-07-01 22:41:45,353 - INFO - Assigning employment from ONS distribution... +2026-07-01 22:41:48,151 - INFO - Assigning VAT registration flags... +2026-07-01 22:41:48,157 - INFO - Voluntary VAT row rate: 0.885 (target 678,350 / synthetic rows 766,560) +2026-07-01 22:41:48,185 - INFO - VAT: 1958215 mandatory + 678675 voluntary = 2636890 registered +2026-07-01 22:41:48,185 - INFO - Assembling final DataFrame... +2026-07-01 22:41:49,035 - INFO - Generated 2,941,232 rows, weighted population 2,459,678 +2026-07-01 22:41:51,545 - INFO - === CALIBRATION SUMMARY (threshold £85k) === +2026-07-01 22:41:51,545 - INFO - HMRC Turnover Bands: 93.9% +2026-07-01 22:41:51,545 - INFO - ONS Population: 90.3% +2026-07-01 22:41:51,545 - INFO - Employment Bands: 77.9% +2026-07-01 22:41:51,545 - INFO - Sector Distribution: 92.5% +2026-07-01 22:41:51,545 - INFO - VAT Liability by Band: 92.6% +2026-07-01 22:41:51,545 - INFO - Overall Accuracy (5 calibrated dims): 89.4% +2026-07-01 22:41:51,545 - INFO - VAT Liability by Sector: 45.1% [informational, NOT calibrated] +2026-07-01 22:41:51,545 - INFO - Total Population: 2,459,678 firms +2026-07-01 22:42:04,175 - INFO - Wrote 2,941,232 rows to /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/synthetic/synthetic_firms_2023-24.csv (142.8 MB) +2026-07-01 22:42:04,281 - INFO - === Generating vintage 2024-25 === +2026-07-01 22:42:04,283 - INFO - Generating synthetic firms (threshold=£90k, seed=42, device=cpu) +2026-07-01 22:42:04,283 - INFO - Loading processed input tables from /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/processed/2024-25 +2026-07-01 22:42:04,289 - INFO - ons_turnover 89 rows +2026-07-01 22:42:04,289 - INFO - ons_employment 89 rows +2026-07-01 22:42:04,289 - INFO - hmrc_population_band 1 rows +2026-07-01 22:42:04,289 - INFO - hmrc_population_sector 88 rows +2026-07-01 22:42:04,289 - INFO - hmrc_liability_band 1 rows +2026-07-01 22:42:04,289 - INFO - hmrc_liability_sector 88 rows +2026-07-01 22:42:04,291 - INFO - ONS total firms: 2,734,615 +2026-07-01 22:42:04,291 - INFO - HMRC VAT-registered firms (latest year): 2,171,200 +2026-07-01 22:42:04,291 - INFO - Generating base firms from ONS structure... +2026-07-01 22:42:05,144 - INFO - Generated 2,734,615 base firms +2026-07-01 22:42:05,213 - INFO - Generating input values... +2026-07-01 22:42:05,633 - INFO - Input/output ratio: mean=0.60 std=0.19; mean value-added share=0.40; firms with negative value added: 0 +2026-07-01 22:42:05,634 - INFO - Assigning employment from ONS distribution... +2026-07-01 22:42:14,570 - INFO - Target matrix shape: (109, 2734615) +2026-07-01 22:42:14,571 - INFO - Targets: 7 turnover + 88 sector + 7 employment + 0 VAT-liability sector + 7 VAT-liability band = 109 +2026-07-01 22:42:14,571 - INFO - Starting multi-objective weight optimization... +2026-07-01 22:42:14,703 - INFO - Iteration 0: loss = 0.199671 +2026-07-01 22:42:34,200 - INFO - Iteration 100: loss = 0.093591 +2026-07-01 22:43:21,598 - INFO - Iteration 200: loss = 0.061318 +2026-07-01 22:47:05,786 - INFO - Iteration 300: loss = 0.056815 +2026-07-01 22:50:30,265 - INFO - Iteration 400: loss = 0.055884 +2026-07-01 22:53:41,023 - INFO - Iteration 500: loss = 0.055568 +2026-07-01 22:55:56,341 - INFO - Iteration 600: loss = 0.055200 +2026-07-01 22:58:57,510 - INFO - Iteration 700: loss = 0.054782 diff --git a/build2425.log b/build2425.log new file mode 100644 index 0000000..c580e11 --- /dev/null +++ b/build2425.log @@ -0,0 +1,54 @@ +2026-07-01 23:16:01,593 - INFO - Generating synthetic firms (threshold=£90k, seed=42, device=cpu) +2026-07-01 23:16:01,594 - INFO - Loading processed input tables from /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/processed/2024-25 +2026-07-01 23:16:01,608 - INFO - ons_turnover 89 rows +2026-07-01 23:16:01,609 - INFO - ons_employment 89 rows +2026-07-01 23:16:01,609 - INFO - hmrc_population_band 1 rows +2026-07-01 23:16:01,609 - INFO - hmrc_population_sector 88 rows +2026-07-01 23:16:01,609 - INFO - hmrc_liability_band 1 rows +2026-07-01 23:16:01,609 - INFO - hmrc_liability_sector 88 rows +2026-07-01 23:16:01,613 - INFO - ONS total firms: 2,734,615 +2026-07-01 23:16:01,613 - INFO - HMRC VAT-registered firms (latest year): 2,171,200 +2026-07-01 23:16:01,613 - INFO - Generating base firms from ONS structure... +2026-07-01 23:16:02,852 - INFO - Generated 2,734,615 base firms +2026-07-01 23:16:02,955 - INFO - Generating input values... +2026-07-01 23:16:03,899 - INFO - Input/output ratio: mean=0.60 std=0.19; mean value-added share=0.40; firms with negative value added: 0 +2026-07-01 23:16:03,901 - INFO - Assigning employment from ONS distribution... +2026-07-01 23:16:17,477 - INFO - Target matrix shape: (109, 2734615) +2026-07-01 23:16:17,477 - INFO - Targets: 7 turnover + 88 sector + 7 employment + 0 VAT-liability sector + 7 VAT-liability band = 109 +2026-07-01 23:16:17,477 - INFO - Starting multi-objective weight optimization... +2026-07-01 23:16:24,785 - INFO - Iteration 0: loss = 0.199671 +2026-07-01 23:17:13,315 - INFO - Iteration 100: loss = 0.093591 +2026-07-01 23:17:52,795 - INFO - Iteration 200: loss = 0.061318 +2026-07-01 23:19:26,606 - INFO - Iteration 300: loss = 0.056815 +2026-07-01 23:20:03,889 - INFO - Iteration 400: loss = 0.055884 +2026-07-01 23:21:30,504 - INFO - Iteration 500: loss = 0.055568 +2026-07-01 23:22:42,954 - INFO - Iteration 600: loss = 0.055200 +2026-07-01 23:24:59,936 - INFO - Iteration 700: loss = 0.054782 +2026-07-01 23:27:32,190 - INFO - Iteration 800: loss = 0.054620 +2026-07-01 23:32:08,362 - INFO - Iteration 900: loss = 0.054590 +2026-07-01 23:33:02,886 - INFO - Optimization complete. Turnover-band fit: +2026-07-01 23:33:02,887 - INFO - £1_to_Threshold 981702 vs 802759 (77.7%) +2026-07-01 23:33:02,898 - INFO - £Threshold_to_£150k 304247 vs 280400 (91.5%) +2026-07-01 23:33:02,899 - INFO - £150k_to_£300k 370574 vs 338600 (90.6%) +2026-07-01 23:33:02,899 - INFO - £300k_to_£500k 199379 vs 186700 (93.2%) +2026-07-01 23:33:02,899 - INFO - £500k_to_£1m 197053 vs 184100 (93.0%) +2026-07-01 23:33:02,899 - INFO - £1m_to_£10m 258700 vs 240500 (92.4%) +2026-07-01 23:33:02,899 - INFO - Greater_than_£10m 48588 vs 45800 (93.9%) +2026-07-01 23:33:02,900 - INFO - Adding 211,400 zero/negative-turnover firms (HMRC)... +2026-07-01 23:33:03,265 - INFO - Added 211,359 zero-turnover firms +2026-07-01 23:33:03,266 - INFO - Assigning employment from ONS distribution... +2026-07-01 23:33:09,356 - INFO - Assigning VAT registration flags... +2026-07-01 23:33:09,406 - INFO - Voluntary VAT row rate: 0.852 (target 683,700 / synthetic rows 802,759) +2026-07-01 23:33:09,568 - INFO - VAT: 1931856 mandatory + 683939 voluntary = 2615795 registered +2026-07-01 23:33:09,569 - INFO - Assembling final DataFrame... +2026-07-01 23:33:12,366 - INFO - Generated 2,945,974 rows, weighted population 2,571,602 +2026-07-01 23:33:20,698 - INFO - === CALIBRATION SUMMARY (threshold £90k) === +2026-07-01 23:33:20,699 - INFO - HMRC Turnover Bands: 93.5% +2026-07-01 23:33:20,699 - INFO - ONS Population: 94.0% +2026-07-01 23:33:20,699 - INFO - Employment Bands: 86.1% +2026-07-01 23:33:20,699 - INFO - Sector Distribution: 94.4% +2026-07-01 23:33:20,699 - INFO - VAT Liability by Band: 79.0% +2026-07-01 23:33:20,699 - INFO - Overall Accuracy (5 calibrated dims): 89.4% +2026-07-01 23:33:20,699 - INFO - VAT Liability by Sector: 43.4% [informational, NOT calibrated] +2026-07-01 23:33:20,699 - INFO - Total Population: 2,571,602 firms +2026-07-01 23:33:50,463 - INFO - Wrote 2,945,974 rows to /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/synthetic/synthetic_firms_2024-25.csv (143.0 MB) diff --git a/build_both.log b/build_both.log new file mode 100644 index 0000000..1d0c338 --- /dev/null +++ b/build_both.log @@ -0,0 +1,175 @@ +2026-07-02 08:58:27,624 - INFO - === Generating vintage 2023-24 === +2026-07-02 08:58:27,632 - INFO - Generating synthetic firms (threshold=£85k, seed=42, device=cpu) +2026-07-02 08:58:27,632 - INFO - Loading processed input tables from /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/processed/2023-24 +2026-07-02 08:58:27,637 - INFO - ons_turnover 89 rows +2026-07-02 08:58:27,637 - INFO - ons_employment 89 rows +2026-07-02 08:58:27,637 - INFO - hmrc_population_band 20 rows +2026-07-02 08:58:27,637 - INFO - hmrc_population_sector 89 rows +2026-07-02 08:58:27,637 - INFO - hmrc_liability_band 20 rows +2026-07-02 08:58:27,637 - INFO - hmrc_liability_sector 88 rows +2026-07-02 08:58:27,640 - INFO - Near-threshold targets: 25 OBR £1k bins over [65k, 90k], interpolated 2023-24 profile, total 453,902 firms +2026-07-02 08:58:27,640 - INFO - ONS total firms: 2,724,775 +2026-07-02 08:58:27,640 - INFO - HMRC VAT-registered firms (latest year): 2,178,960 +2026-07-02 08:58:27,640 - INFO - Generating base firms from ONS structure... +2026-07-02 08:58:27,912 - INFO - Generated 2,724,775 base firms +2026-07-02 08:58:27,927 - INFO - Generating input values... +2026-07-02 08:58:28,107 - INFO - Input/output ratio: mean=0.60 std=0.19; mean value-added share=0.40; firms with negative value added: 0 +2026-07-02 08:58:28,107 - INFO - Assigning employment from ONS distribution... +2026-07-02 08:58:30,605 - INFO - Target matrix shape: (133, 2724775) +2026-07-02 08:58:30,605 - INFO - Targets: 7 turnover + 88 sector + 7 employment + 0 VAT-liability sector + 6 VAT-liability band + 25 near-threshold = 133 +2026-07-02 08:58:30,605 - INFO - Starting multi-objective weight optimization... +2026-07-02 08:58:31,384 - INFO - Iteration 0: loss = 0.165942 +2026-07-02 08:58:37,250 - INFO - Iteration 100: loss = 0.070754 +2026-07-02 08:58:43,168 - INFO - Iteration 200: loss = 0.050738 +2026-07-02 08:58:49,100 - INFO - Iteration 300: loss = 0.046129 +2026-07-02 08:58:55,013 - INFO - Iteration 400: loss = 0.045633 +2026-07-02 08:59:00,891 - INFO - Iteration 500: loss = 0.045463 +2026-07-02 08:59:06,890 - INFO - Iteration 600: loss = 0.045319 +2026-07-02 08:59:12,740 - INFO - Iteration 700: loss = 0.045189 +2026-07-02 08:59:18,588 - INFO - Iteration 800: loss = 0.045110 +2026-07-02 08:59:24,488 - INFO - Iteration 900: loss = 0.045028 +2026-07-02 08:59:30,422 - INFO - Optimization complete. Turnover-band fit: +2026-07-02 08:59:30,422 - INFO - £1_to_Threshold 861318 vs 766560 (87.6%) +2026-07-02 08:59:30,422 - INFO - £Threshold_to_£150k 331406 vs 305320 (91.5%) +2026-07-02 08:59:30,422 - INFO - £150k_to_£300k 364281 vs 334470 (91.1%) +2026-07-02 08:59:30,422 - INFO - £300k_to_£500k 196169 vs 184080 (93.4%) +2026-07-02 08:59:30,422 - INFO - £500k_to_£1m 192340 vs 180500 (93.4%) +2026-07-02 08:59:30,422 - INFO - £1m_to_£10m 251136 vs 235060 (93.2%) +2026-07-02 08:59:30,422 - INFO - Greater_than_£10m 47437 vs 44680 (93.8%) +2026-07-02 08:59:30,422 - INFO - Adding 216,500 zero/negative-turnover firms (HMRC)... +2026-07-02 08:59:30,444 - INFO - Added 216,457 zero-turnover firms +2026-07-02 08:59:30,445 - INFO - Assigning employment from ONS distribution... +2026-07-02 08:59:31,337 - INFO - Assigning VAT registration flags... +2026-07-02 08:59:31,340 - INFO - Voluntary VAT row rate: 0.885 (target 678,350 / synthetic rows 766,560) +2026-07-02 08:59:31,347 - INFO - VAT: 1958215 mandatory + 678675 voluntary = 2636890 registered +2026-07-02 08:59:31,347 - INFO - Assembling final DataFrame... +2026-07-02 08:59:31,659 - INFO - Generated 2,941,232 rows, weighted population 2,460,542 +2026-07-02 08:59:32,705 - INFO - VAT liability £1-to-Threshold (informational, NOT calibrated): 27.4% +2026-07-02 08:59:32,705 - INFO - === CALIBRATION SUMMARY (threshold £85k) === +2026-07-02 08:59:32,705 - INFO - HMRC Turnover Bands: 93.8% +2026-07-02 08:59:32,705 - INFO - ONS Population: 90.3% +2026-07-02 08:59:32,705 - INFO - Employment Bands: 77.9% +2026-07-02 08:59:32,705 - INFO - Sector Distribution: 92.7% +2026-07-02 08:59:32,705 - INFO - VAT Liability by Band: 91.3% +2026-07-02 08:59:32,705 - INFO - Overall Accuracy (5 calibrated dims): 89.2% +2026-07-02 08:59:32,705 - INFO - VAT Liability by Sector: 45.2% [informational, NOT calibrated] +2026-07-02 08:59:32,705 - INFO - Total Population: 2,460,542 firms +2026-07-02 08:59:37,203 - INFO - Wrote 2,941,232 rows to /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/synthetic/synthetic_firms_2023-24.csv (142.7 MB) +2026-07-02 08:59:37,225 - INFO - === Generating vintage 2024-25 === +2026-07-02 08:59:37,227 - INFO - Generating synthetic firms (threshold=£90k, seed=42, device=cpu) +2026-07-02 08:59:37,227 - INFO - Loading processed input tables from /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/processed/2024-25 +2026-07-02 08:59:37,231 - INFO - ons_turnover 89 rows +2026-07-02 08:59:37,231 - INFO - ons_employment 89 rows +2026-07-02 08:59:37,231 - INFO - hmrc_population_band 1 rows +2026-07-02 08:59:37,231 - INFO - hmrc_population_sector 88 rows +2026-07-02 08:59:37,231 - INFO - hmrc_liability_band 1 rows +2026-07-02 08:59:37,231 - INFO - hmrc_liability_sector 88 rows +2026-07-02 08:59:37,232 - INFO - ONS total firms: 2,734,615 +2026-07-02 08:59:37,232 - INFO - HMRC VAT-registered firms (latest year): 2,171,200 +2026-07-02 08:59:37,232 - INFO - Generating base firms from ONS structure... +2026-07-02 08:59:37,489 - INFO - Generated 2,734,615 base firms +2026-07-02 08:59:37,503 - INFO - Generating input values... +2026-07-02 08:59:37,653 - INFO - Input/output ratio: mean=0.60 std=0.19; mean value-added share=0.40; firms with negative value added: 0 +2026-07-02 08:59:37,653 - INFO - Assigning employment from ONS distribution... +2026-07-02 08:59:40,229 - INFO - Target matrix shape: (108, 2734615) +2026-07-02 08:59:40,229 - INFO - Targets: 7 turnover + 88 sector + 7 employment + 0 VAT-liability sector + 6 VAT-liability band + 0 near-threshold = 108 +2026-07-02 08:59:40,229 - INFO - Starting multi-objective weight optimization... +2026-07-02 08:59:40,287 - INFO - Iteration 0: loss = 0.178650 +2026-07-02 08:59:45,294 - INFO - Iteration 100: loss = 0.072528 +2026-07-02 08:59:50,313 - INFO - Iteration 200: loss = 0.040183 +2026-07-02 08:59:55,347 - INFO - Iteration 300: loss = 0.035918 +2026-07-02 09:00:00,347 - INFO - Iteration 400: loss = 0.035314 +2026-07-02 09:00:05,343 - INFO - Iteration 500: loss = 0.035383 +2026-07-02 09:00:10,371 - INFO - Iteration 600: loss = 0.035272 +2026-07-02 09:00:15,379 - INFO - Iteration 700: loss = 0.034978 +2026-07-02 09:00:20,460 - INFO - Iteration 800: loss = 0.034860 +2026-07-02 09:00:25,564 - INFO - Iteration 900: loss = 0.034859 +2026-07-02 09:00:30,600 - INFO - Optimization complete. Turnover-band fit: +2026-07-02 09:00:30,600 - INFO - £1_to_Threshold 933569 vs 802759 (83.7%) +2026-07-02 09:00:30,600 - INFO - £Threshold_to_£150k 305999 vs 280400 (90.9%) +2026-07-02 09:00:30,600 - INFO - £150k_to_£300k 374039 vs 338600 (89.5%) +2026-07-02 09:00:30,600 - INFO - £300k_to_£500k 200439 vs 186700 (92.6%) +2026-07-02 09:00:30,600 - INFO - £500k_to_£1m 197518 vs 184100 (92.7%) +2026-07-02 09:00:30,600 - INFO - £1m_to_£10m 259745 vs 240500 (92.0%) +2026-07-02 09:00:30,600 - INFO - Greater_than_£10m 48655 vs 45800 (93.8%) +2026-07-02 09:00:30,600 - INFO - Adding 211,400 zero/negative-turnover firms (HMRC)... +2026-07-02 09:00:30,619 - INFO - Added 211,359 zero-turnover firms +2026-07-02 09:00:30,619 - INFO - Assigning employment from ONS distribution... +2026-07-02 09:00:31,489 - INFO - Assigning VAT registration flags... +2026-07-02 09:00:31,490 - INFO - Voluntary VAT row rate: 0.852 (target 683,700 / synthetic rows 802,759) +2026-07-02 09:00:31,497 - INFO - VAT: 1931856 mandatory + 683939 voluntary = 2615795 registered +2026-07-02 09:00:31,497 - INFO - Assembling final DataFrame... +2026-07-02 09:00:31,800 - INFO - Generated 2,945,974 rows, weighted population 2,531,324 +2026-07-02 09:00:32,836 - INFO - VAT liability £1-to-Threshold (informational, NOT calibrated): 0.0% +2026-07-02 09:00:32,836 - INFO - === CALIBRATION SUMMARY (threshold £90k) === +2026-07-02 09:00:32,836 - INFO - HMRC Turnover Bands: 93.1% +2026-07-02 09:00:32,836 - INFO - ONS Population: 92.6% +2026-07-02 09:00:32,836 - INFO - Employment Bands: 92.4% +2026-07-02 09:00:32,836 - INFO - Sector Distribution: 94.2% +2026-07-02 09:00:32,836 - INFO - VAT Liability by Band: 92.0% +2026-07-02 09:00:32,836 - INFO - Overall Accuracy (5 calibrated dims): 92.8% +2026-07-02 09:00:32,836 - INFO - VAT Liability by Sector: 44.8% [informational, NOT calibrated] +2026-07-02 09:00:32,836 - INFO - Total Population: 2,531,324 firms +2026-07-02 09:00:37,315 - INFO - Wrote 2,945,974 rows to /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/synthetic/synthetic_firms_2024-25.csv (142.8 MB) +Calibration report — synthetic UK firm populations + +Accuracy = max(0, 1 - relative absolute error); reported error is +the clipped complement. Overall averages the five calibrated +dimensions and excludes the VAT-liability-by-sector diagnostic. + +================================================================ + Vintage 2023-24 | threshold £85k +================================================================ + rows (firm types): 2,941,232 + weighted population: 2,460,542 firms +---------------------------------------------------------------- + Dimension accuracy error +---------------------------------------------------------------- + HMRC Turnover Bands 93.8% 6.2% + ONS Population 90.3% 9.7% + Employment Bands 77.9% 22.1% + Sector Distribution 92.7% 7.3% + VAT Liability by Band 91.3% 8.7% +---------------------------------------------------------------- + Overall (5 calibrated dims) 89.2% 10.8% +---------------------------------------------------------------- + Informational diagnostic (not a calibration target): + VAT Liability by Sector 45.2% 54.8% +================================================================ + +================================================================ + Vintage 2024-25 | threshold £90k +================================================================ + rows (firm types): 2,945,974 + weighted population: 2,531,324 firms +---------------------------------------------------------------- + Dimension accuracy error +---------------------------------------------------------------- + HMRC Turnover Bands 93.1% 6.9% + ONS Population 92.6% 7.4% + Employment Bands 92.4% 7.6% + Sector Distribution 94.2% 5.8% + VAT Liability by Band 92.0% 8.0% +---------------------------------------------------------------- + Overall (5 calibrated dims) 92.8% 7.2% +---------------------------------------------------------------- + Informational diagnostic (not a calibration target): + VAT Liability by Sector 44.8% 55.2% +================================================================ + +Done: 2/2 vintage(s) reported. + +Generating figures (both vintages)... +Generating firms_by_turnover_band_85k.png... + saved /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/results/firms_by_turnover_band_85k.png +Generating vat_firms_by_turnover_band_85k.png... + saved /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/results/vat_firms_by_turnover_band_85k.png +Generating turnover_distribution_85k.png... + saved /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/results/turnover_distribution_85k.png +Generating firms_by_turnover_band_90k.png... + saved /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/results/firms_by_turnover_band_90k.png +Generating vat_firms_by_turnover_band_90k.png... + saved /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/results/vat_firms_by_turnover_band_90k.png +Generating turnover_distribution_90k.png... + saved /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/results/turnover_distribution_90k.png + done. diff --git a/build_obr.log b/build_obr.log new file mode 100644 index 0000000..9c0e506 --- /dev/null +++ b/build_obr.log @@ -0,0 +1,55 @@ +2026-07-02 07:50:34,376 - INFO - Generating synthetic firms (threshold=£85k, seed=42, device=cpu) +2026-07-02 07:50:34,376 - INFO - Loading processed input tables from /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/processed/2023-24 +2026-07-02 07:50:34,379 - INFO - ons_turnover 89 rows +2026-07-02 07:50:34,379 - INFO - ons_employment 89 rows +2026-07-02 07:50:34,379 - INFO - hmrc_population_band 20 rows +2026-07-02 07:50:34,379 - INFO - hmrc_population_sector 89 rows +2026-07-02 07:50:34,379 - INFO - hmrc_liability_band 20 rows +2026-07-02 07:50:34,379 - INFO - hmrc_liability_sector 88 rows +2026-07-02 07:50:34,381 - INFO - Near-threshold targets: 25 OBR £1k bins over [65k, 90k], interpolated 2023-24 profile, total 453,902 firms +2026-07-02 07:50:34,381 - INFO - ONS total firms: 2,724,775 +2026-07-02 07:50:34,381 - INFO - HMRC VAT-registered firms (latest year): 2,178,960 +2026-07-02 07:50:34,381 - INFO - Generating base firms from ONS structure... +2026-07-02 07:50:34,701 - INFO - Generated 2,724,775 base firms +2026-07-02 07:50:34,715 - INFO - Generating input values... +2026-07-02 07:50:34,902 - INFO - Input/output ratio: mean=0.60 std=0.19; mean value-added share=0.40; firms with negative value added: 0 +2026-07-02 07:50:34,902 - INFO - Assigning employment from ONS distribution... +2026-07-02 07:50:37,584 - INFO - Target matrix shape: (134, 2724775) +2026-07-02 07:50:37,584 - INFO - Targets: 7 turnover + 88 sector + 7 employment + 0 VAT-liability sector + 7 VAT-liability band + 25 near-threshold = 134 +2026-07-02 07:50:37,584 - INFO - Starting multi-objective weight optimization... +2026-07-02 07:50:38,445 - INFO - Iteration 0: loss = 0.167092 +2026-07-02 07:50:44,994 - INFO - Iteration 100: loss = 0.072900 +2026-07-02 07:50:51,409 - INFO - Iteration 200: loss = 0.052294 +2026-07-02 07:50:57,809 - INFO - Iteration 300: loss = 0.047141 +2026-07-02 07:51:04,521 - INFO - Iteration 400: loss = 0.046373 +2026-07-02 07:51:11,832 - INFO - Iteration 500: loss = 0.046060 +2026-07-02 07:51:18,416 - INFO - Iteration 600: loss = 0.045846 +2026-07-02 07:51:25,000 - INFO - Iteration 700: loss = 0.045693 +2026-07-02 07:51:31,422 - INFO - Iteration 800: loss = 0.045600 +2026-07-02 07:51:37,817 - INFO - Iteration 900: loss = 0.045480 +2026-07-02 07:51:44,498 - INFO - Optimization complete. Turnover-band fit: +2026-07-02 07:51:44,498 - INFO - £1_to_Threshold 862581 vs 766560 (87.5%) +2026-07-02 07:51:44,498 - INFO - £Threshold_to_£150k 331745 vs 305320 (91.3%) +2026-07-02 07:51:44,498 - INFO - £150k_to_£300k 364485 vs 334470 (91.0%) +2026-07-02 07:51:44,498 - INFO - £300k_to_£500k 195978 vs 184080 (93.5%) +2026-07-02 07:51:44,499 - INFO - £500k_to_£1m 192156 vs 180500 (93.5%) +2026-07-02 07:51:44,499 - INFO - £1m_to_£10m 250716 vs 235060 (93.3%) +2026-07-02 07:51:44,499 - INFO - Greater_than_£10m 47436 vs 44680 (93.8%) +2026-07-02 07:51:44,499 - INFO - Adding 216,500 zero/negative-turnover firms (HMRC)... +2026-07-02 07:51:44,525 - INFO - Added 216,457 zero-turnover firms +2026-07-02 07:51:44,525 - INFO - Assigning employment from ONS distribution... +2026-07-02 07:51:45,420 - INFO - Assigning VAT registration flags... +2026-07-02 07:51:45,421 - INFO - Voluntary VAT row rate: 0.885 (target 678,350 / synthetic rows 766,560) +2026-07-02 07:51:45,432 - INFO - VAT: 1958215 mandatory + 678675 voluntary = 2636890 registered +2026-07-02 07:51:45,432 - INFO - Assembling final DataFrame... +2026-07-02 07:51:45,757 - INFO - Generated 2,941,232 rows, weighted population 2,461,554 +2026-07-02 07:51:46,844 - INFO - === CALIBRATION SUMMARY (threshold £85k) === +2026-07-02 07:51:46,844 - INFO - HMRC Turnover Bands: 93.8% +2026-07-02 07:51:46,844 - INFO - ONS Population: 90.3% +2026-07-02 07:51:46,844 - INFO - Employment Bands: 78.0% +2026-07-02 07:51:46,844 - INFO - Sector Distribution: 92.5% +2026-07-02 07:51:46,844 - INFO - VAT Liability by Band: 92.2% +2026-07-02 07:51:46,844 - INFO - Overall Accuracy (5 calibrated dims): 89.4% +2026-07-02 07:51:46,844 - INFO - VAT Liability by Sector: 45.4% [informational, NOT calibrated] +2026-07-02 07:51:46,844 - INFO - Total Population: 2,461,554 firms +2026-07-02 07:51:51,421 - INFO - Wrote 2,941,232 rows to /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/synthetic/synthetic_firms_2023-24.csv (142.8 MB) diff --git a/fast_build.log b/fast_build.log new file mode 100644 index 0000000..b377092 --- /dev/null +++ b/fast_build.log @@ -0,0 +1,57 @@ +2026-07-02 09:44:33,485 - INFO - Generating synthetic firms (threshold=£85k, seed=42, device=cpu) +2026-07-02 09:44:33,485 - INFO - Loading processed input tables from /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/processed/2023-24 +2026-07-02 09:44:33,493 - INFO - ons_turnover 89 rows +2026-07-02 09:44:33,493 - INFO - ons_employment 89 rows +2026-07-02 09:44:33,493 - INFO - hmrc_population_band 20 rows +2026-07-02 09:44:33,493 - INFO - hmrc_population_sector 89 rows +2026-07-02 09:44:33,493 - INFO - hmrc_liability_band 20 rows +2026-07-02 09:44:33,493 - INFO - hmrc_liability_sector 88 rows +2026-07-02 09:44:33,498 - INFO - Near-threshold targets: 25 OBR £1k bins over [65k, 90k], interpolated 2023-24 profile, total 453,902 firms +2026-07-02 09:44:33,499 - INFO - ONS total firms: 2,724,775 +2026-07-02 09:44:33,499 - INFO - HMRC VAT-registered firms (latest year): 2,178,960 +2026-07-02 09:44:33,499 - INFO - Generating base firms from ONS structure... +2026-07-02 09:44:33,852 - INFO - Generated 2,724,775 base firms +2026-07-02 09:44:33,869 - INFO - Generating input values... +2026-07-02 09:44:34,056 - INFO - Input/output ratio: mean=0.60 std=0.19; mean value-added share=0.40; firms with negative value added: 0 +2026-07-02 09:44:34,292 - INFO - Stratified thinning: kept 408,647 of 2,724,775 rows (15.0%); base weights 1.0-27.2; window [15k, 150k] at 30%, tails at 5% +2026-07-02 09:44:34,295 - INFO - Assigning employment from ONS distribution... +2026-07-02 09:44:34,873 - INFO - Target matrix shape: (133, 408647) +2026-07-02 09:44:34,873 - INFO - Targets: 7 turnover + 88 sector + 7 employment + 0 VAT-liability sector + 6 VAT-liability band + 25 near-threshold = 133 +2026-07-02 09:44:34,873 - INFO - Starting multi-objective weight optimization... +2026-07-02 09:44:35,688 - INFO - Iteration 0: loss = 0.166471 +2026-07-02 09:44:36,831 - INFO - Iteration 100: loss = 0.067381 +2026-07-02 09:44:37,968 - INFO - Iteration 200: loss = 0.046828 +2026-07-02 09:44:39,044 - INFO - Iteration 300: loss = 0.044058 +2026-07-02 09:44:40,109 - INFO - Iteration 400: loss = 0.043850 +2026-07-02 09:44:41,250 - INFO - Iteration 500: loss = 0.043622 +2026-07-02 09:44:42,301 - INFO - Iteration 600: loss = 0.043493 +2026-07-02 09:44:43,367 - INFO - Iteration 700: loss = 0.043393 +2026-07-02 09:44:44,434 - INFO - Iteration 800: loss = 0.043393 +2026-07-02 09:44:45,495 - INFO - Iteration 900: loss = 0.043380 +2026-07-02 09:44:46,566 - INFO - Optimization complete. Turnover-band fit: +2026-07-02 09:44:46,566 - INFO - £1_to_Threshold 863897 vs 766560 (87.3%) +2026-07-02 09:44:46,566 - INFO - £Threshold_to_£150k 336717 vs 305320 (89.7%) +2026-07-02 09:44:46,566 - INFO - £150k_to_£300k 361892 vs 334470 (91.8%) +2026-07-02 09:44:46,566 - INFO - £300k_to_£500k 196186 vs 184080 (93.4%) +2026-07-02 09:44:46,566 - INFO - £500k_to_£1m 192123 vs 180500 (93.6%) +2026-07-02 09:44:46,566 - INFO - £1m_to_£10m 250195 vs 235060 (93.6%) +2026-07-02 09:44:46,566 - INFO - Greater_than_£10m 47485 vs 44680 (93.7%) +2026-07-02 09:44:46,566 - INFO - Adding 216,500 zero/negative-turnover firms (HMRC)... +2026-07-02 09:44:46,582 - INFO - Added 216,464 zero-turnover firms +2026-07-02 09:44:46,582 - INFO - Assigning employment from ONS distribution... +2026-07-02 09:44:46,742 - INFO - Assigning VAT registration flags... +2026-07-02 09:44:46,743 - INFO - Voluntary VAT row rate: 0.885 (target 678,350 / base-weighted rows 766,560) +2026-07-02 09:44:46,746 - INFO - VAT: 217838 mandatory + 168738 voluntary = 386576 registered +2026-07-02 09:44:46,746 - INFO - Assembling final DataFrame... +2026-07-02 09:44:46,812 - INFO - Generated 625,111 rows, weighted population 2,464,958 +2026-07-02 09:44:47,028 - INFO - VAT liability £1-to-Threshold (informational, NOT calibrated): 43.5% +2026-07-02 09:44:47,028 - INFO - === CALIBRATION SUMMARY (threshold £85k) === +2026-07-02 09:44:47,028 - INFO - HMRC Turnover Bands: 93.7% +2026-07-02 09:44:47,028 - INFO - ONS Population: 90.5% +2026-07-02 09:44:47,028 - INFO - Employment Bands: 79.3% +2026-07-02 09:44:47,028 - INFO - Sector Distribution: 92.6% +2026-07-02 09:44:47,028 - INFO - VAT Liability by Band: 92.7% +2026-07-02 09:44:47,028 - INFO - Overall Accuracy (5 calibrated dims): 89.7% +2026-07-02 09:44:47,028 - INFO - VAT Liability by Sector: 42.1% [informational, NOT calibrated] +2026-07-02 09:44:47,028 - INFO - Total Population: 2,464,958 firms +2026-07-02 09:44:47,917 - INFO - Wrote 625,111 rows to /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/synthetic/fast_check.csv (26.4 MB) diff --git a/latex2.log b/latex2.log new file mode 100644 index 0000000..c77c74d --- /dev/null +++ b/latex2.log @@ -0,0 +1,1292 @@ +Rc files read (in order): + NONE +Latexmk: This is Latexmk, John Collins, 9 March 2026. Version 4.88. +Latexmk: applying rule 'lualatex'... +Rule 'lualatex': Reasons for rerun +Changed files or newly in use/created: + Appendix/a_inference.tex + Sections/behavioural.tex + Sections/bunching.tex + Sections/conclusion.tex + Sections/data.tex + Sections/intro.tex + Sections/model.tex + Sections/static.tex + figures/dynamic_cost_vs_elasticity.png + figures/dynamic_notch_fit_e017.png + frontmatter.tex +Category 'changed_user': + Appendix/a_inference.tex + Sections/behavioural.tex + Sections/bunching.tex + Sections/conclusion.tex + Sections/data.tex + Sections/intro.tex + Sections/model.tex + Sections/static.tex + figures/dynamic_cost_vs_elasticity.png + figures/dynamic_notch_fit_e017.png + frontmatter.tex + +------------ +Run number 1 of rule 'lualatex' +------------ +------------ +Running 'lualatex -interaction=nonstopmode -halt-on-error -recorder "main.tex"' +------------ +This is LuaHBTeX, Version 1.24.0 (TeX Live 2026) + restricted system commands enabled. +(./main.tex +LaTeX2e <2025-11-01> +L3 programming layer <2026-01-19> + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/article.cls +Document Class: article 2025/01/22 v1.4n Standard LaTeX document class +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/size12.clo)) +(./YGTemplate.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3kernel/expl3.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3backend/l3backend-luatex.def))) + (/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec-luatex.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/babel.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/locale/en/babel-english.t +ex) (/usr/local/texlive/2026/texmf-dist/tex/generic/babel-english/english.ldf)) + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/lm/t1lmr.fd)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/a4wide/a4wide.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/ntgclass/a4.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/xcolor/xcolor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/color.cfg) + +Package xcolor Warning: Package option `usenames' is obsolete and ignored on in +put line 265. + +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-def/luatex.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/mathcolor.ltx)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/dvipsnam.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphicx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/keyval.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphics.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/trig.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/graphics.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/tabularx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/array.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.sty +**************************************** +* Local config file subfigure.cfg used * +**************************************** +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/float/float.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption3.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/subcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fnpct/fnpct.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/etoolbox/etoolbox.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/infwarerr/infwarerr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/iftex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty)))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts/kpfonts.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/kpfonts-otf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/realscripts/realscripts.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpRoman.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpLight.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpSans.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMono.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-luatex. +sty (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fix-cm.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ts1enc.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsmath.sty +For additional information on amsmath, use the `?' option. +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amstext.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsgen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsbsy.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsopn.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/lualatex/lualatex-math/lualatex-math.st +y) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-table.t +ex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMath-Regular.fontsp +ec))) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/pgf.revision.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeyslibraryfil +tered.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-luatex.d +ef +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-p +df.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol. +code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigo +nometric.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.rando +m.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.compa +rison.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integ +erarithmetics.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfint.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconst +ruct.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicst +ate.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransform +ations.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathproce +ssing.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretranspare +ncy.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code. +tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-0-65.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-1-18.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/math/pgfmath.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex)) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.cod +e.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothan +dlers.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarytopaths.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplots.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgfplotssysgeneric +.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgfplotslibrary.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_loader.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryfpu.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_pgfutil-common-lists.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/luamath/pgflibrar +yluamath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code +.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructure.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructureext.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +array.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +matrix.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +shared.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +deque.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.co +de.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.da +ta.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.verb +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgflibrarypgfplot +s.surfshading.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgflibrarypgfplots +.surfshading.pgfsys-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolormap. +code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolor.cod +e.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.c +ode.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplothandle +r.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplotimage. +code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscoordprocessin +g.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.errorbars.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.markers.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.paths.code.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduledecoration +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathmorphing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathmorphing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathreplacing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathreplacing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.contourlua.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryplotmarks.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplotmar +ks.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplotstable.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.coltype.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesome.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifxetex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifluatex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-ge +neric.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-xe +luatex.tex)) (/usr/local/texlive/2026/texmf-dist/tex/latex/psfrag/psfrag.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryintersections.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryinterse +ctions.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypatterns.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibrarypattern +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +decorations.softclip.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryf +illbetween.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.decorations.softclip.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/booktabs/booktabs.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/bm.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/rotating.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ifthen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hyperref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdfescape/pdfescape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hycolor/hycolor.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/nameref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/refcount/refcount.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/gettitlestring/gettitlestring.s +ty (/usr/local/texlive/2026/texmf-dist/tex/latex/kvoptions/kvoptions.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/stringenc/stringenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/pd1enc.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/intcalc/intcalc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/puenc.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/url/url.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/bitset/bitset.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hluatex.def +(/usr/local/texlive/2026/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty + +(/usr/local/texlive/2026/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +))) (/usr/local/texlive/2026/texmf-dist/tex/latex/todonotes/todonotes.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/xkeyval/xkeyval.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkeyval.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkvutils.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypositioning.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/calc.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/natbib/natbib.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/paralist/paralist.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/multicol.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/longtable.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/multirow/multirow.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/lscape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/chngcntr/chngcntr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/footmisc/footmisc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fmtcount.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcprefix.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcnumparser.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fc-english.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime-defaults.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/threeparttable/threeparttable.sty +) (/usr/local/texlive/2026/texmf-dist/tex/latex/diagbox/diagbox.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/p2e-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/sectsty/sectsty.sty + +LaTeX Warning: Command \underbar has changed. + Check if current package is valid. + + +LaTeX Warning: Command \underline has changed. + Check if current package is valid. + +)) (./title_metadata.tex) (./main.aux) +(/usr/local/texlive/2026/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +) (/usr/local/texlive/2026/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/ltcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations-basic-d +ictionary-english.trsl) + +Package pgfplots Warning: running in backwards compatibility mode (unsuitable t +ick labels; missing features). Consider writing \pgfplotsset{compat=1.18} into +your preamble. + on input line 12. + +(./main.out) (./main.out) + +Package todonotes Warning: The length marginparwidth is less than 2cm and will +most likely cause issues with the appearance of inserted todonotes. The issue c +an be solved by adding a line like \setlength {\marginparwidth }{2cm} prior to +loading the todonotes package. on input line 12. + +(./frontmatter.tex +Overfull \hbox (8.09319pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 registration-threshold re-forms, re-leased with its sy +nthetic-data gen-er-a-tor. The thresh- + +Overfull \hbox (8.50201pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/it/10.95 shape \TU/KpRoman(1)/m/n/10.95 (a ta-per) and \TU/KpR +oman(1)/m/it/10.95 rate \TU/KpRoman(1)/m/n/10.95 (a reduced-rate band) re-forms + stat-i-cally on a com-mon £184.8bn + +Overfull \hbox (45.11325pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 base: rais-ing the thresh-old to £100,000 costs £783 +m, a grad-u-ated ta-per over £85,000--£105,000 +[1 +Non-PDF special ignored!{/usr/local/texlive/2026/texmf-var/fonts/map/pdftex/upd +map/pdftex.map}] [2]) (./body.tex (./Sections/intro.tex [3<./figures/firms_by_t +urnover_band_85k.png><./figures/vat_firms_by_turnover_band_85k.png>] [4] +Overfull \hbox (0.9187pt too wide) in paragraph at lines 49--50 +[]\TU/KpRoman(1)/m/n/12 Third, con-di-tional on the as-sumed elas-tic-ity, inte +nsive-margin re-sponses barely move + +Overfull \hbox (13.0106pt too wide) in paragraph at lines 51--52 +\TU/KpRoman(1)/m/n/12 pa-per demon-strates the point in three di-rec-tions. The + 2023--24 pop-u-la-tion’s near-threshold +[5] [6]) (./Sections/background.tex [7]) (./Sections/data.tex [8<./figures/obr_ +vat_bunching_85k.png>] +Overfull \hbox (0.61864pt too wide) in paragraph at lines 4--16 +\TU/KpRoman(1)/m/n/12 Study-ing firm re-sponses at the thresh-old needs firm-le +vel turnover near the cut-off, which +[9] +Overfull \hbox (0.3166pt too wide) in paragraph at lines 60--64 +[]\TU/KpRoman(1)/m/n/12 The base pop-u-la-tion re-pro-duces the ONS struc-ture +but not the HMRC VAT-registered + +Overfull \hbox (23.08046pt too wide) in paragraph at lines 75--101 +\TU/KpRoman(1)/m/n/12 Chart C data give HMRC counts of busi-nesses by £1,000 t +urnover band over £65,000--£90,000 +[10] +Overfull \hbox (14.26959pt too wide) in paragraph at lines 128--154 +\TU/KpRoman(1)/m/n/12 statu-tory thresh-old was £85,000. The HMRC band tar-get +s step down across the threshold--- + +Overfull \hbox (21.09047pt too wide) in paragraph at lines 128--154 +\TU/KpRoman(1)/m/n/12 brated den-sity rises into the thresh-old (about $\TU/KpM +ath-Regular.otf(1)/m/n/12 13[]800$ \TU/KpRoman(1)/m/n/12 firms per £1,000 in t +he £84,000--£85,000 +[11]) (./Sections/static.tex [12<./figures/turnover_distribution_85k.png>] +[13] [14<./figures/vat_threshold_revenue_impact.png>] +Overfull \hbox (13.10669pt too wide) in paragraph at lines 168--182 +\TU/KpRoman(1)/m/n/12 The thresh-old sweep above moves the \TU/KpRoman(1)/m/it/ +12 lo-ca-tion \TU/KpRoman(1)/m/n/12 of a sin-gle cut-off. The same static princ +iple--- +[15] [16<./figures/revenue_impact_2025_26.png><./figures/firms_impact_2025_26.p +ng>]) (./Sections/bunching.tex +Overfull \hbox (6.67659pt too wide) in paragraph at lines 4--22 +\TU/KpRoman(1)/m/n/12 ([][]2011[][]) and [][]Kleven and Waseem[][] ([][]2013[][ +])---as ap-plied to UK VAT data by [][]Liu et al.[][] ([][]2021[][])---to +[17] +Overfull \hbox (25.36118pt too wide) in paragraph at lines 66--77 +\TU/KpRoman(1)/m/n/12 the ap-prox-i-ma-tion hold-ing when $\TU/KpMath-Regular.o +tf(1)/m/n/12 𝑔$ \TU/KpRoman(1)/m/n/12 is lo-cally smooth. The bunch-ing ra-t +io $\TU/KpMath-Regular.otf(1)/m/n/12 𝑏(𝑦[]) = 𝐵(𝑦[])/𝑔(𝑦[]) +≈ +[18] [19] [20<./figures/bunching_analysis_85k.png><./figures/bunching_analysis_ +90k.png>] [21]) (./Sections/model.tex +Overfull \hbox (9.26462pt too wide) in paragraph at lines 22--29 +\TU/KpRoman(1)/m/n/12 Two pop-u-la-tions are out-side its scope and are treated + as such through-out: below-threshold +[22] [23] [24<./figures/dynamic_notch_fit_e017.png>]) +(./Sections/behavioural.tex +Overfull \hbox (8.2552pt too wide) in paragraph at lines 139--1 +\TU/KpMath-Regular.otf(1)/m/n/12 (𝜏 − 𝑟) 𝑇[] = £5[]250$\TU/KpRoman( +1)/m/n/12 . The firm counts con-firm this (\TU/KpMono(0)/m/n/12 results/dominat +ed_region_mass.txt\TU/KpRoman(1)/m/n/12 ): +[25] +Overfull \hbox (0.45064pt too wide) in paragraph at lines 76--83 +\TU/KpRoman(1)/m/n/12 firm’s op-ti-mal turnover un-der a coun-ter-fac-tual sc +hed-ule, \TU/KpRoman(1)/m/it/12 given \TU/KpRoman(1)/m/n/12 that its ob-served +turnover + +Overfull \hbox (2.70668pt too wide) in paragraph at lines 87--96 +\TU/KpRoman(1)/m/n/12 The in-ten-sive re-sponse de-pends only on $\TU/KpMath-Re +gular.otf(1)/m/n/12 𝑒$\TU/KpRoman(1)/m/n/12 , the statu-tory rate, and the s +ched-ule fractions--- +[26] +Overfull \hbox (19.06874pt too wide) in paragraph at lines 97--117 +[]\TU/KpRoman(1)/b/n/12 Region-confined scope.[] \TU/KpRoman(1)/m/n/12 The mar- +gin priced here is purely \TU/KpRoman(1)/m/it/12 in-ten-sive\TU/KpRoman(1)/m/n/ +12 : each firm re-optimises + +Overfull \hbox (1.25473pt too wide) in paragraph at lines 118--129 +[]\TU/KpRoman(1)/b/n/12 Con-di-tional on $\TU/KpMath-Regular.otf(1)/m/n/12 +𝑒$\TU/KpRoman(1)/b/n/12 .[] \TU/KpRoman(1)/m/n/12 The elas-tic-ity $\TU/KpMa +th-Regular.otf(1)/m/n/12 𝑒$ \TU/KpRoman(1)/m/n/12 is not iden-ti-fied from t +hese data, so ev-ery be-havioural +[27<./figures/formulation_a_optima.png>] +Overfull \hbox (34.0586pt too wide) in paragraph at lines 154--166 + [][] +[28]) (./Sections/conclusion.tex +Overfull \hbox (20.66867pt too wide) in paragraph at lines 4--13 +\TU/KpRoman(1)/m/n/12 the UK VAT reg-is-tra-tion thresh-old, re-leased in full- +--including its synthetic-data generator--- + +Overfull \hbox (68.06161pt too wide) in paragraph at lines 23--35 + [][] +[29] [30<./figures/dynamic_cost_vs_elasticity.png>] [31]) [32] (./main.bbl +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +[]\TU/KpRoman(1)/m/n/10.95 HM Rev-enue and Cus-toms (2024) ``In-creas-ing the V +AT Reg-is-tra-tion Thresh-old,'' + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpRoman(1)/m/n/10.95 Tax in-for-ma-tion and im-pact note, GOV.UK, [][]$\TU/ +KpMono(0)/m/n/10.95 https://www.gov.uk/government/ + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpMono(0)/m/n/10.95 publications/vat-[]increasing-[]the-[]registration-[]an +d-[]deregistration-[]thresholds/ +[33] +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +[]\TU/KpRoman(1)/m/n/10.95 HM Trea-sury (2018) ``VAT Reg-is-tra-tion Thresh-old +: Call for Ev-i-dence,'' HM + +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +\TU/KpRoman(1)/m/n/10.95 Trea-sury, March 2018, [][]$\TU/KpMono(0)/m/n/10.95 ht +tps://www.gov.uk/government/consultations/ + +Underfull \hbox (badness 7869) in paragraph at lines 106--109 +[] [] \TU/KpRoman(1)/m/n/10.95 (2024) ``Spring Bud-get 2024: Pol-icy Cost-ings, +'' HM Trea-sury, March 2024, + +Underfull \hbox (badness 10000) in paragraph at lines 106--109 +[][]$\TU/KpMono(0)/m/n/10.95 https://assets.publishing.service.gov.uk/media/65e +7920c08eef600155a5617/ + +Underfull \hbox (badness 4886) in paragraph at lines 133--137 +[]\TU/KpRoman(1)/m/n/10.95 Liu, Li, Ben Lock-wood, and Eddy H. F. Tam (2024) `` +Small Firm Growth and the + +Underfull \hbox (badness 2865) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 VAT Thresh-old: Ev-i-dence for the UK,'' IMF Work-ing +Pa-perWP/24/33, In-ter-na-tional + +Underfull \hbox (badness 10000) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 Mon-e-tary Fund, [][]$\TU/KpMono(0)/m/n/10.95 https:// +www.imf.org/en/publications/wp/issues/2024/02/16/ + +Underfull \hbox (badness 1490) in paragraph at lines 139--143 +\TU/KpRoman(1)/m/n/10.95 West Ben-gal, In-dia,'' TaxDev / In-sti-tute for Fis-c +al Stud-ies, [][]$\TU/KpMono(0)/m/n/10.95 https://www.taxdev.org/ + +Underfull \hbox (badness 10000) in paragraph at lines 146--149 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice for Bud-get Re-spon-si-bil-ity (2023) ``The +Im-pact of the Frozen VAT Reg-is-tra- + +Underfull \hbox (badness 4886) in paragraph at lines 146--149 +\TU/KpRoman(1)/m/n/10.95 tion Thresh-old,'' Eco-nomic and Fis-cal Out-look, Mar +ch 2023, [][]$\TU/KpMono(0)/m/n/10.95 https://obr.uk/box/ + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice of Tax Sim-pli-fi-ca-tion (2017) ``Value Add +ed Tax: Routes to Sim-pli-fi-ca-tion,'' + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +\TU/KpRoman(1)/m/n/10.95 OTS re-port, Novem-ber 2017, [][]$\TU/KpMono(0)/m/n/10 +.95 https://assets.publishing.service.gov.uk/media/ +[34]) [35] (./Appendix/appendix.tex (./Appendix/a_data.tex +Overfull \hbox (11.12668pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion check rather than a silent re-place-ment. The snap-s +hot used here is Pol-i-cyEngine/ledger + +Overfull \hbox (30.38661pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 and max-i-mum nu-meric dif-fer-ence zero. (The ``2024--25 + vin-tage'' here de-notes the HMRC/ONS + +Overfull \hbox (3.00157pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion cal-i-brates to.) A 1,000-iteration Pop-u-lace run f +rom those tar-gets gen-er-ated 2,946,015 + +Overfull \hbox (58.07478pt too wide) in paragraph at lines 32--61 +\TU/KpMono(0)/m/n/12 firm-microsim-populace-ledger \TU/KpRoman(1)/m/n/12 and ch +ecked into \TU/KpMono(0)/m/n/12 results/populace_ledger_comparison.txt +[36]) (./Appendix/a_inference.tex +Overfull \hbox (8.25868pt too wide) in paragraph at lines 4--25 +\TU/KpMono(0)/m/n/12 results/recovery_bunching.txt\TU/KpRoman(1)/m/n/12 . The e +s-ti-ma-tor re-ports the ge-om-e-try only---the bunch- + +Overfull \hbox (11.25064pt too wide) in paragraph at lines 4--25 +\TU/KpRoman(1)/m/n/12 cess mass to an elas-tic-ity is not iden-ti-fied with-out + functional-form as-sump-tions ([][]Blomquist +[37] [38] [39] +Underfull \hbox (badness 1845) in paragraph at lines 157--157 +[][]\TU/KpRoman(1)/b/n/12 Ta-ble A.3[][]: []|\TU/KpRoman(1)/m/n/12 Power (re-co +v-ery) test on the step-free pop-u-la-tion: Kleven--Waseem- +))) [40] (./main.aux) + +LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right. + + +Package rerunfilecheck Warning: File `main.out' has changed. +(rerunfilecheck) Rerun to get outlines right +(rerunfilecheck) or use package `bookmark'. + +) +(see the transcript file for additional information) + 1355 words of node memory still in use: + 6 hlist, 2 vlist, 2 rule, 15 glue, 4 kern, 1 glyph, 169 attribute, 77 glue_s +pec, 85 attribute_list, 2 write, 28 pdf_action nodes + avail lists: 1:1,2:874,3:445,4:203,5:722,6:29,7:9305,8:146,9:398,10:28,11:68 +4 + +warning (pdf backend): unreferenced destination with name 'Hfootnote.2' + +warning (pdf backend): unreferenced destination with name 'Hfootnote.1' + + +Output written on main.pdf (40 pages, 2159383 bytes). +Transcript written on main.log. +Latexmk: Getting log file 'main.log' +Latexmk: Examining 'main.fls' +Latexmk: Examining 'main.log' +Latexmk: Found input bbl file 'main.bbl' +Latexmk: References changed. +Latexmk: References changed. +Latexmk: References changed. +Latexmk: Log file says output to 'main.pdf' +Latexmk: Using bibtex to make bibliography file(s). + ===Source file 'main.bbl' for 'lualatex' +Latexmk: Found bibliography file(s): + ./references.bib +Latexmk: applying rule 'bibtex main'... +Rule 'bibtex main': Reasons for rerun +Changed files or newly in use/created: + main.aux + +------------ +Run number 1 of rule 'bibtex main' +------------ +------------ +Running 'bibtex "main.aux"' +------------ +This is BibTeX, Version 0.99e (TeX Live 2026) +The top-level auxiliary file: main.aux +The style file: econ.bst +Database file #1: references.bib +Latexmk: applying rule 'lualatex'... +Rule 'lualatex': Reasons for rerun +Changed files or newly in use/created: + main.aux + main.out + +------------ +Run number 2 of rule 'lualatex' +------------ +------------ +Running 'lualatex -interaction=nonstopmode -halt-on-error -recorder "main.tex"' +------------ +This is LuaHBTeX, Version 1.24.0 (TeX Live 2026) + restricted system commands enabled. +(./main.tex +LaTeX2e <2025-11-01> +L3 programming layer <2026-01-19> + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/article.cls +Document Class: article 2025/01/22 v1.4n Standard LaTeX document class +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/size12.clo)) +(./YGTemplate.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3kernel/expl3.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3backend/l3backend-luatex.def))) + (/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec-luatex.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/babel.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/locale/en/babel-english.t +ex) (/usr/local/texlive/2026/texmf-dist/tex/generic/babel-english/english.ldf)) + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/lm/t1lmr.fd)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/a4wide/a4wide.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/ntgclass/a4.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/xcolor/xcolor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/color.cfg) + +Package xcolor Warning: Package option `usenames' is obsolete and ignored on in +put line 265. + +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-def/luatex.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/mathcolor.ltx)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/dvipsnam.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphicx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/keyval.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphics.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/trig.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/graphics.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/tabularx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/array.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.sty +**************************************** +* Local config file subfigure.cfg used * +**************************************** +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/float/float.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption3.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/subcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fnpct/fnpct.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/etoolbox/etoolbox.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/infwarerr/infwarerr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/iftex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty)))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts/kpfonts.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/kpfonts-otf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/realscripts/realscripts.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpRoman.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpLight.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpSans.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMono.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-luatex. +sty (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fix-cm.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ts1enc.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsmath.sty +For additional information on amsmath, use the `?' option. +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amstext.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsgen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsbsy.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsopn.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/lualatex/lualatex-math/lualatex-math.st +y) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-table.t +ex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMath-Regular.fontsp +ec))) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/pgf.revision.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeyslibraryfil +tered.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-luatex.d +ef +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-p +df.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol. +code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigo +nometric.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.rando +m.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.compa +rison.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integ +erarithmetics.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfint.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconst +ruct.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicst +ate.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransform +ations.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathproce +ssing.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretranspare +ncy.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code. +tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-0-65.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-1-18.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/math/pgfmath.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex)) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.cod +e.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothan +dlers.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarytopaths.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplots.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgfplotssysgeneric +.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgfplotslibrary.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_loader.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryfpu.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_pgfutil-common-lists.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/luamath/pgflibrar +yluamath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code +.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructure.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructureext.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +array.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +matrix.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +shared.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +deque.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.co +de.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.da +ta.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.verb +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgflibrarypgfplot +s.surfshading.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgflibrarypgfplots +.surfshading.pgfsys-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolormap. +code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolor.cod +e.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.c +ode.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplothandle +r.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplotimage. +code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscoordprocessin +g.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.errorbars.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.markers.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.paths.code.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduledecoration +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathmorphing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathmorphing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathreplacing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathreplacing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.contourlua.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryplotmarks.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplotmar +ks.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplotstable.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.coltype.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesome.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifxetex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifluatex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-ge +neric.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-xe +luatex.tex)) (/usr/local/texlive/2026/texmf-dist/tex/latex/psfrag/psfrag.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryintersections.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryinterse +ctions.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypatterns.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibrarypattern +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +decorations.softclip.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryf +illbetween.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.decorations.softclip.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/booktabs/booktabs.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/bm.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/rotating.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ifthen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hyperref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdfescape/pdfescape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hycolor/hycolor.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/nameref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/refcount/refcount.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/gettitlestring/gettitlestring.s +ty (/usr/local/texlive/2026/texmf-dist/tex/latex/kvoptions/kvoptions.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/stringenc/stringenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/pd1enc.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/intcalc/intcalc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/puenc.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/url/url.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/bitset/bitset.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hluatex.def +(/usr/local/texlive/2026/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty + +(/usr/local/texlive/2026/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +))) (/usr/local/texlive/2026/texmf-dist/tex/latex/todonotes/todonotes.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/xkeyval/xkeyval.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkeyval.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkvutils.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypositioning.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/calc.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/natbib/natbib.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/paralist/paralist.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/multicol.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/longtable.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/multirow/multirow.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/lscape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/chngcntr/chngcntr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/footmisc/footmisc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fmtcount.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcprefix.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcnumparser.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fc-english.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime-defaults.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/threeparttable/threeparttable.sty +) (/usr/local/texlive/2026/texmf-dist/tex/latex/diagbox/diagbox.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/p2e-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/sectsty/sectsty.sty + +LaTeX Warning: Command \underbar has changed. + Check if current package is valid. + + +LaTeX Warning: Command \underline has changed. + Check if current package is valid. + +)) (./title_metadata.tex) (./main.aux) +(/usr/local/texlive/2026/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +) (/usr/local/texlive/2026/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/ltcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations-basic-d +ictionary-english.trsl) + +Package pgfplots Warning: running in backwards compatibility mode (unsuitable t +ick labels; missing features). Consider writing \pgfplotsset{compat=1.18} into +your preamble. + on input line 12. + +(./main.out) (./main.out) + +Package todonotes Warning: The length marginparwidth is less than 2cm and will +most likely cause issues with the appearance of inserted todonotes. The issue c +an be solved by adding a line like \setlength {\marginparwidth }{2cm} prior to +loading the todonotes package. on input line 12. + +(./frontmatter.tex +Overfull \hbox (8.09319pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 registration-threshold re-forms, re-leased with its sy +nthetic-data gen-er-a-tor. The thresh- + +Overfull \hbox (8.50201pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/it/10.95 shape \TU/KpRoman(1)/m/n/10.95 (a ta-per) and \TU/KpR +oman(1)/m/it/10.95 rate \TU/KpRoman(1)/m/n/10.95 (a reduced-rate band) re-forms + stat-i-cally on a com-mon £184.8bn + +Overfull \hbox (45.11325pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 base: rais-ing the thresh-old to £100,000 costs £783 +m, a grad-u-ated ta-per over £85,000--£105,000 +[1 +Non-PDF special ignored!{/usr/local/texlive/2026/texmf-var/fonts/map/pdftex/upd +map/pdftex.map}] [2]) (./body.tex (./Sections/intro.tex [3<./figures/firms_by_t +urnover_band_85k.png><./figures/vat_firms_by_turnover_band_85k.png>] [4] +Overfull \hbox (0.9187pt too wide) in paragraph at lines 49--50 +[]\TU/KpRoman(1)/m/n/12 Third, con-di-tional on the as-sumed elas-tic-ity, inte +nsive-margin re-sponses barely move + +Overfull \hbox (13.0106pt too wide) in paragraph at lines 51--52 +\TU/KpRoman(1)/m/n/12 pa-per demon-strates the point in three di-rec-tions. The + 2023--24 pop-u-la-tion’s near-threshold +[5] [6]) (./Sections/background.tex [7]) (./Sections/data.tex [8<./figures/obr_ +vat_bunching_85k.png>] +Overfull \hbox (0.61864pt too wide) in paragraph at lines 4--16 +\TU/KpRoman(1)/m/n/12 Study-ing firm re-sponses at the thresh-old needs firm-le +vel turnover near the cut-off, which +[9] +Overfull \hbox (0.3166pt too wide) in paragraph at lines 60--64 +[]\TU/KpRoman(1)/m/n/12 The base pop-u-la-tion re-pro-duces the ONS struc-ture +but not the HMRC VAT-registered + +Overfull \hbox (23.08046pt too wide) in paragraph at lines 75--101 +\TU/KpRoman(1)/m/n/12 Chart C data give HMRC counts of busi-nesses by £1,000 t +urnover band over £65,000--£90,000 +[10] +Overfull \hbox (14.26959pt too wide) in paragraph at lines 128--154 +\TU/KpRoman(1)/m/n/12 statu-tory thresh-old was £85,000. The HMRC band tar-get +s step down across the threshold--- + +Overfull \hbox (21.09047pt too wide) in paragraph at lines 128--154 +\TU/KpRoman(1)/m/n/12 brated den-sity rises into the thresh-old (about $\TU/KpM +ath-Regular.otf(1)/m/n/12 13[]800$ \TU/KpRoman(1)/m/n/12 firms per £1,000 in t +he £84,000--£85,000 +[11]) (./Sections/static.tex [12<./figures/turnover_distribution_85k.png>] +[13] [14<./figures/vat_threshold_revenue_impact.png>] +Overfull \hbox (13.10669pt too wide) in paragraph at lines 168--182 +\TU/KpRoman(1)/m/n/12 The thresh-old sweep above moves the \TU/KpRoman(1)/m/it/ +12 lo-ca-tion \TU/KpRoman(1)/m/n/12 of a sin-gle cut-off. The same static princ +iple--- +[15] [16<./figures/revenue_impact_2025_26.png><./figures/firms_impact_2025_26.p +ng>]) (./Sections/bunching.tex +Overfull \hbox (6.67659pt too wide) in paragraph at lines 4--22 +\TU/KpRoman(1)/m/n/12 ([][]2011[][]) and [][]Kleven and Waseem[][] ([][]2013[][ +])---as ap-plied to UK VAT data by [][]Liu et al.[][] ([][]2021[][])---to +[17] +Overfull \hbox (25.36118pt too wide) in paragraph at lines 66--77 +\TU/KpRoman(1)/m/n/12 the ap-prox-i-ma-tion hold-ing when $\TU/KpMath-Regular.o +tf(1)/m/n/12 𝑔$ \TU/KpRoman(1)/m/n/12 is lo-cally smooth. The bunch-ing ra-t +io $\TU/KpMath-Regular.otf(1)/m/n/12 𝑏(𝑦[]) = 𝐵(𝑦[])/𝑔(𝑦[]) +≈ +[18] [19] [20<./figures/bunching_analysis_85k.png><./figures/bunching_analysis_ +90k.png>] [21]) (./Sections/model.tex +Overfull \hbox (9.26462pt too wide) in paragraph at lines 22--29 +\TU/KpRoman(1)/m/n/12 Two pop-u-la-tions are out-side its scope and are treated + as such through-out: below-threshold +[22] [23] [24<./figures/dynamic_notch_fit_e017.png>]) +(./Sections/behavioural.tex +Overfull \hbox (8.2552pt too wide) in paragraph at lines 139--1 +\TU/KpMath-Regular.otf(1)/m/n/12 (𝜏 − 𝑟) 𝑇[] = £5[]250$\TU/KpRoman( +1)/m/n/12 . The firm counts con-firm this (\TU/KpMono(0)/m/n/12 results/dominat +ed_region_mass.txt\TU/KpRoman(1)/m/n/12 ): +[25] +Overfull \hbox (0.45064pt too wide) in paragraph at lines 76--83 +\TU/KpRoman(1)/m/n/12 firm’s op-ti-mal turnover un-der a coun-ter-fac-tual sc +hed-ule, \TU/KpRoman(1)/m/it/12 given \TU/KpRoman(1)/m/n/12 that its ob-served +turnover + +Overfull \hbox (2.70668pt too wide) in paragraph at lines 87--96 +\TU/KpRoman(1)/m/n/12 The in-ten-sive re-sponse de-pends only on $\TU/KpMath-Re +gular.otf(1)/m/n/12 𝑒$\TU/KpRoman(1)/m/n/12 , the statu-tory rate, and the s +ched-ule fractions--- +[26] +Overfull \hbox (19.06874pt too wide) in paragraph at lines 97--117 +[]\TU/KpRoman(1)/b/n/12 Region-confined scope.[] \TU/KpRoman(1)/m/n/12 The mar- +gin priced here is purely \TU/KpRoman(1)/m/it/12 in-ten-sive\TU/KpRoman(1)/m/n/ +12 : each firm re-optimises + +Overfull \hbox (1.25473pt too wide) in paragraph at lines 118--129 +[]\TU/KpRoman(1)/b/n/12 Con-di-tional on $\TU/KpMath-Regular.otf(1)/m/n/12 +𝑒$\TU/KpRoman(1)/b/n/12 .[] \TU/KpRoman(1)/m/n/12 The elas-tic-ity $\TU/KpMa +th-Regular.otf(1)/m/n/12 𝑒$ \TU/KpRoman(1)/m/n/12 is not iden-ti-fied from t +hese data, so ev-ery be-havioural +[27<./figures/formulation_a_optima.png>] +Overfull \hbox (34.0586pt too wide) in paragraph at lines 154--166 + [][] +[28]) (./Sections/conclusion.tex +Overfull \hbox (20.66867pt too wide) in paragraph at lines 4--13 +\TU/KpRoman(1)/m/n/12 the UK VAT reg-is-tra-tion thresh-old, re-leased in full- +--including its synthetic-data generator--- + +Overfull \hbox (68.06161pt too wide) in paragraph at lines 23--35 + [][] +[29] [30<./figures/dynamic_cost_vs_elasticity.png>] [31]) [32] (./main.bbl +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +[]\TU/KpRoman(1)/m/n/10.95 HM Rev-enue and Cus-toms (2024) ``In-creas-ing the V +AT Reg-is-tra-tion Thresh-old,'' + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpRoman(1)/m/n/10.95 Tax in-for-ma-tion and im-pact note, GOV.UK, [][]$\TU/ +KpMono(0)/m/n/10.95 https://www.gov.uk/government/ + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpMono(0)/m/n/10.95 publications/vat-[]increasing-[]the-[]registration-[]an +d-[]deregistration-[]thresholds/ +[33] +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +[]\TU/KpRoman(1)/m/n/10.95 HM Trea-sury (2018) ``VAT Reg-is-tra-tion Thresh-old +: Call for Ev-i-dence,'' HM + +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +\TU/KpRoman(1)/m/n/10.95 Trea-sury, March 2018, [][]$\TU/KpMono(0)/m/n/10.95 ht +tps://www.gov.uk/government/consultations/ + +Underfull \hbox (badness 7869) in paragraph at lines 106--109 +[] [] \TU/KpRoman(1)/m/n/10.95 (2024) ``Spring Bud-get 2024: Pol-icy Cost-ings, +'' HM Trea-sury, March 2024, + +Underfull \hbox (badness 10000) in paragraph at lines 106--109 +[][]$\TU/KpMono(0)/m/n/10.95 https://assets.publishing.service.gov.uk/media/65e +7920c08eef600155a5617/ + +Underfull \hbox (badness 4886) in paragraph at lines 133--137 +[]\TU/KpRoman(1)/m/n/10.95 Liu, Li, Ben Lock-wood, and Eddy H. F. Tam (2024) `` +Small Firm Growth and the + +Underfull \hbox (badness 2865) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 VAT Thresh-old: Ev-i-dence for the UK,'' IMF Work-ing +Pa-perWP/24/33, In-ter-na-tional + +Underfull \hbox (badness 10000) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 Mon-e-tary Fund, [][]$\TU/KpMono(0)/m/n/10.95 https:// +www.imf.org/en/publications/wp/issues/2024/02/16/ + +Underfull \hbox (badness 1490) in paragraph at lines 139--143 +\TU/KpRoman(1)/m/n/10.95 West Ben-gal, In-dia,'' TaxDev / In-sti-tute for Fis-c +al Stud-ies, [][]$\TU/KpMono(0)/m/n/10.95 https://www.taxdev.org/ + +Underfull \hbox (badness 10000) in paragraph at lines 146--149 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice for Bud-get Re-spon-si-bil-ity (2023) ``The +Im-pact of the Frozen VAT Reg-is-tra- + +Underfull \hbox (badness 4886) in paragraph at lines 146--149 +\TU/KpRoman(1)/m/n/10.95 tion Thresh-old,'' Eco-nomic and Fis-cal Out-look, Mar +ch 2023, [][]$\TU/KpMono(0)/m/n/10.95 https://obr.uk/box/ + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice of Tax Sim-pli-fi-ca-tion (2017) ``Value Add +ed Tax: Routes to Sim-pli-fi-ca-tion,'' + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +\TU/KpRoman(1)/m/n/10.95 OTS re-port, Novem-ber 2017, [][]$\TU/KpMono(0)/m/n/10 +.95 https://assets.publishing.service.gov.uk/media/ +[34]) [35] (./Appendix/appendix.tex (./Appendix/a_data.tex +Overfull \hbox (11.12668pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion check rather than a silent re-place-ment. The snap-s +hot used here is Pol-i-cyEngine/ledger + +Overfull \hbox (30.38661pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 and max-i-mum nu-meric dif-fer-ence zero. (The ``2024--25 + vin-tage'' here de-notes the HMRC/ONS + +Overfull \hbox (3.00157pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion cal-i-brates to.) A 1,000-iteration Pop-u-lace run f +rom those tar-gets gen-er-ated 2,946,015 + +Overfull \hbox (58.07478pt too wide) in paragraph at lines 32--61 +\TU/KpMono(0)/m/n/12 firm-microsim-populace-ledger \TU/KpRoman(1)/m/n/12 and ch +ecked into \TU/KpMono(0)/m/n/12 results/populace_ledger_comparison.txt +[36]) (./Appendix/a_inference.tex +Overfull \hbox (8.25868pt too wide) in paragraph at lines 4--25 +\TU/KpMono(0)/m/n/12 results/recovery_bunching.txt\TU/KpRoman(1)/m/n/12 . The e +s-ti-ma-tor re-ports the ge-om-e-try only---the bunch- + +Overfull \hbox (11.25064pt too wide) in paragraph at lines 4--25 +\TU/KpRoman(1)/m/n/12 cess mass to an elas-tic-ity is not iden-ti-fied with-out + functional-form as-sump-tions ([][]Blomquist +[37] [38] [39] +Underfull \hbox (badness 1845) in paragraph at lines 157--157 +[][]\TU/KpRoman(1)/b/n/12 Ta-ble A.3[][]: []|\TU/KpRoman(1)/m/n/12 Power (re-co +v-ery) test on the step-free pop-u-la-tion: Kleven--Waseem- +))) [40] (./main.aux)) +(see the transcript file for additional information) + 1355 words of node memory still in use: + 6 hlist, 2 vlist, 2 rule, 15 glue, 4 kern, 1 glyph, 169 attribute, 77 glue_s +pec, 85 attribute_list, 2 write, 28 pdf_action nodes + avail lists: 1:1,2:874,3:445,4:203,5:722,6:29,7:9305,8:146,9:398,10:28,11:68 +4 + +warning (pdf backend): unreferenced destination with name 'Hfootnote.2' + +warning (pdf backend): unreferenced destination with name 'Hfootnote.1' + + +Output written on main.pdf (40 pages, 2159400 bytes). +Transcript written on main.log. +Latexmk: Getting log file 'main.log' +Latexmk: Examining 'main.fls' +Latexmk: Examining 'main.log' +Latexmk: Found input bbl file 'main.bbl' +Latexmk: Log file says output to 'main.pdf' +Latexmk: Using bibtex to make bibliography file(s). + ===Source file 'main.bbl' for 'lualatex' +Latexmk: Found bibliography file(s): + ./references.bib +Latexmk: Summary of warnings from last run of *latex: + Latex failed to resolve 2 reference(s) +Latexmk: ====Problematic refs and citations with line #s in .tex file: + (pdf backend): unreferenced destination with name 'Hfootnote.2' + (pdf backend): unreferenced destination with name 'Hfootnote.1' +Latexmk: All targets (main.pdf) are up-to-date + diff --git a/latex3.log b/latex3.log new file mode 100644 index 0000000..73e7161 --- /dev/null +++ b/latex3.log @@ -0,0 +1,1267 @@ +Rc files read (in order): + NONE +Latexmk: This is Latexmk, John Collins, 9 March 2026. Version 4.88. +Latexmk: applying rule 'lualatex'... +Rule 'lualatex': Reasons for rerun +Changed files or newly in use/created: + Appendix/a_inference.tex +Category 'changed_user': + Appendix/a_inference.tex + +------------ +Run number 1 of rule 'lualatex' +------------ +------------ +Running 'lualatex -interaction=nonstopmode -halt-on-error -recorder "main.tex"' +------------ +This is LuaHBTeX, Version 1.24.0 (TeX Live 2026) + restricted system commands enabled. +(./main.tex +LaTeX2e <2025-11-01> +L3 programming layer <2026-01-19> + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/article.cls +Document Class: article 2025/01/22 v1.4n Standard LaTeX document class +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/size12.clo)) +(./YGTemplate.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3kernel/expl3.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3backend/l3backend-luatex.def))) + (/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec-luatex.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/babel.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/locale/en/babel-english.t +ex) (/usr/local/texlive/2026/texmf-dist/tex/generic/babel-english/english.ldf)) + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/lm/t1lmr.fd)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/a4wide/a4wide.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/ntgclass/a4.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/xcolor/xcolor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/color.cfg) + +Package xcolor Warning: Package option `usenames' is obsolete and ignored on in +put line 265. + +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-def/luatex.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/mathcolor.ltx)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/dvipsnam.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphicx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/keyval.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphics.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/trig.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/graphics.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/tabularx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/array.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.sty +**************************************** +* Local config file subfigure.cfg used * +**************************************** +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/float/float.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption3.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/subcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fnpct/fnpct.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/etoolbox/etoolbox.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/infwarerr/infwarerr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/iftex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty)))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts/kpfonts.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/kpfonts-otf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/realscripts/realscripts.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpRoman.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpLight.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpSans.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMono.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-luatex. +sty (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fix-cm.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ts1enc.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsmath.sty +For additional information on amsmath, use the `?' option. +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amstext.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsgen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsbsy.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsopn.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/lualatex/lualatex-math/lualatex-math.st +y) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-table.t +ex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMath-Regular.fontsp +ec))) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/pgf.revision.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeyslibraryfil +tered.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-luatex.d +ef +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-p +df.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol. +code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigo +nometric.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.rando +m.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.compa +rison.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integ +erarithmetics.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfint.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconst +ruct.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicst +ate.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransform +ations.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathproce +ssing.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretranspare +ncy.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code. +tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-0-65.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-1-18.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/math/pgfmath.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex)) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.cod +e.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothan +dlers.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarytopaths.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplots.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgfplotssysgeneric +.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgfplotslibrary.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_loader.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryfpu.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_pgfutil-common-lists.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/luamath/pgflibrar +yluamath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code +.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructure.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructureext.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +array.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +matrix.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +shared.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +deque.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.co +de.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.da +ta.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.verb +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgflibrarypgfplot +s.surfshading.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgflibrarypgfplots +.surfshading.pgfsys-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolormap. +code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolor.cod +e.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.c +ode.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplothandle +r.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplotimage. +code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscoordprocessin +g.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.errorbars.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.markers.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.paths.code.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduledecoration +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathmorphing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathmorphing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathreplacing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathreplacing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.contourlua.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryplotmarks.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplotmar +ks.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplotstable.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.coltype.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesome.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifxetex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifluatex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-ge +neric.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-xe +luatex.tex)) (/usr/local/texlive/2026/texmf-dist/tex/latex/psfrag/psfrag.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryintersections.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryinterse +ctions.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypatterns.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibrarypattern +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +decorations.softclip.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryf +illbetween.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.decorations.softclip.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/booktabs/booktabs.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/bm.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/rotating.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ifthen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hyperref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdfescape/pdfescape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hycolor/hycolor.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/nameref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/refcount/refcount.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/gettitlestring/gettitlestring.s +ty (/usr/local/texlive/2026/texmf-dist/tex/latex/kvoptions/kvoptions.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/stringenc/stringenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/pd1enc.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/intcalc/intcalc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/puenc.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/url/url.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/bitset/bitset.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hluatex.def +(/usr/local/texlive/2026/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty + +(/usr/local/texlive/2026/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +))) (/usr/local/texlive/2026/texmf-dist/tex/latex/todonotes/todonotes.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/xkeyval/xkeyval.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkeyval.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkvutils.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypositioning.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/calc.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/natbib/natbib.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/paralist/paralist.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/multicol.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/longtable.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/multirow/multirow.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/lscape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/chngcntr/chngcntr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/footmisc/footmisc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fmtcount.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcprefix.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcnumparser.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fc-english.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime-defaults.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/threeparttable/threeparttable.sty +) (/usr/local/texlive/2026/texmf-dist/tex/latex/diagbox/diagbox.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/p2e-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/sectsty/sectsty.sty + +LaTeX Warning: Command \underbar has changed. + Check if current package is valid. + + +LaTeX Warning: Command \underline has changed. + Check if current package is valid. + +)) (./title_metadata.tex) (./main.aux) +(/usr/local/texlive/2026/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +) (/usr/local/texlive/2026/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/ltcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations-basic-d +ictionary-english.trsl) + +Package pgfplots Warning: running in backwards compatibility mode (unsuitable t +ick labels; missing features). Consider writing \pgfplotsset{compat=1.18} into +your preamble. + on input line 12. + +(./main.out) (./main.out) + +Package todonotes Warning: The length marginparwidth is less than 2cm and will +most likely cause issues with the appearance of inserted todonotes. The issue c +an be solved by adding a line like \setlength {\marginparwidth }{2cm} prior to +loading the todonotes package. on input line 12. + +(./frontmatter.tex +Overfull \hbox (8.09319pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 registration-threshold re-forms, re-leased with its sy +nthetic-data gen-er-a-tor. The thresh- + +Overfull \hbox (8.50201pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/it/10.95 shape \TU/KpRoman(1)/m/n/10.95 (a ta-per) and \TU/KpR +oman(1)/m/it/10.95 rate \TU/KpRoman(1)/m/n/10.95 (a reduced-rate band) re-forms + stat-i-cally on a com-mon £184.8bn + +Overfull \hbox (45.11325pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 base: rais-ing the thresh-old to £100,000 costs £784 +m, a grad-u-ated ta-per over £85,000--£105,000 +[1 +Non-PDF special ignored!{/usr/local/texlive/2026/texmf-var/fonts/map/pdftex/upd +map/pdftex.map}] [2]) (./body.tex (./Sections/intro.tex [3<./figures/firms_by_t +urnover_band_85k.png><./figures/vat_firms_by_turnover_band_85k.png>] [4] +Overfull \hbox (0.9187pt too wide) in paragraph at lines 49--50 +[]\TU/KpRoman(1)/m/n/12 Third, con-di-tional on the as-sumed elas-tic-ity, inte +nsive-margin re-sponses barely move + +Overfull \hbox (13.0106pt too wide) in paragraph at lines 51--52 +\TU/KpRoman(1)/m/n/12 pa-per demon-strates the point in three di-rec-tions. The + 2023--24 pop-u-la-tion’s near-threshold +[5] [6]) (./Sections/background.tex [7]) (./Sections/data.tex [8<./figures/obr_ +vat_bunching_85k.png>] +Overfull \hbox (0.61864pt too wide) in paragraph at lines 4--16 +\TU/KpRoman(1)/m/n/12 Study-ing firm re-sponses at the thresh-old needs firm-le +vel turnover near the cut-off, which +[9] +Overfull \hbox (0.3166pt too wide) in paragraph at lines 60--64 +[]\TU/KpRoman(1)/m/n/12 The base pop-u-la-tion re-pro-duces the ONS struc-ture +but not the HMRC VAT-registered + +Overfull \hbox (23.08046pt too wide) in paragraph at lines 75--110 +\TU/KpRoman(1)/m/n/12 Chart C data give HMRC counts of busi-nesses by £1,000 t +urnover band over £65,000--£90,000 +[10] +Overfull \hbox (14.26959pt too wide) in paragraph at lines 137--163 +\TU/KpRoman(1)/m/n/12 statu-tory thresh-old was £85,000. The HMRC band tar-get +s step down across the threshold--- + +Overfull \hbox (21.09047pt too wide) in paragraph at lines 137--163 +\TU/KpRoman(1)/m/n/12 brated den-sity rises into the thresh-old (about $\TU/KpM +ath-Regular.otf(1)/m/n/12 13[]800$ \TU/KpRoman(1)/m/n/12 firms per £1,000 in t +he £84,000--£85,000 +[11]) (./Sections/static.tex [12<./figures/turnover_distribution_85k.png>] +[13] [14<./figures/vat_threshold_revenue_impact.png>] +Overfull \hbox (13.10669pt too wide) in paragraph at lines 168--182 +\TU/KpRoman(1)/m/n/12 The thresh-old sweep above moves the \TU/KpRoman(1)/m/it/ +12 lo-ca-tion \TU/KpRoman(1)/m/n/12 of a sin-gle cut-off. The same static princ +iple--- +[15] [16<./figures/revenue_impact_2025_26.png><./figures/firms_impact_2025_26.p +ng>]) (./Sections/bunching.tex +Overfull \hbox (6.67659pt too wide) in paragraph at lines 4--22 +\TU/KpRoman(1)/m/n/12 ([][]2011[][]) and [][]Kleven and Waseem[][] ([][]2013[][ +])---as ap-plied to UK VAT data by [][]Liu et al.[][] ([][]2021[][])---to +[17] [18] +Overfull \hbox (25.36118pt too wide) in paragraph at lines 72--83 +\TU/KpRoman(1)/m/n/12 the ap-prox-i-ma-tion hold-ing when $\TU/KpMath-Regular.o +tf(1)/m/n/12 𝑔$ \TU/KpRoman(1)/m/n/12 is lo-cally smooth. The bunch-ing ra-t +io $\TU/KpMath-Regular.otf(1)/m/n/12 𝑏(𝑦[]) = 𝐵(𝑦[])/𝑔(𝑦[]) +≈ + +Overfull \hbox (9.11465pt too wide) in paragraph at lines 86--100 +\TU/KpRoman(1)/m/n/12 behaviour---the gen-er-a-tor con-tains no firm location-c +hoice---and the placebo be-low proves +[19] [20<./figures/bunching_analysis_85k.png><./figures/bunching_analysis_90k.p +ng>] [21]) (./Sections/model.tex [22] +Overfull \hbox (9.26462pt too wide) in paragraph at lines 22--29 +\TU/KpRoman(1)/m/n/12 Two pop-u-la-tions are out-side its scope and are treated + as such through-out: below-threshold +[23]) (./Sections/behavioural.tex +Overfull \hbox (8.2552pt too wide) in paragraph at lines 139--1 +\TU/KpMath-Regular.otf(1)/m/n/12 (𝜏 − 𝑟) 𝑇[] = £5[]250$\TU/KpRoman( +1)/m/n/12 . The firm counts con-firm this (\TU/KpMono(0)/m/n/12 results/dominat +ed_region_mass.txt\TU/KpRoman(1)/m/n/12 ): +[24] [25<./figures/dynamic_notch_fit_e017.png>] [26] +Overfull \hbox (0.45064pt too wide) in paragraph at lines 76--83 +\TU/KpRoman(1)/m/n/12 firm’s op-ti-mal turnover un-der a coun-ter-fac-tual sc +hed-ule, \TU/KpRoman(1)/m/it/12 given \TU/KpRoman(1)/m/n/12 that its ob-served +turnover +[27<./figures/formulation_a_optima.png>] +Overfull \hbox (2.70668pt too wide) in paragraph at lines 87--96 +\TU/KpRoman(1)/m/n/12 The in-ten-sive re-sponse de-pends only on $\TU/KpMath-Re +gular.otf(1)/m/n/12 𝑒$\TU/KpRoman(1)/m/n/12 , the statu-tory rate, and the s +ched-ule fractions--- + +Overfull \hbox (19.06874pt too wide) in paragraph at lines 97--117 +[]\TU/KpRoman(1)/b/n/12 Region-confined scope.[] \TU/KpRoman(1)/m/n/12 The mar- +gin priced here is purely \TU/KpRoman(1)/m/it/12 in-ten-sive\TU/KpRoman(1)/m/n/ +12 : each firm re-optimises + +Overfull \hbox (1.25473pt too wide) in paragraph at lines 118--129 +[]\TU/KpRoman(1)/b/n/12 Con-di-tional on $\TU/KpMath-Regular.otf(1)/m/n/12 +𝑒$\TU/KpRoman(1)/b/n/12 .[] \TU/KpRoman(1)/m/n/12 The elas-tic-ity $\TU/KpMa +th-Regular.otf(1)/m/n/12 𝑒$ \TU/KpRoman(1)/m/n/12 is not iden-ti-fied from t +hese data, so ev-ery be-havioural + +Overfull \hbox (34.0586pt too wide) in paragraph at lines 154--166 + [][] +[28] [29]) (./Sections/conclusion.tex +Overfull \hbox (20.66867pt too wide) in paragraph at lines 4--13 +\TU/KpRoman(1)/m/n/12 the UK VAT reg-is-tra-tion thresh-old, re-leased in full- +--including its synthetic-data generator--- +[30<./figures/dynamic_cost_vs_elasticity.png>] +Overfull \hbox (68.06161pt too wide) in paragraph at lines 23--35 + [][] +[31]) [32] [33] (./main.bbl +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +[]\TU/KpRoman(1)/m/n/10.95 HM Rev-enue and Cus-toms (2024) ``In-creas-ing the V +AT Reg-is-tra-tion Thresh-old,'' + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpRoman(1)/m/n/10.95 Tax in-for-ma-tion and im-pact note, GOV.UK, [][]$\TU/ +KpMono(0)/m/n/10.95 https://www.gov.uk/government/ + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpMono(0)/m/n/10.95 publications/vat-[]increasing-[]the-[]registration-[]an +d-[]deregistration-[]thresholds/ +[34] +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +[]\TU/KpRoman(1)/m/n/10.95 HM Trea-sury (2018) ``VAT Reg-is-tra-tion Thresh-old +: Call for Ev-i-dence,'' HM + +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +\TU/KpRoman(1)/m/n/10.95 Trea-sury, March 2018, [][]$\TU/KpMono(0)/m/n/10.95 ht +tps://www.gov.uk/government/consultations/ + +Underfull \hbox (badness 7869) in paragraph at lines 106--109 +[] [] \TU/KpRoman(1)/m/n/10.95 (2024) ``Spring Bud-get 2024: Pol-icy Cost-ings, +'' HM Trea-sury, March 2024, + +Underfull \hbox (badness 10000) in paragraph at lines 106--109 +[][]$\TU/KpMono(0)/m/n/10.95 https://assets.publishing.service.gov.uk/media/65e +7920c08eef600155a5617/ + +Underfull \hbox (badness 4886) in paragraph at lines 133--137 +[]\TU/KpRoman(1)/m/n/10.95 Liu, Li, Ben Lock-wood, and Eddy H. F. Tam (2024) `` +Small Firm Growth and the + +Underfull \hbox (badness 2865) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 VAT Thresh-old: Ev-i-dence for the UK,'' IMF Work-ing +Pa-perWP/24/33, In-ter-na-tional + +Underfull \hbox (badness 10000) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 Mon-e-tary Fund, [][]$\TU/KpMono(0)/m/n/10.95 https:// +www.imf.org/en/publications/wp/issues/2024/02/16/ + +Underfull \hbox (badness 1490) in paragraph at lines 139--143 +\TU/KpRoman(1)/m/n/10.95 West Ben-gal, In-dia,'' TaxDev / In-sti-tute for Fis-c +al Stud-ies, [][]$\TU/KpMono(0)/m/n/10.95 https://www.taxdev.org/ + +Underfull \hbox (badness 10000) in paragraph at lines 146--149 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice for Bud-get Re-spon-si-bil-ity (2023) ``The +Im-pact of the Frozen VAT Reg-is-tra- + +Underfull \hbox (badness 4886) in paragraph at lines 146--149 +\TU/KpRoman(1)/m/n/10.95 tion Thresh-old,'' Eco-nomic and Fis-cal Out-look, Mar +ch 2023, [][]$\TU/KpMono(0)/m/n/10.95 https://obr.uk/box/ + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice of Tax Sim-pli-fi-ca-tion (2017) ``Value Add +ed Tax: Routes to Sim-pli-fi-ca-tion,'' + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +\TU/KpRoman(1)/m/n/10.95 OTS re-port, Novem-ber 2017, [][]$\TU/KpMono(0)/m/n/10 +.95 https://assets.publishing.service.gov.uk/media/ +[35]) [36] (./Appendix/appendix.tex (./Appendix/a_data.tex +Overfull \hbox (11.12668pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion check rather than a silent re-place-ment. The snap-s +hot used here is Pol-i-cyEngine/ledger + +Overfull \hbox (30.38661pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 and max-i-mum nu-meric dif-fer-ence zero. (The ``2024--25 + vin-tage'' here de-notes the HMRC/ONS + +Overfull \hbox (3.00157pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion cal-i-brates to.) A 1,000-iteration Pop-u-lace run f +rom those tar-gets gen-er-ated 2,946,015 + +Overfull \hbox (79.53078pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 into \TU/KpMono(0)/m/n/12 results/populace_ledger_compari +son.txt \TU/KpRoman(1)/m/n/12 and \TU/KpMono(0)/m/n/12 results/populace_ledger_ +provenance.json\TU/KpRoman(1)/m/n/12 . +[37]) (./Appendix/a_inference.tex +Overfull \hbox (103.32681pt too wide) in paragraph at lines 4--26 +\TU/KpMono(0)/m/n/12 results/bunching_inference.txt\TU/KpRoman(1)/m/n/12 , \TU/ +KpMono(0)/m/n/12 results/placebo_bunching.txt\TU/KpRoman(1)/m/n/12 , \TU/KpMono +(0)/m/n/12 results/recovery_bunching.txt +[38] [39] +Underfull \hbox (badness 1845) in paragraph at lines 159--159 +[][]\TU/KpRoman(1)/b/n/12 Ta-ble A.3[][]: []|\TU/KpRoman(1)/m/n/12 Power (re-co +v-ery) test on the step-free pop-u-la-tion: Kleven--Waseem- +[40]))) [41] (./main.aux) + +LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right. + +) +(see the transcript file for additional information) + 1318 words of node memory still in use: + 6 hlist, 2 vlist, 2 rule, 14 glue, 4 kern, 1 glyph, 163 attribute, 77 glue_s +pec, 82 attribute_list, 2 write, 26 pdf_action nodes + avail lists: 1:1,2:958,3:445,4:211,5:756,6:33,7:10104,8:146,9:374,10:28,11:7 +17 + +warning (pdf backend): unreferenced destination with name 'Hfootnote.2' + +warning (pdf backend): unreferenced destination with name 'Hfootnote.1' + + +Output written on main.pdf (41 pages, 2158644 bytes). +Transcript written on main.log. +Latexmk: Getting log file 'main.log' +Latexmk: Examining 'main.fls' +Latexmk: Examining 'main.log' +Latexmk: Found input bbl file 'main.bbl' +Latexmk: References changed. +Latexmk: References changed. +Latexmk: Log file says output to 'main.pdf' +Latexmk: Using bibtex to make bibliography file(s). + ===Source file 'main.bbl' for 'lualatex' +Latexmk: Found bibliography file(s): + ./references.bib +Latexmk: applying rule 'bibtex main'... +Rule 'bibtex main': Reasons for rerun +Changed files or newly in use/created: + main.aux + +------------ +Run number 1 of rule 'bibtex main' +------------ +------------ +Running 'bibtex "main.aux"' +------------ +This is BibTeX, Version 0.99e (TeX Live 2026) +The top-level auxiliary file: main.aux +The style file: econ.bst +Database file #1: references.bib +Latexmk: applying rule 'lualatex'... +Rule 'lualatex': Reasons for rerun +Changed files or newly in use/created: + main.aux + +------------ +Run number 2 of rule 'lualatex' +------------ +------------ +Running 'lualatex -interaction=nonstopmode -halt-on-error -recorder "main.tex"' +------------ +This is LuaHBTeX, Version 1.24.0 (TeX Live 2026) + restricted system commands enabled. +(./main.tex +LaTeX2e <2025-11-01> +L3 programming layer <2026-01-19> + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/article.cls +Document Class: article 2025/01/22 v1.4n Standard LaTeX document class +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/size12.clo)) +(./YGTemplate.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3kernel/expl3.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3backend/l3backend-luatex.def))) + (/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec-luatex.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/babel.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/locale/en/babel-english.t +ex) (/usr/local/texlive/2026/texmf-dist/tex/generic/babel-english/english.ldf)) + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/lm/t1lmr.fd)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/a4wide/a4wide.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/ntgclass/a4.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/xcolor/xcolor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/color.cfg) + +Package xcolor Warning: Package option `usenames' is obsolete and ignored on in +put line 265. + +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-def/luatex.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/mathcolor.ltx)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/dvipsnam.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphicx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/keyval.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphics.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/trig.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/graphics.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/tabularx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/array.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.sty +**************************************** +* Local config file subfigure.cfg used * +**************************************** +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/float/float.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption3.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/subcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fnpct/fnpct.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/etoolbox/etoolbox.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/infwarerr/infwarerr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/iftex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty)))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts/kpfonts.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/kpfonts-otf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/realscripts/realscripts.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpRoman.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpLight.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpSans.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMono.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-luatex. +sty (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fix-cm.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ts1enc.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsmath.sty +For additional information on amsmath, use the `?' option. +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amstext.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsgen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsbsy.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsopn.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/lualatex/lualatex-math/lualatex-math.st +y) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-table.t +ex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMath-Regular.fontsp +ec))) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/pgf.revision.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeyslibraryfil +tered.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-luatex.d +ef +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-p +df.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol. +code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigo +nometric.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.rando +m.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.compa +rison.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integ +erarithmetics.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfint.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconst +ruct.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicst +ate.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransform +ations.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathproce +ssing.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretranspare +ncy.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code. +tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-0-65.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-1-18.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/math/pgfmath.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex)) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.cod +e.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothan +dlers.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarytopaths.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplots.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgfplotssysgeneric +.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgfplotslibrary.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_loader.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryfpu.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_pgfutil-common-lists.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/luamath/pgflibrar +yluamath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code +.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructure.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructureext.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +array.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +matrix.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +shared.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +deque.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.co +de.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.da +ta.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.verb +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgflibrarypgfplot +s.surfshading.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgflibrarypgfplots +.surfshading.pgfsys-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolormap. +code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolor.cod +e.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.c +ode.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplothandle +r.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplotimage. +code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscoordprocessin +g.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.errorbars.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.markers.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.paths.code.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduledecoration +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathmorphing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathmorphing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathreplacing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathreplacing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.contourlua.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryplotmarks.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplotmar +ks.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplotstable.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.coltype.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesome.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifxetex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifluatex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-ge +neric.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-xe +luatex.tex)) (/usr/local/texlive/2026/texmf-dist/tex/latex/psfrag/psfrag.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryintersections.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryinterse +ctions.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypatterns.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibrarypattern +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +decorations.softclip.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryf +illbetween.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.decorations.softclip.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/booktabs/booktabs.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/bm.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/rotating.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ifthen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hyperref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdfescape/pdfescape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hycolor/hycolor.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/nameref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/refcount/refcount.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/gettitlestring/gettitlestring.s +ty (/usr/local/texlive/2026/texmf-dist/tex/latex/kvoptions/kvoptions.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/stringenc/stringenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/pd1enc.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/intcalc/intcalc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/puenc.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/url/url.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/bitset/bitset.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hluatex.def +(/usr/local/texlive/2026/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty + +(/usr/local/texlive/2026/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +))) (/usr/local/texlive/2026/texmf-dist/tex/latex/todonotes/todonotes.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/xkeyval/xkeyval.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkeyval.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkvutils.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypositioning.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/calc.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/natbib/natbib.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/paralist/paralist.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/multicol.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/longtable.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/multirow/multirow.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/lscape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/chngcntr/chngcntr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/footmisc/footmisc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fmtcount.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcprefix.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcnumparser.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fc-english.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime-defaults.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/threeparttable/threeparttable.sty +) (/usr/local/texlive/2026/texmf-dist/tex/latex/diagbox/diagbox.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/p2e-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/sectsty/sectsty.sty + +LaTeX Warning: Command \underbar has changed. + Check if current package is valid. + + +LaTeX Warning: Command \underline has changed. + Check if current package is valid. + +)) (./title_metadata.tex) (./main.aux) +(/usr/local/texlive/2026/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +) (/usr/local/texlive/2026/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/ltcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations-basic-d +ictionary-english.trsl) + +Package pgfplots Warning: running in backwards compatibility mode (unsuitable t +ick labels; missing features). Consider writing \pgfplotsset{compat=1.18} into +your preamble. + on input line 12. + +(./main.out) (./main.out) + +Package todonotes Warning: The length marginparwidth is less than 2cm and will +most likely cause issues with the appearance of inserted todonotes. The issue c +an be solved by adding a line like \setlength {\marginparwidth }{2cm} prior to +loading the todonotes package. on input line 12. + +(./frontmatter.tex +Overfull \hbox (8.09319pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 registration-threshold re-forms, re-leased with its sy +nthetic-data gen-er-a-tor. The thresh- + +Overfull \hbox (8.50201pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/it/10.95 shape \TU/KpRoman(1)/m/n/10.95 (a ta-per) and \TU/KpR +oman(1)/m/it/10.95 rate \TU/KpRoman(1)/m/n/10.95 (a reduced-rate band) re-forms + stat-i-cally on a com-mon £184.8bn + +Overfull \hbox (45.11325pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 base: rais-ing the thresh-old to £100,000 costs £784 +m, a grad-u-ated ta-per over £85,000--£105,000 +[1 +Non-PDF special ignored!{/usr/local/texlive/2026/texmf-var/fonts/map/pdftex/upd +map/pdftex.map}] [2]) (./body.tex (./Sections/intro.tex [3<./figures/firms_by_t +urnover_band_85k.png><./figures/vat_firms_by_turnover_band_85k.png>] [4] +Overfull \hbox (0.9187pt too wide) in paragraph at lines 49--50 +[]\TU/KpRoman(1)/m/n/12 Third, con-di-tional on the as-sumed elas-tic-ity, inte +nsive-margin re-sponses barely move + +Overfull \hbox (13.0106pt too wide) in paragraph at lines 51--52 +\TU/KpRoman(1)/m/n/12 pa-per demon-strates the point in three di-rec-tions. The + 2023--24 pop-u-la-tion’s near-threshold +[5] [6]) (./Sections/background.tex [7]) (./Sections/data.tex [8<./figures/obr_ +vat_bunching_85k.png>] +Overfull \hbox (0.61864pt too wide) in paragraph at lines 4--16 +\TU/KpRoman(1)/m/n/12 Study-ing firm re-sponses at the thresh-old needs firm-le +vel turnover near the cut-off, which +[9] +Overfull \hbox (0.3166pt too wide) in paragraph at lines 60--64 +[]\TU/KpRoman(1)/m/n/12 The base pop-u-la-tion re-pro-duces the ONS struc-ture +but not the HMRC VAT-registered + +Overfull \hbox (23.08046pt too wide) in paragraph at lines 75--110 +\TU/KpRoman(1)/m/n/12 Chart C data give HMRC counts of busi-nesses by £1,000 t +urnover band over £65,000--£90,000 +[10] +Overfull \hbox (14.26959pt too wide) in paragraph at lines 137--163 +\TU/KpRoman(1)/m/n/12 statu-tory thresh-old was £85,000. The HMRC band tar-get +s step down across the threshold--- + +Overfull \hbox (21.09047pt too wide) in paragraph at lines 137--163 +\TU/KpRoman(1)/m/n/12 brated den-sity rises into the thresh-old (about $\TU/KpM +ath-Regular.otf(1)/m/n/12 13[]800$ \TU/KpRoman(1)/m/n/12 firms per £1,000 in t +he £84,000--£85,000 +[11]) (./Sections/static.tex [12<./figures/turnover_distribution_85k.png>] +[13] [14<./figures/vat_threshold_revenue_impact.png>] +Overfull \hbox (13.10669pt too wide) in paragraph at lines 168--182 +\TU/KpRoman(1)/m/n/12 The thresh-old sweep above moves the \TU/KpRoman(1)/m/it/ +12 lo-ca-tion \TU/KpRoman(1)/m/n/12 of a sin-gle cut-off. The same static princ +iple--- +[15] [16<./figures/revenue_impact_2025_26.png><./figures/firms_impact_2025_26.p +ng>]) (./Sections/bunching.tex +Overfull \hbox (6.67659pt too wide) in paragraph at lines 4--22 +\TU/KpRoman(1)/m/n/12 ([][]2011[][]) and [][]Kleven and Waseem[][] ([][]2013[][ +])---as ap-plied to UK VAT data by [][]Liu et al.[][] ([][]2021[][])---to +[17] [18] +Overfull \hbox (25.36118pt too wide) in paragraph at lines 72--83 +\TU/KpRoman(1)/m/n/12 the ap-prox-i-ma-tion hold-ing when $\TU/KpMath-Regular.o +tf(1)/m/n/12 𝑔$ \TU/KpRoman(1)/m/n/12 is lo-cally smooth. The bunch-ing ra-t +io $\TU/KpMath-Regular.otf(1)/m/n/12 𝑏(𝑦[]) = 𝐵(𝑦[])/𝑔(𝑦[]) +≈ + +Overfull \hbox (9.11465pt too wide) in paragraph at lines 86--100 +\TU/KpRoman(1)/m/n/12 behaviour---the gen-er-a-tor con-tains no firm location-c +hoice---and the placebo be-low proves +[19] [20<./figures/bunching_analysis_85k.png><./figures/bunching_analysis_90k.p +ng>] [21]) (./Sections/model.tex [22] +Overfull \hbox (9.26462pt too wide) in paragraph at lines 22--29 +\TU/KpRoman(1)/m/n/12 Two pop-u-la-tions are out-side its scope and are treated + as such through-out: below-threshold +[23]) (./Sections/behavioural.tex +Overfull \hbox (8.2552pt too wide) in paragraph at lines 139--1 +\TU/KpMath-Regular.otf(1)/m/n/12 (𝜏 − 𝑟) 𝑇[] = £5[]250$\TU/KpRoman( +1)/m/n/12 . The firm counts con-firm this (\TU/KpMono(0)/m/n/12 results/dominat +ed_region_mass.txt\TU/KpRoman(1)/m/n/12 ): +[24] [25<./figures/dynamic_notch_fit_e017.png>] [26] +Overfull \hbox (0.45064pt too wide) in paragraph at lines 76--83 +\TU/KpRoman(1)/m/n/12 firm’s op-ti-mal turnover un-der a coun-ter-fac-tual sc +hed-ule, \TU/KpRoman(1)/m/it/12 given \TU/KpRoman(1)/m/n/12 that its ob-served +turnover +[27<./figures/formulation_a_optima.png>] +Overfull \hbox (2.70668pt too wide) in paragraph at lines 87--96 +\TU/KpRoman(1)/m/n/12 The in-ten-sive re-sponse de-pends only on $\TU/KpMath-Re +gular.otf(1)/m/n/12 𝑒$\TU/KpRoman(1)/m/n/12 , the statu-tory rate, and the s +ched-ule fractions--- + +Overfull \hbox (19.06874pt too wide) in paragraph at lines 97--117 +[]\TU/KpRoman(1)/b/n/12 Region-confined scope.[] \TU/KpRoman(1)/m/n/12 The mar- +gin priced here is purely \TU/KpRoman(1)/m/it/12 in-ten-sive\TU/KpRoman(1)/m/n/ +12 : each firm re-optimises + +Overfull \hbox (1.25473pt too wide) in paragraph at lines 118--129 +[]\TU/KpRoman(1)/b/n/12 Con-di-tional on $\TU/KpMath-Regular.otf(1)/m/n/12 +𝑒$\TU/KpRoman(1)/b/n/12 .[] \TU/KpRoman(1)/m/n/12 The elas-tic-ity $\TU/KpMa +th-Regular.otf(1)/m/n/12 𝑒$ \TU/KpRoman(1)/m/n/12 is not iden-ti-fied from t +hese data, so ev-ery be-havioural + +Overfull \hbox (34.0586pt too wide) in paragraph at lines 154--166 + [][] +[28] [29]) (./Sections/conclusion.tex +Overfull \hbox (20.66867pt too wide) in paragraph at lines 4--13 +\TU/KpRoman(1)/m/n/12 the UK VAT reg-is-tra-tion thresh-old, re-leased in full- +--including its synthetic-data generator--- +[30<./figures/dynamic_cost_vs_elasticity.png>] +Overfull \hbox (68.06161pt too wide) in paragraph at lines 23--35 + [][] +[31]) [32] [33] (./main.bbl +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +[]\TU/KpRoman(1)/m/n/10.95 HM Rev-enue and Cus-toms (2024) ``In-creas-ing the V +AT Reg-is-tra-tion Thresh-old,'' + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpRoman(1)/m/n/10.95 Tax in-for-ma-tion and im-pact note, GOV.UK, [][]$\TU/ +KpMono(0)/m/n/10.95 https://www.gov.uk/government/ + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpMono(0)/m/n/10.95 publications/vat-[]increasing-[]the-[]registration-[]an +d-[]deregistration-[]thresholds/ +[34] +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +[]\TU/KpRoman(1)/m/n/10.95 HM Trea-sury (2018) ``VAT Reg-is-tra-tion Thresh-old +: Call for Ev-i-dence,'' HM + +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +\TU/KpRoman(1)/m/n/10.95 Trea-sury, March 2018, [][]$\TU/KpMono(0)/m/n/10.95 ht +tps://www.gov.uk/government/consultations/ + +Underfull \hbox (badness 7869) in paragraph at lines 106--109 +[] [] \TU/KpRoman(1)/m/n/10.95 (2024) ``Spring Bud-get 2024: Pol-icy Cost-ings, +'' HM Trea-sury, March 2024, + +Underfull \hbox (badness 10000) in paragraph at lines 106--109 +[][]$\TU/KpMono(0)/m/n/10.95 https://assets.publishing.service.gov.uk/media/65e +7920c08eef600155a5617/ + +Underfull \hbox (badness 4886) in paragraph at lines 133--137 +[]\TU/KpRoman(1)/m/n/10.95 Liu, Li, Ben Lock-wood, and Eddy H. F. Tam (2024) `` +Small Firm Growth and the + +Underfull \hbox (badness 2865) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 VAT Thresh-old: Ev-i-dence for the UK,'' IMF Work-ing +Pa-perWP/24/33, In-ter-na-tional + +Underfull \hbox (badness 10000) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 Mon-e-tary Fund, [][]$\TU/KpMono(0)/m/n/10.95 https:// +www.imf.org/en/publications/wp/issues/2024/02/16/ + +Underfull \hbox (badness 1490) in paragraph at lines 139--143 +\TU/KpRoman(1)/m/n/10.95 West Ben-gal, In-dia,'' TaxDev / In-sti-tute for Fis-c +al Stud-ies, [][]$\TU/KpMono(0)/m/n/10.95 https://www.taxdev.org/ + +Underfull \hbox (badness 10000) in paragraph at lines 146--149 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice for Bud-get Re-spon-si-bil-ity (2023) ``The +Im-pact of the Frozen VAT Reg-is-tra- + +Underfull \hbox (badness 4886) in paragraph at lines 146--149 +\TU/KpRoman(1)/m/n/10.95 tion Thresh-old,'' Eco-nomic and Fis-cal Out-look, Mar +ch 2023, [][]$\TU/KpMono(0)/m/n/10.95 https://obr.uk/box/ + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice of Tax Sim-pli-fi-ca-tion (2017) ``Value Add +ed Tax: Routes to Sim-pli-fi-ca-tion,'' + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +\TU/KpRoman(1)/m/n/10.95 OTS re-port, Novem-ber 2017, [][]$\TU/KpMono(0)/m/n/10 +.95 https://assets.publishing.service.gov.uk/media/ +[35]) [36] (./Appendix/appendix.tex (./Appendix/a_data.tex +Overfull \hbox (11.12668pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion check rather than a silent re-place-ment. The snap-s +hot used here is Pol-i-cyEngine/ledger + +Overfull \hbox (30.38661pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 and max-i-mum nu-meric dif-fer-ence zero. (The ``2024--25 + vin-tage'' here de-notes the HMRC/ONS + +Overfull \hbox (3.00157pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion cal-i-brates to.) A 1,000-iteration Pop-u-lace run f +rom those tar-gets gen-er-ated 2,946,015 + +Overfull \hbox (79.53078pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 into \TU/KpMono(0)/m/n/12 results/populace_ledger_compari +son.txt \TU/KpRoman(1)/m/n/12 and \TU/KpMono(0)/m/n/12 results/populace_ledger_ +provenance.json\TU/KpRoman(1)/m/n/12 . +[37]) (./Appendix/a_inference.tex +Overfull \hbox (103.32681pt too wide) in paragraph at lines 4--26 +\TU/KpMono(0)/m/n/12 results/bunching_inference.txt\TU/KpRoman(1)/m/n/12 , \TU/ +KpMono(0)/m/n/12 results/placebo_bunching.txt\TU/KpRoman(1)/m/n/12 , \TU/KpMono +(0)/m/n/12 results/recovery_bunching.txt +[38] [39] +Underfull \hbox (badness 1845) in paragraph at lines 159--159 +[][]\TU/KpRoman(1)/b/n/12 Ta-ble A.3[][]: []|\TU/KpRoman(1)/m/n/12 Power (re-co +v-ery) test on the step-free pop-u-la-tion: Kleven--Waseem- +[40]))) [41] (./main.aux)) +(see the transcript file for additional information) + 1318 words of node memory still in use: + 6 hlist, 2 vlist, 2 rule, 14 glue, 4 kern, 1 glyph, 163 attribute, 77 glue_s +pec, 82 attribute_list, 2 write, 26 pdf_action nodes + avail lists: 1:1,2:958,3:445,4:211,5:756,6:33,7:10104,8:146,9:374,10:28,11:7 +17 + +warning (pdf backend): unreferenced destination with name 'Hfootnote.2' + +warning (pdf backend): unreferenced destination with name 'Hfootnote.1' + + +Output written on main.pdf (41 pages, 2158644 bytes). +Transcript written on main.log. +Latexmk: Getting log file 'main.log' +Latexmk: Examining 'main.fls' +Latexmk: Examining 'main.log' +Latexmk: Found input bbl file 'main.bbl' +Latexmk: Log file says output to 'main.pdf' +Latexmk: Using bibtex to make bibliography file(s). + ===Source file 'main.bbl' for 'lualatex' +Latexmk: Found bibliography file(s): + ./references.bib +Latexmk: Summary of warnings from last run of *latex: + Latex failed to resolve 2 reference(s) +Latexmk: ====Problematic refs and citations with line #s in .tex file: + (pdf backend): unreferenced destination with name 'Hfootnote.2' + (pdf backend): unreferenced destination with name 'Hfootnote.1' +Latexmk: All targets (main.pdf) are up-to-date + diff --git a/latex4.log b/latex4.log new file mode 100644 index 0000000..309a80e --- /dev/null +++ b/latex4.log @@ -0,0 +1,631 @@ +Rc files read (in order): + NONE +Latexmk: This is Latexmk, John Collins, 9 March 2026. Version 4.88. +Latexmk: applying rule 'lualatex'... +Rule 'lualatex': Reasons for rerun +Changed files or newly in use/created: + Sections/intro.tex + Sections/static.tex +Category 'changed_user': + Sections/intro.tex + Sections/static.tex + +------------ +Run number 1 of rule 'lualatex' +------------ +------------ +Running 'lualatex -interaction=nonstopmode -halt-on-error -recorder "main.tex"' +------------ +This is LuaHBTeX, Version 1.24.0 (TeX Live 2026) + restricted system commands enabled. +(./main.tex +LaTeX2e <2025-11-01> +L3 programming layer <2026-01-19> + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/article.cls +Document Class: article 2025/01/22 v1.4n Standard LaTeX document class +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/size12.clo)) +(./YGTemplate.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3kernel/expl3.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3backend/l3backend-luatex.def))) + (/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec-luatex.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/babel.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/locale/en/babel-english.t +ex) (/usr/local/texlive/2026/texmf-dist/tex/generic/babel-english/english.ldf)) + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/lm/t1lmr.fd)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/a4wide/a4wide.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/ntgclass/a4.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/xcolor/xcolor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/color.cfg) + +Package xcolor Warning: Package option `usenames' is obsolete and ignored on in +put line 265. + +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-def/luatex.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/mathcolor.ltx)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/dvipsnam.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphicx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/keyval.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphics.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/trig.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/graphics.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/tabularx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/array.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.sty +**************************************** +* Local config file subfigure.cfg used * +**************************************** +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/float/float.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption3.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/subcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fnpct/fnpct.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/etoolbox/etoolbox.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/infwarerr/infwarerr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/iftex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty)))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts/kpfonts.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/kpfonts-otf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/realscripts/realscripts.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpRoman.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpLight.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpSans.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMono.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-luatex. +sty (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fix-cm.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ts1enc.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsmath.sty +For additional information on amsmath, use the `?' option. +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amstext.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsgen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsbsy.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsopn.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/lualatex/lualatex-math/lualatex-math.st +y) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-table.t +ex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMath-Regular.fontsp +ec))) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/pgf.revision.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeyslibraryfil +tered.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-luatex.d +ef +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-p +df.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol. +code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigo +nometric.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.rando +m.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.compa +rison.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integ +erarithmetics.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfint.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconst +ruct.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicst +ate.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransform +ations.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathproce +ssing.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretranspare +ncy.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code. +tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-0-65.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-1-18.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/math/pgfmath.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex)) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.cod +e.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothan +dlers.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarytopaths.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplots.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgfplotssysgeneric +.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgfplotslibrary.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_loader.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryfpu.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_pgfutil-common-lists.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/luamath/pgflibrar +yluamath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code +.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructure.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructureext.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +array.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +matrix.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +shared.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +deque.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.co +de.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.da +ta.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.verb +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgflibrarypgfplot +s.surfshading.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgflibrarypgfplots +.surfshading.pgfsys-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolormap. +code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolor.cod +e.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.c +ode.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplothandle +r.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplotimage. +code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscoordprocessin +g.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.errorbars.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.markers.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.paths.code.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduledecoration +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathmorphing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathmorphing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathreplacing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathreplacing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.contourlua.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryplotmarks.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplotmar +ks.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplotstable.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.coltype.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesome.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifxetex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifluatex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-ge +neric.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-xe +luatex.tex)) (/usr/local/texlive/2026/texmf-dist/tex/latex/psfrag/psfrag.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryintersections.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryinterse +ctions.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypatterns.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibrarypattern +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +decorations.softclip.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryf +illbetween.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.decorations.softclip.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/booktabs/booktabs.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/bm.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/rotating.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ifthen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hyperref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdfescape/pdfescape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hycolor/hycolor.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/nameref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/refcount/refcount.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/gettitlestring/gettitlestring.s +ty (/usr/local/texlive/2026/texmf-dist/tex/latex/kvoptions/kvoptions.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/stringenc/stringenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/pd1enc.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/intcalc/intcalc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/puenc.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/url/url.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/bitset/bitset.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hluatex.def +(/usr/local/texlive/2026/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty + +(/usr/local/texlive/2026/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +))) (/usr/local/texlive/2026/texmf-dist/tex/latex/todonotes/todonotes.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/xkeyval/xkeyval.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkeyval.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkvutils.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypositioning.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/calc.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/natbib/natbib.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/paralist/paralist.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/multicol.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/longtable.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/multirow/multirow.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/lscape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/chngcntr/chngcntr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/footmisc/footmisc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fmtcount.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcprefix.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcnumparser.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fc-english.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime-defaults.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/threeparttable/threeparttable.sty +) (/usr/local/texlive/2026/texmf-dist/tex/latex/diagbox/diagbox.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/p2e-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/sectsty/sectsty.sty + +LaTeX Warning: Command \underbar has changed. + Check if current package is valid. + + +LaTeX Warning: Command \underline has changed. + Check if current package is valid. + +)) (./title_metadata.tex) (./main.aux) +(/usr/local/texlive/2026/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +) (/usr/local/texlive/2026/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/ltcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations-basic-d +ictionary-english.trsl) + +Package pgfplots Warning: running in backwards compatibility mode (unsuitable t +ick labels; missing features). Consider writing \pgfplotsset{compat=1.18} into +your preamble. + on input line 12. + +(./main.out) (./main.out) + +Package todonotes Warning: The length marginparwidth is less than 2cm and will +most likely cause issues with the appearance of inserted todonotes. The issue c +an be solved by adding a line like \setlength {\marginparwidth }{2cm} prior to +loading the todonotes package. on input line 12. + +(./frontmatter.tex +Overfull \hbox (8.09319pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 registration-threshold re-forms, re-leased with its sy +nthetic-data gen-er-a-tor. The thresh- + +Overfull \hbox (8.50201pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/it/10.95 shape \TU/KpRoman(1)/m/n/10.95 (a ta-per) and \TU/KpR +oman(1)/m/it/10.95 rate \TU/KpRoman(1)/m/n/10.95 (a reduced-rate band) re-forms + stat-i-cally on a com-mon £184.8bn + +Overfull \hbox (45.11325pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 base: rais-ing the thresh-old to £100,000 costs £784 +m, a grad-u-ated ta-per over £85,000--£105,000 +[1 +Non-PDF special ignored!{/usr/local/texlive/2026/texmf-var/fonts/map/pdftex/upd +map/pdftex.map}] [2]) (./body.tex (./Sections/intro.tex [3<./figures/firms_by_t +urnover_band_85k.png><./figures/vat_firms_by_turnover_band_85k.png>] [4] +Overfull \hbox (0.9187pt too wide) in paragraph at lines 49--50 +[]\TU/KpRoman(1)/m/n/12 Third, con-di-tional on the as-sumed elas-tic-ity, inte +nsive-margin re-sponses barely move + +Overfull \hbox (13.0106pt too wide) in paragraph at lines 51--52 +\TU/KpRoman(1)/m/n/12 pa-per demon-strates the point in three di-rec-tions. The + 2023--24 pop-u-la-tion’s near-threshold +[5] [6]) (./Sections/background.tex [7]) (./Sections/data.tex [8<./figures/obr_ +vat_bunching_85k.png>] +Overfull \hbox (0.61864pt too wide) in paragraph at lines 4--16 +\TU/KpRoman(1)/m/n/12 Study-ing firm re-sponses at the thresh-old needs firm-le +vel turnover near the cut-off, which +[9] +Overfull \hbox (0.3166pt too wide) in paragraph at lines 60--64 +[]\TU/KpRoman(1)/m/n/12 The base pop-u-la-tion re-pro-duces the ONS struc-ture +but not the HMRC VAT-registered + +Overfull \hbox (23.08046pt too wide) in paragraph at lines 75--110 +\TU/KpRoman(1)/m/n/12 Chart C data give HMRC counts of busi-nesses by £1,000 t +urnover band over £65,000--£90,000 +[10] +Overfull \hbox (14.26959pt too wide) in paragraph at lines 137--163 +\TU/KpRoman(1)/m/n/12 statu-tory thresh-old was £85,000. The HMRC band tar-get +s step down across the threshold--- + +Overfull \hbox (21.09047pt too wide) in paragraph at lines 137--163 +\TU/KpRoman(1)/m/n/12 brated den-sity rises into the thresh-old (about $\TU/KpM +ath-Regular.otf(1)/m/n/12 13[]800$ \TU/KpRoman(1)/m/n/12 firms per £1,000 in t +he £84,000--£85,000 +[11]) (./Sections/static.tex [12<./figures/turnover_distribution_85k.png>] +[13] [14<./figures/vat_threshold_revenue_impact.png>] +Overfull \hbox (13.10669pt too wide) in paragraph at lines 168--182 +\TU/KpRoman(1)/m/n/12 The thresh-old sweep above moves the \TU/KpRoman(1)/m/it/ +12 lo-ca-tion \TU/KpRoman(1)/m/n/12 of a sin-gle cut-off. The same static princ +iple--- +[15] [16<./figures/revenue_impact_2025_26.png><./figures/firms_impact_2025_26.p +ng>]) (./Sections/bunching.tex +Overfull \hbox (6.67659pt too wide) in paragraph at lines 4--22 +\TU/KpRoman(1)/m/n/12 ([][]2011[][]) and [][]Kleven and Waseem[][] ([][]2013[][ +])---as ap-plied to UK VAT data by [][]Liu et al.[][] ([][]2021[][])---to +[17] [18] +Overfull \hbox (25.36118pt too wide) in paragraph at lines 72--83 +\TU/KpRoman(1)/m/n/12 the ap-prox-i-ma-tion hold-ing when $\TU/KpMath-Regular.o +tf(1)/m/n/12 𝑔$ \TU/KpRoman(1)/m/n/12 is lo-cally smooth. The bunch-ing ra-t +io $\TU/KpMath-Regular.otf(1)/m/n/12 𝑏(𝑦[]) = 𝐵(𝑦[])/𝑔(𝑦[]) +≈ + +Overfull \hbox (9.11465pt too wide) in paragraph at lines 86--100 +\TU/KpRoman(1)/m/n/12 behaviour---the gen-er-a-tor con-tains no firm location-c +hoice---and the placebo be-low proves +[19] [20<./figures/bunching_analysis_85k.png><./figures/bunching_analysis_90k.p +ng>] [21]) (./Sections/model.tex [22] +Overfull \hbox (9.26462pt too wide) in paragraph at lines 22--29 +\TU/KpRoman(1)/m/n/12 Two pop-u-la-tions are out-side its scope and are treated + as such through-out: below-threshold +[23]) (./Sections/behavioural.tex +Overfull \hbox (8.2552pt too wide) in paragraph at lines 139--1 +\TU/KpMath-Regular.otf(1)/m/n/12 (𝜏 − 𝑟) 𝑇[] = £5[]250$\TU/KpRoman( +1)/m/n/12 . The firm counts con-firm this (\TU/KpMono(0)/m/n/12 results/dominat +ed_region_mass.txt\TU/KpRoman(1)/m/n/12 ): +[24] [25<./figures/dynamic_notch_fit_e017.png>] [26] +Overfull \hbox (0.45064pt too wide) in paragraph at lines 76--83 +\TU/KpRoman(1)/m/n/12 firm’s op-ti-mal turnover un-der a coun-ter-fac-tual sc +hed-ule, \TU/KpRoman(1)/m/it/12 given \TU/KpRoman(1)/m/n/12 that its ob-served +turnover +[27<./figures/formulation_a_optima.png>] +Overfull \hbox (2.70668pt too wide) in paragraph at lines 87--96 +\TU/KpRoman(1)/m/n/12 The in-ten-sive re-sponse de-pends only on $\TU/KpMath-Re +gular.otf(1)/m/n/12 𝑒$\TU/KpRoman(1)/m/n/12 , the statu-tory rate, and the s +ched-ule fractions--- + +Overfull \hbox (19.06874pt too wide) in paragraph at lines 97--117 +[]\TU/KpRoman(1)/b/n/12 Region-confined scope.[] \TU/KpRoman(1)/m/n/12 The mar- +gin priced here is purely \TU/KpRoman(1)/m/it/12 in-ten-sive\TU/KpRoman(1)/m/n/ +12 : each firm re-optimises + +Overfull \hbox (1.25473pt too wide) in paragraph at lines 118--129 +[]\TU/KpRoman(1)/b/n/12 Con-di-tional on $\TU/KpMath-Regular.otf(1)/m/n/12 +𝑒$\TU/KpRoman(1)/b/n/12 .[] \TU/KpRoman(1)/m/n/12 The elas-tic-ity $\TU/KpMa +th-Regular.otf(1)/m/n/12 𝑒$ \TU/KpRoman(1)/m/n/12 is not iden-ti-fied from t +hese data, so ev-ery be-havioural + +Overfull \hbox (34.0586pt too wide) in paragraph at lines 154--166 + [][] +[28] [29]) (./Sections/conclusion.tex +Overfull \hbox (20.66867pt too wide) in paragraph at lines 4--13 +\TU/KpRoman(1)/m/n/12 the UK VAT reg-is-tra-tion thresh-old, re-leased in full- +--including its synthetic-data generator--- +[30<./figures/dynamic_cost_vs_elasticity.png>] +Overfull \hbox (68.06161pt too wide) in paragraph at lines 23--35 + [][] +[31]) [32] [33] (./main.bbl +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +[]\TU/KpRoman(1)/m/n/10.95 HM Rev-enue and Cus-toms (2024) ``In-creas-ing the V +AT Reg-is-tra-tion Thresh-old,'' + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpRoman(1)/m/n/10.95 Tax in-for-ma-tion and im-pact note, GOV.UK, [][]$\TU/ +KpMono(0)/m/n/10.95 https://www.gov.uk/government/ + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpMono(0)/m/n/10.95 publications/vat-[]increasing-[]the-[]registration-[]an +d-[]deregistration-[]thresholds/ +[34] +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +[]\TU/KpRoman(1)/m/n/10.95 HM Trea-sury (2018) ``VAT Reg-is-tra-tion Thresh-old +: Call for Ev-i-dence,'' HM + +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +\TU/KpRoman(1)/m/n/10.95 Trea-sury, March 2018, [][]$\TU/KpMono(0)/m/n/10.95 ht +tps://www.gov.uk/government/consultations/ + +Underfull \hbox (badness 7869) in paragraph at lines 106--109 +[] [] \TU/KpRoman(1)/m/n/10.95 (2024) ``Spring Bud-get 2024: Pol-icy Cost-ings, +'' HM Trea-sury, March 2024, + +Underfull \hbox (badness 10000) in paragraph at lines 106--109 +[][]$\TU/KpMono(0)/m/n/10.95 https://assets.publishing.service.gov.uk/media/65e +7920c08eef600155a5617/ + +Underfull \hbox (badness 4886) in paragraph at lines 133--137 +[]\TU/KpRoman(1)/m/n/10.95 Liu, Li, Ben Lock-wood, and Eddy H. F. Tam (2024) `` +Small Firm Growth and the + +Underfull \hbox (badness 2865) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 VAT Thresh-old: Ev-i-dence for the UK,'' IMF Work-ing +Pa-perWP/24/33, In-ter-na-tional + +Underfull \hbox (badness 10000) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 Mon-e-tary Fund, [][]$\TU/KpMono(0)/m/n/10.95 https:// +www.imf.org/en/publications/wp/issues/2024/02/16/ + +Underfull \hbox (badness 1490) in paragraph at lines 139--143 +\TU/KpRoman(1)/m/n/10.95 West Ben-gal, In-dia,'' TaxDev / In-sti-tute for Fis-c +al Stud-ies, [][]$\TU/KpMono(0)/m/n/10.95 https://www.taxdev.org/ + +Underfull \hbox (badness 10000) in paragraph at lines 146--149 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice for Bud-get Re-spon-si-bil-ity (2023) ``The +Im-pact of the Frozen VAT Reg-is-tra- + +Underfull \hbox (badness 4886) in paragraph at lines 146--149 +\TU/KpRoman(1)/m/n/10.95 tion Thresh-old,'' Eco-nomic and Fis-cal Out-look, Mar +ch 2023, [][]$\TU/KpMono(0)/m/n/10.95 https://obr.uk/box/ + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice of Tax Sim-pli-fi-ca-tion (2017) ``Value Add +ed Tax: Routes to Sim-pli-fi-ca-tion,'' + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +\TU/KpRoman(1)/m/n/10.95 OTS re-port, Novem-ber 2017, [][]$\TU/KpMono(0)/m/n/10 +.95 https://assets.publishing.service.gov.uk/media/ +[35]) [36] (./Appendix/appendix.tex (./Appendix/a_data.tex +Overfull \hbox (11.12668pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion check rather than a silent re-place-ment. The snap-s +hot used here is Pol-i-cyEngine/ledger + +Overfull \hbox (30.38661pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 and max-i-mum nu-meric dif-fer-ence zero. (The ``2024--25 + vin-tage'' here de-notes the HMRC/ONS + +Overfull \hbox (3.00157pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion cal-i-brates to.) A 1,000-iteration Pop-u-lace run f +rom those tar-gets gen-er-ated 2,946,015 + +Overfull \hbox (79.53078pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 into \TU/KpMono(0)/m/n/12 results/populace_ledger_compari +son.txt \TU/KpRoman(1)/m/n/12 and \TU/KpMono(0)/m/n/12 results/populace_ledger_ +provenance.json\TU/KpRoman(1)/m/n/12 . +[37]) (./Appendix/a_inference.tex +Overfull \hbox (103.32681pt too wide) in paragraph at lines 4--26 +\TU/KpMono(0)/m/n/12 results/bunching_inference.txt\TU/KpRoman(1)/m/n/12 , \TU/ +KpMono(0)/m/n/12 results/placebo_bunching.txt\TU/KpRoman(1)/m/n/12 , \TU/KpMono +(0)/m/n/12 results/recovery_bunching.txt +[38] [39] +Underfull \hbox (badness 1845) in paragraph at lines 159--159 +[][]\TU/KpRoman(1)/b/n/12 Ta-ble A.3[][]: []|\TU/KpRoman(1)/m/n/12 Power (re-co +v-ery) test on the step-free pop-u-la-tion: Kleven--Waseem- +[40]))) [41] (./main.aux)) +(see the transcript file for additional information) + 1318 words of node memory still in use: + 6 hlist, 2 vlist, 2 rule, 14 glue, 4 kern, 1 glyph, 163 attribute, 77 glue_s +pec, 82 attribute_list, 2 write, 26 pdf_action nodes + avail lists: 1:1,2:958,3:445,4:211,5:756,6:33,7:10104,8:146,9:374,10:28,11:7 +17 + +warning (pdf backend): unreferenced destination with name 'Hfootnote.2' + +warning (pdf backend): unreferenced destination with name 'Hfootnote.1' + + +Output written on main.pdf (41 pages, 2158642 bytes). +Transcript written on main.log. +Latexmk: Getting log file 'main.log' +Latexmk: Examining 'main.fls' +Latexmk: Examining 'main.log' +Latexmk: Found input bbl file 'main.bbl' +Latexmk: Log file says output to 'main.pdf' +Latexmk: Using bibtex to make bibliography file(s). + ===Source file 'main.bbl' for 'lualatex' +Latexmk: Found bibliography file(s): + ./references.bib +Latexmk: Summary of warnings from last run of *latex: + Latex failed to resolve 2 reference(s) +Latexmk: ====Problematic refs and citations with line #s in .tex file: + (pdf backend): unreferenced destination with name 'Hfootnote.2' + (pdf backend): unreferenced destination with name 'Hfootnote.1' +Latexmk: All targets (main.pdf) are up-to-date + diff --git a/latex5.log b/latex5.log new file mode 100644 index 0000000..bb94100 --- /dev/null +++ b/latex5.log @@ -0,0 +1,1271 @@ +Rc files read (in order): + NONE +Latexmk: This is Latexmk, John Collins, 9 March 2026. Version 4.88. +Latexmk: applying rule 'lualatex'... +Rule 'lualatex': Reasons for rerun +Changed files or newly in use/created: + Sections/data.tex +Category 'changed_user': + Sections/data.tex + +------------ +Run number 1 of rule 'lualatex' +------------ +------------ +Running 'lualatex -interaction=nonstopmode -halt-on-error -recorder "main.tex"' +------------ +This is LuaHBTeX, Version 1.24.0 (TeX Live 2026) + restricted system commands enabled. +(./main.tex +LaTeX2e <2025-11-01> +L3 programming layer <2026-01-19> + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/article.cls +Document Class: article 2025/01/22 v1.4n Standard LaTeX document class +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/size12.clo)) +(./YGTemplate.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3kernel/expl3.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3backend/l3backend-luatex.def))) + (/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec-luatex.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/babel.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/locale/en/babel-english.t +ex) (/usr/local/texlive/2026/texmf-dist/tex/generic/babel-english/english.ldf)) + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/lm/t1lmr.fd)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/a4wide/a4wide.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/ntgclass/a4.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/xcolor/xcolor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/color.cfg) + +Package xcolor Warning: Package option `usenames' is obsolete and ignored on in +put line 265. + +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-def/luatex.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/mathcolor.ltx)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/dvipsnam.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphicx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/keyval.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphics.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/trig.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/graphics.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/tabularx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/array.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.sty +**************************************** +* Local config file subfigure.cfg used * +**************************************** +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/float/float.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption3.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/subcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fnpct/fnpct.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/etoolbox/etoolbox.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/infwarerr/infwarerr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/iftex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty)))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts/kpfonts.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/kpfonts-otf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/realscripts/realscripts.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpRoman.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpLight.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpSans.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMono.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-luatex. +sty (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fix-cm.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ts1enc.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsmath.sty +For additional information on amsmath, use the `?' option. +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amstext.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsgen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsbsy.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsopn.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/lualatex/lualatex-math/lualatex-math.st +y) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-table.t +ex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMath-Regular.fontsp +ec))) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/pgf.revision.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeyslibraryfil +tered.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-luatex.d +ef +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-p +df.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol. +code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigo +nometric.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.rando +m.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.compa +rison.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integ +erarithmetics.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfint.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconst +ruct.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicst +ate.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransform +ations.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathproce +ssing.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretranspare +ncy.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code. +tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-0-65.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-1-18.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/math/pgfmath.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex)) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.cod +e.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothan +dlers.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarytopaths.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplots.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgfplotssysgeneric +.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgfplotslibrary.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_loader.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryfpu.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_pgfutil-common-lists.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/luamath/pgflibrar +yluamath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code +.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructure.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructureext.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +array.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +matrix.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +shared.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +deque.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.co +de.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.da +ta.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.verb +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgflibrarypgfplot +s.surfshading.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgflibrarypgfplots +.surfshading.pgfsys-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolormap. +code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolor.cod +e.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.c +ode.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplothandle +r.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplotimage. +code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscoordprocessin +g.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.errorbars.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.markers.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.paths.code.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduledecoration +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathmorphing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathmorphing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathreplacing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathreplacing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.contourlua.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryplotmarks.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplotmar +ks.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplotstable.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.coltype.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesome.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifxetex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifluatex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-ge +neric.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-xe +luatex.tex)) (/usr/local/texlive/2026/texmf-dist/tex/latex/psfrag/psfrag.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryintersections.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryinterse +ctions.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypatterns.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibrarypattern +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +decorations.softclip.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryf +illbetween.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.decorations.softclip.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/booktabs/booktabs.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/bm.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/rotating.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ifthen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hyperref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdfescape/pdfescape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hycolor/hycolor.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/nameref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/refcount/refcount.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/gettitlestring/gettitlestring.s +ty (/usr/local/texlive/2026/texmf-dist/tex/latex/kvoptions/kvoptions.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/stringenc/stringenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/pd1enc.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/intcalc/intcalc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/puenc.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/url/url.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/bitset/bitset.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hluatex.def +(/usr/local/texlive/2026/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty + +(/usr/local/texlive/2026/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +))) (/usr/local/texlive/2026/texmf-dist/tex/latex/todonotes/todonotes.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/xkeyval/xkeyval.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkeyval.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkvutils.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypositioning.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/calc.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/natbib/natbib.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/paralist/paralist.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/multicol.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/longtable.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/multirow/multirow.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/lscape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/chngcntr/chngcntr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/footmisc/footmisc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fmtcount.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcprefix.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcnumparser.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fc-english.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime-defaults.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/threeparttable/threeparttable.sty +) (/usr/local/texlive/2026/texmf-dist/tex/latex/diagbox/diagbox.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/p2e-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/sectsty/sectsty.sty + +LaTeX Warning: Command \underbar has changed. + Check if current package is valid. + + +LaTeX Warning: Command \underline has changed. + Check if current package is valid. + +)) (./title_metadata.tex) (./main.aux) +(/usr/local/texlive/2026/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +) (/usr/local/texlive/2026/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/ltcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations-basic-d +ictionary-english.trsl) + +Package pgfplots Warning: running in backwards compatibility mode (unsuitable t +ick labels; missing features). Consider writing \pgfplotsset{compat=1.18} into +your preamble. + on input line 12. + +(./main.out) (./main.out) + +Package todonotes Warning: The length marginparwidth is less than 2cm and will +most likely cause issues with the appearance of inserted todonotes. The issue c +an be solved by adding a line like \setlength {\marginparwidth }{2cm} prior to +loading the todonotes package. on input line 12. + +(./frontmatter.tex +Overfull \hbox (8.09319pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 registration-threshold re-forms, re-leased with its sy +nthetic-data gen-er-a-tor. The thresh- + +Overfull \hbox (8.50201pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/it/10.95 shape \TU/KpRoman(1)/m/n/10.95 (a ta-per) and \TU/KpR +oman(1)/m/it/10.95 rate \TU/KpRoman(1)/m/n/10.95 (a reduced-rate band) re-forms + stat-i-cally on a com-mon £184.8bn + +Overfull \hbox (45.11325pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 base: rais-ing the thresh-old to £100,000 costs £784 +m, a grad-u-ated ta-per over £85,000--£105,000 +[1 +Non-PDF special ignored!{/usr/local/texlive/2026/texmf-var/fonts/map/pdftex/upd +map/pdftex.map}] [2]) (./body.tex (./Sections/intro.tex [3<./figures/firms_by_t +urnover_band_85k.png><./figures/vat_firms_by_turnover_band_85k.png>] [4] +Overfull \hbox (0.9187pt too wide) in paragraph at lines 49--50 +[]\TU/KpRoman(1)/m/n/12 Third, con-di-tional on the as-sumed elas-tic-ity, inte +nsive-margin re-sponses barely move + +Overfull \hbox (13.0106pt too wide) in paragraph at lines 51--52 +\TU/KpRoman(1)/m/n/12 pa-per demon-strates the point in three di-rec-tions. The + 2023--24 pop-u-la-tion’s near-threshold +[5] [6]) (./Sections/background.tex [7]) (./Sections/data.tex [8<./figures/obr_ +vat_bunching_85k.png>] +Overfull \hbox (0.61864pt too wide) in paragraph at lines 4--16 +\TU/KpRoman(1)/m/n/12 Study-ing firm re-sponses at the thresh-old needs firm-le +vel turnover near the cut-off, which +[9] +Overfull \hbox (0.3166pt too wide) in paragraph at lines 60--64 +[]\TU/KpRoman(1)/m/n/12 The base pop-u-la-tion re-pro-duces the ONS struc-ture +but not the HMRC VAT-registered + +Overfull \hbox (23.08046pt too wide) in paragraph at lines 75--110 +\TU/KpRoman(1)/m/n/12 Chart C data give HMRC counts of busi-nesses by £1,000 t +urnover band over £65,000--£90,000 +[10] +Overfull \hbox (14.26959pt too wide) in paragraph at lines 137--163 +\TU/KpRoman(1)/m/n/12 statu-tory thresh-old was £85,000. The HMRC band tar-get +s step down across the threshold--- + +Overfull \hbox (21.09047pt too wide) in paragraph at lines 137--163 +\TU/KpRoman(1)/m/n/12 brated den-sity rises into the thresh-old (about $\TU/KpM +ath-Regular.otf(1)/m/n/12 13[]800$ \TU/KpRoman(1)/m/n/12 firms per £1,000 in t +he £84,000--£85,000 +[11]) (./Sections/static.tex [12<./figures/turnover_distribution_85k.png>] +[13] [14<./figures/vat_threshold_revenue_impact.png>] +Overfull \hbox (13.10669pt too wide) in paragraph at lines 168--182 +\TU/KpRoman(1)/m/n/12 The thresh-old sweep above moves the \TU/KpRoman(1)/m/it/ +12 lo-ca-tion \TU/KpRoman(1)/m/n/12 of a sin-gle cut-off. The same static princ +iple--- +[15] [16<./figures/revenue_impact_2025_26.png><./figures/firms_impact_2025_26.p +ng>]) (./Sections/bunching.tex +Overfull \hbox (6.67659pt too wide) in paragraph at lines 4--22 +\TU/KpRoman(1)/m/n/12 ([][]2011[][]) and [][]Kleven and Waseem[][] ([][]2013[][ +])---as ap-plied to UK VAT data by [][]Liu et al.[][] ([][]2021[][])---to +[17] [18] +Overfull \hbox (25.36118pt too wide) in paragraph at lines 72--83 +\TU/KpRoman(1)/m/n/12 the ap-prox-i-ma-tion hold-ing when $\TU/KpMath-Regular.o +tf(1)/m/n/12 𝑔$ \TU/KpRoman(1)/m/n/12 is lo-cally smooth. The bunch-ing ra-t +io $\TU/KpMath-Regular.otf(1)/m/n/12 𝑏(𝑦[]) = 𝐵(𝑦[])/𝑔(𝑦[]) +≈ + +Overfull \hbox (9.11465pt too wide) in paragraph at lines 86--100 +\TU/KpRoman(1)/m/n/12 behaviour---the gen-er-a-tor con-tains no firm location-c +hoice---and the placebo be-low proves +[19] [20<./figures/bunching_analysis_85k.png><./figures/bunching_analysis_90k.p +ng>] [21]) (./Sections/model.tex +Overfull \hbox (9.26462pt too wide) in paragraph at lines 22--29 +\TU/KpRoman(1)/m/n/12 Two pop-u-la-tions are out-side its scope and are treated + as such through-out: below-threshold +[22] [23] [24<./figures/dynamic_notch_fit_e017.png>]) +(./Sections/behavioural.tex +Overfull \hbox (8.2552pt too wide) in paragraph at lines 139--1 +\TU/KpMath-Regular.otf(1)/m/n/12 (𝜏 − 𝑟) 𝑇[] = £5[]250$\TU/KpRoman( +1)/m/n/12 . The firm counts con-firm this (\TU/KpMono(0)/m/n/12 results/dominat +ed_region_mass.txt\TU/KpRoman(1)/m/n/12 ): +[25] +Overfull \hbox (0.45064pt too wide) in paragraph at lines 76--83 +\TU/KpRoman(1)/m/n/12 firm’s op-ti-mal turnover un-der a coun-ter-fac-tual sc +hed-ule, \TU/KpRoman(1)/m/it/12 given \TU/KpRoman(1)/m/n/12 that its ob-served +turnover + +Overfull \hbox (2.70668pt too wide) in paragraph at lines 87--96 +\TU/KpRoman(1)/m/n/12 The in-ten-sive re-sponse de-pends only on $\TU/KpMath-Re +gular.otf(1)/m/n/12 𝑒$\TU/KpRoman(1)/m/n/12 , the statu-tory rate, and the s +ched-ule fractions--- + +Overfull \hbox (19.06874pt too wide) in paragraph at lines 97--117 +[]\TU/KpRoman(1)/b/n/12 Region-confined scope.[] \TU/KpRoman(1)/m/n/12 The mar- +gin priced here is purely \TU/KpRoman(1)/m/it/12 in-ten-sive\TU/KpRoman(1)/m/n/ +12 : each firm re-optimises +[26] +Overfull \hbox (1.25473pt too wide) in paragraph at lines 118--129 +[]\TU/KpRoman(1)/b/n/12 Con-di-tional on $\TU/KpMath-Regular.otf(1)/m/n/12 +𝑒$\TU/KpRoman(1)/b/n/12 .[] \TU/KpRoman(1)/m/n/12 The elas-tic-ity $\TU/KpMa +th-Regular.otf(1)/m/n/12 𝑒$ \TU/KpRoman(1)/m/n/12 is not iden-ti-fied from t +hese data, so ev-ery be-havioural +[27<./figures/formulation_a_optima.png>] +Overfull \hbox (34.0586pt too wide) in paragraph at lines 154--166 + [][] +[28]) (./Sections/conclusion.tex [29<./figures/dynamic_cost_vs_elasticity.png>] + +Overfull \hbox (20.66867pt too wide) in paragraph at lines 4--13 +\TU/KpRoman(1)/m/n/12 the UK VAT reg-is-tra-tion thresh-old, re-leased in full- +--including its synthetic-data generator--- + +Overfull \hbox (68.06161pt too wide) in paragraph at lines 23--35 + [][] +[30]) [31] [32] (./main.bbl +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +[]\TU/KpRoman(1)/m/n/10.95 HM Rev-enue and Cus-toms (2024) ``In-creas-ing the V +AT Reg-is-tra-tion Thresh-old,'' + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpRoman(1)/m/n/10.95 Tax in-for-ma-tion and im-pact note, GOV.UK, [][]$\TU/ +KpMono(0)/m/n/10.95 https://www.gov.uk/government/ + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpMono(0)/m/n/10.95 publications/vat-[]increasing-[]the-[]registration-[]an +d-[]deregistration-[]thresholds/ +[33] +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +[]\TU/KpRoman(1)/m/n/10.95 HM Trea-sury (2018) ``VAT Reg-is-tra-tion Thresh-old +: Call for Ev-i-dence,'' HM + +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +\TU/KpRoman(1)/m/n/10.95 Trea-sury, March 2018, [][]$\TU/KpMono(0)/m/n/10.95 ht +tps://www.gov.uk/government/consultations/ + +Underfull \hbox (badness 7869) in paragraph at lines 106--109 +[] [] \TU/KpRoman(1)/m/n/10.95 (2024) ``Spring Bud-get 2024: Pol-icy Cost-ings, +'' HM Trea-sury, March 2024, + +Underfull \hbox (badness 10000) in paragraph at lines 106--109 +[][]$\TU/KpMono(0)/m/n/10.95 https://assets.publishing.service.gov.uk/media/65e +7920c08eef600155a5617/ + +Underfull \hbox (badness 4886) in paragraph at lines 133--137 +[]\TU/KpRoman(1)/m/n/10.95 Liu, Li, Ben Lock-wood, and Eddy H. F. Tam (2024) `` +Small Firm Growth and the + +Underfull \hbox (badness 2865) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 VAT Thresh-old: Ev-i-dence for the UK,'' IMF Work-ing +Pa-perWP/24/33, In-ter-na-tional + +Underfull \hbox (badness 10000) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 Mon-e-tary Fund, [][]$\TU/KpMono(0)/m/n/10.95 https:// +www.imf.org/en/publications/wp/issues/2024/02/16/ + +Underfull \hbox (badness 1490) in paragraph at lines 139--143 +\TU/KpRoman(1)/m/n/10.95 West Ben-gal, In-dia,'' TaxDev / In-sti-tute for Fis-c +al Stud-ies, [][]$\TU/KpMono(0)/m/n/10.95 https://www.taxdev.org/ + +Underfull \hbox (badness 10000) in paragraph at lines 146--149 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice for Bud-get Re-spon-si-bil-ity (2023) ``The +Im-pact of the Frozen VAT Reg-is-tra- + +Underfull \hbox (badness 4886) in paragraph at lines 146--149 +\TU/KpRoman(1)/m/n/10.95 tion Thresh-old,'' Eco-nomic and Fis-cal Out-look, Mar +ch 2023, [][]$\TU/KpMono(0)/m/n/10.95 https://obr.uk/box/ + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice of Tax Sim-pli-fi-ca-tion (2017) ``Value Add +ed Tax: Routes to Sim-pli-fi-ca-tion,'' + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +\TU/KpRoman(1)/m/n/10.95 OTS re-port, Novem-ber 2017, [][]$\TU/KpMono(0)/m/n/10 +.95 https://assets.publishing.service.gov.uk/media/ +[34]) [35] (./Appendix/appendix.tex (./Appendix/a_data.tex +Overfull \hbox (11.12668pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion check rather than a silent re-place-ment. The snap-s +hot used here is Pol-i-cyEngine/ledger + +Overfull \hbox (30.38661pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 and max-i-mum nu-meric dif-fer-ence zero. (The ``2024--25 + vin-tage'' here de-notes the HMRC/ONS + +Overfull \hbox (3.00157pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion cal-i-brates to.) A 1,000-iteration Pop-u-lace run f +rom those tar-gets gen-er-ated 2,946,015 + +Overfull \hbox (79.53078pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 into \TU/KpMono(0)/m/n/12 results/populace_ledger_compari +son.txt \TU/KpRoman(1)/m/n/12 and \TU/KpMono(0)/m/n/12 results/populace_ledger_ +provenance.json\TU/KpRoman(1)/m/n/12 . +[36]) (./Appendix/a_inference.tex +Overfull \hbox (103.32681pt too wide) in paragraph at lines 4--26 +\TU/KpMono(0)/m/n/12 results/bunching_inference.txt\TU/KpRoman(1)/m/n/12 , \TU/ +KpMono(0)/m/n/12 results/placebo_bunching.txt\TU/KpRoman(1)/m/n/12 , \TU/KpMono +(0)/m/n/12 results/recovery_bunching.txt +[37] [38] +Underfull \hbox (badness 1845) in paragraph at lines 159--159 +[][]\TU/KpRoman(1)/b/n/12 Ta-ble A.3[][]: []|\TU/KpRoman(1)/m/n/12 Power (re-co +v-ery) test on the step-free pop-u-la-tion: Kleven--Waseem- +[39]))) [40] (./main.aux) + +LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right. + +) +(see the transcript file for additional information) + 1305 words of node memory still in use: + 6 hlist, 2 vlist, 2 rule, 13 glue, 4 kern, 1 glyph, 161 attribute, 77 glue_s +pec, 81 attribute_list, 2 write, 26 pdf_action nodes + avail lists: 1:1,2:942,3:445,4:211,5:829,6:33,7:10233,8:146,9:439,10:28,11:7 +48 + +warning (pdf backend): unreferenced destination with name 'Hfootnote.2' + +warning (pdf backend): unreferenced destination with name 'Hfootnote.1' + + +Output written on main.pdf (40 pages, 2158405 bytes). +Transcript written on main.log. +Latexmk: Getting log file 'main.log' +Latexmk: Examining 'main.fls' +Latexmk: Examining 'main.log' +Latexmk: Found input bbl file 'main.bbl' +Latexmk: References changed. +Latexmk: References changed. +Latexmk: Log file says output to 'main.pdf' +Latexmk: Using bibtex to make bibliography file(s). + ===Source file 'main.bbl' for 'lualatex' +Latexmk: Found bibliography file(s): + ./references.bib +Latexmk: applying rule 'bibtex main'... +Rule 'bibtex main': Reasons for rerun +Changed files or newly in use/created: + main.aux + +------------ +Run number 1 of rule 'bibtex main' +------------ +------------ +Running 'bibtex "main.aux"' +------------ +This is BibTeX, Version 0.99e (TeX Live 2026) +The top-level auxiliary file: main.aux +The style file: econ.bst +Database file #1: references.bib +Latexmk: applying rule 'lualatex'... +Rule 'lualatex': Reasons for rerun +Changed files or newly in use/created: + main.aux + +------------ +Run number 2 of rule 'lualatex' +------------ +------------ +Running 'lualatex -interaction=nonstopmode -halt-on-error -recorder "main.tex"' +------------ +This is LuaHBTeX, Version 1.24.0 (TeX Live 2026) + restricted system commands enabled. +(./main.tex +LaTeX2e <2025-11-01> +L3 programming layer <2026-01-19> + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/article.cls +Document Class: article 2025/01/22 v1.4n Standard LaTeX document class +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/size12.clo)) +(./YGTemplate.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3kernel/expl3.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3backend/l3backend-luatex.def))) + (/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec-luatex.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/babel.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/locale/en/babel-english.t +ex) (/usr/local/texlive/2026/texmf-dist/tex/generic/babel-english/english.ldf)) + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/lm/t1lmr.fd)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/a4wide/a4wide.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/ntgclass/a4.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/xcolor/xcolor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/color.cfg) + +Package xcolor Warning: Package option `usenames' is obsolete and ignored on in +put line 265. + +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-def/luatex.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/mathcolor.ltx)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/dvipsnam.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphicx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/keyval.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphics.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/trig.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/graphics.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/tabularx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/array.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.sty +**************************************** +* Local config file subfigure.cfg used * +**************************************** +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/float/float.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption3.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/subcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fnpct/fnpct.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/etoolbox/etoolbox.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/infwarerr/infwarerr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/iftex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty)))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts/kpfonts.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/kpfonts-otf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/realscripts/realscripts.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpRoman.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpLight.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpSans.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMono.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-luatex. +sty (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fix-cm.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ts1enc.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsmath.sty +For additional information on amsmath, use the `?' option. +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amstext.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsgen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsbsy.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsopn.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/lualatex/lualatex-math/lualatex-math.st +y) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-table.t +ex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMath-Regular.fontsp +ec))) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/pgf.revision.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeyslibraryfil +tered.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-luatex.d +ef +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-p +df.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol. +code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigo +nometric.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.rando +m.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.compa +rison.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integ +erarithmetics.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfint.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconst +ruct.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicst +ate.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransform +ations.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathproce +ssing.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretranspare +ncy.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code. +tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-0-65.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-1-18.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/math/pgfmath.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex)) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.cod +e.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothan +dlers.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarytopaths.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplots.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgfplotssysgeneric +.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgfplotslibrary.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_loader.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryfpu.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_pgfutil-common-lists.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/luamath/pgflibrar +yluamath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code +.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructure.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructureext.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +array.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +matrix.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +shared.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +deque.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.co +de.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.da +ta.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.verb +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgflibrarypgfplot +s.surfshading.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgflibrarypgfplots +.surfshading.pgfsys-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolormap. +code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolor.cod +e.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.c +ode.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplothandle +r.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplotimage. +code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscoordprocessin +g.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.errorbars.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.markers.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.paths.code.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduledecoration +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathmorphing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathmorphing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathreplacing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathreplacing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.contourlua.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryplotmarks.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplotmar +ks.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplotstable.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.coltype.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesome.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifxetex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifluatex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-ge +neric.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-xe +luatex.tex)) (/usr/local/texlive/2026/texmf-dist/tex/latex/psfrag/psfrag.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryintersections.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryinterse +ctions.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypatterns.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibrarypattern +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +decorations.softclip.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryf +illbetween.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.decorations.softclip.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/booktabs/booktabs.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/bm.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/rotating.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ifthen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hyperref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdfescape/pdfescape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hycolor/hycolor.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/nameref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/refcount/refcount.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/gettitlestring/gettitlestring.s +ty (/usr/local/texlive/2026/texmf-dist/tex/latex/kvoptions/kvoptions.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/stringenc/stringenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/pd1enc.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/intcalc/intcalc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/puenc.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/url/url.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/bitset/bitset.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hluatex.def +(/usr/local/texlive/2026/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty + +(/usr/local/texlive/2026/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +))) (/usr/local/texlive/2026/texmf-dist/tex/latex/todonotes/todonotes.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/xkeyval/xkeyval.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkeyval.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkvutils.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypositioning.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/calc.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/natbib/natbib.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/paralist/paralist.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/multicol.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/longtable.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/multirow/multirow.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/lscape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/chngcntr/chngcntr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/footmisc/footmisc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fmtcount.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcprefix.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcnumparser.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fc-english.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime-defaults.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/threeparttable/threeparttable.sty +) (/usr/local/texlive/2026/texmf-dist/tex/latex/diagbox/diagbox.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/p2e-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/sectsty/sectsty.sty + +LaTeX Warning: Command \underbar has changed. + Check if current package is valid. + + +LaTeX Warning: Command \underline has changed. + Check if current package is valid. + +)) (./title_metadata.tex) (./main.aux) +(/usr/local/texlive/2026/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +) (/usr/local/texlive/2026/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/ltcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations-basic-d +ictionary-english.trsl) + +Package pgfplots Warning: running in backwards compatibility mode (unsuitable t +ick labels; missing features). Consider writing \pgfplotsset{compat=1.18} into +your preamble. + on input line 12. + +(./main.out) (./main.out) + +Package todonotes Warning: The length marginparwidth is less than 2cm and will +most likely cause issues with the appearance of inserted todonotes. The issue c +an be solved by adding a line like \setlength {\marginparwidth }{2cm} prior to +loading the todonotes package. on input line 12. + +(./frontmatter.tex +Overfull \hbox (8.09319pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 registration-threshold re-forms, re-leased with its sy +nthetic-data gen-er-a-tor. The thresh- + +Overfull \hbox (8.50201pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/it/10.95 shape \TU/KpRoman(1)/m/n/10.95 (a ta-per) and \TU/KpR +oman(1)/m/it/10.95 rate \TU/KpRoman(1)/m/n/10.95 (a reduced-rate band) re-forms + stat-i-cally on a com-mon £184.8bn + +Overfull \hbox (45.11325pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 base: rais-ing the thresh-old to £100,000 costs £784 +m, a grad-u-ated ta-per over £85,000--£105,000 +[1 +Non-PDF special ignored!{/usr/local/texlive/2026/texmf-var/fonts/map/pdftex/upd +map/pdftex.map}] [2]) (./body.tex (./Sections/intro.tex [3<./figures/firms_by_t +urnover_band_85k.png><./figures/vat_firms_by_turnover_band_85k.png>] [4] +Overfull \hbox (0.9187pt too wide) in paragraph at lines 49--50 +[]\TU/KpRoman(1)/m/n/12 Third, con-di-tional on the as-sumed elas-tic-ity, inte +nsive-margin re-sponses barely move + +Overfull \hbox (13.0106pt too wide) in paragraph at lines 51--52 +\TU/KpRoman(1)/m/n/12 pa-per demon-strates the point in three di-rec-tions. The + 2023--24 pop-u-la-tion’s near-threshold +[5] [6]) (./Sections/background.tex [7]) (./Sections/data.tex [8<./figures/obr_ +vat_bunching_85k.png>] +Overfull \hbox (0.61864pt too wide) in paragraph at lines 4--16 +\TU/KpRoman(1)/m/n/12 Study-ing firm re-sponses at the thresh-old needs firm-le +vel turnover near the cut-off, which +[9] +Overfull \hbox (0.3166pt too wide) in paragraph at lines 60--64 +[]\TU/KpRoman(1)/m/n/12 The base pop-u-la-tion re-pro-duces the ONS struc-ture +but not the HMRC VAT-registered + +Overfull \hbox (23.08046pt too wide) in paragraph at lines 75--110 +\TU/KpRoman(1)/m/n/12 Chart C data give HMRC counts of busi-nesses by £1,000 t +urnover band over £65,000--£90,000 +[10] +Overfull \hbox (14.26959pt too wide) in paragraph at lines 137--163 +\TU/KpRoman(1)/m/n/12 statu-tory thresh-old was £85,000. The HMRC band tar-get +s step down across the threshold--- + +Overfull \hbox (21.09047pt too wide) in paragraph at lines 137--163 +\TU/KpRoman(1)/m/n/12 brated den-sity rises into the thresh-old (about $\TU/KpM +ath-Regular.otf(1)/m/n/12 13[]800$ \TU/KpRoman(1)/m/n/12 firms per £1,000 in t +he £84,000--£85,000 +[11]) (./Sections/static.tex [12<./figures/turnover_distribution_85k.png>] +[13] [14<./figures/vat_threshold_revenue_impact.png>] +Overfull \hbox (13.10669pt too wide) in paragraph at lines 168--182 +\TU/KpRoman(1)/m/n/12 The thresh-old sweep above moves the \TU/KpRoman(1)/m/it/ +12 lo-ca-tion \TU/KpRoman(1)/m/n/12 of a sin-gle cut-off. The same static princ +iple--- +[15] [16<./figures/revenue_impact_2025_26.png><./figures/firms_impact_2025_26.p +ng>]) (./Sections/bunching.tex +Overfull \hbox (6.67659pt too wide) in paragraph at lines 4--22 +\TU/KpRoman(1)/m/n/12 ([][]2011[][]) and [][]Kleven and Waseem[][] ([][]2013[][ +])---as ap-plied to UK VAT data by [][]Liu et al.[][] ([][]2021[][])---to +[17] [18] +Overfull \hbox (25.36118pt too wide) in paragraph at lines 72--83 +\TU/KpRoman(1)/m/n/12 the ap-prox-i-ma-tion hold-ing when $\TU/KpMath-Regular.o +tf(1)/m/n/12 𝑔$ \TU/KpRoman(1)/m/n/12 is lo-cally smooth. The bunch-ing ra-t +io $\TU/KpMath-Regular.otf(1)/m/n/12 𝑏(𝑦[]) = 𝐵(𝑦[])/𝑔(𝑦[]) +≈ + +Overfull \hbox (9.11465pt too wide) in paragraph at lines 86--100 +\TU/KpRoman(1)/m/n/12 behaviour---the gen-er-a-tor con-tains no firm location-c +hoice---and the placebo be-low proves +[19] [20<./figures/bunching_analysis_85k.png><./figures/bunching_analysis_90k.p +ng>] [21]) (./Sections/model.tex +Overfull \hbox (9.26462pt too wide) in paragraph at lines 22--29 +\TU/KpRoman(1)/m/n/12 Two pop-u-la-tions are out-side its scope and are treated + as such through-out: below-threshold +[22] [23] [24<./figures/dynamic_notch_fit_e017.png>]) +(./Sections/behavioural.tex +Overfull \hbox (8.2552pt too wide) in paragraph at lines 139--1 +\TU/KpMath-Regular.otf(1)/m/n/12 (𝜏 − 𝑟) 𝑇[] = £5[]250$\TU/KpRoman( +1)/m/n/12 . The firm counts con-firm this (\TU/KpMono(0)/m/n/12 results/dominat +ed_region_mass.txt\TU/KpRoman(1)/m/n/12 ): +[25] +Overfull \hbox (0.45064pt too wide) in paragraph at lines 76--83 +\TU/KpRoman(1)/m/n/12 firm’s op-ti-mal turnover un-der a coun-ter-fac-tual sc +hed-ule, \TU/KpRoman(1)/m/it/12 given \TU/KpRoman(1)/m/n/12 that its ob-served +turnover + +Overfull \hbox (2.70668pt too wide) in paragraph at lines 87--96 +\TU/KpRoman(1)/m/n/12 The in-ten-sive re-sponse de-pends only on $\TU/KpMath-Re +gular.otf(1)/m/n/12 𝑒$\TU/KpRoman(1)/m/n/12 , the statu-tory rate, and the s +ched-ule fractions--- + +Overfull \hbox (19.06874pt too wide) in paragraph at lines 97--117 +[]\TU/KpRoman(1)/b/n/12 Region-confined scope.[] \TU/KpRoman(1)/m/n/12 The mar- +gin priced here is purely \TU/KpRoman(1)/m/it/12 in-ten-sive\TU/KpRoman(1)/m/n/ +12 : each firm re-optimises +[26] +Overfull \hbox (1.25473pt too wide) in paragraph at lines 118--129 +[]\TU/KpRoman(1)/b/n/12 Con-di-tional on $\TU/KpMath-Regular.otf(1)/m/n/12 +𝑒$\TU/KpRoman(1)/b/n/12 .[] \TU/KpRoman(1)/m/n/12 The elas-tic-ity $\TU/KpMa +th-Regular.otf(1)/m/n/12 𝑒$ \TU/KpRoman(1)/m/n/12 is not iden-ti-fied from t +hese data, so ev-ery be-havioural +[27<./figures/formulation_a_optima.png>] +Overfull \hbox (34.0586pt too wide) in paragraph at lines 154--166 + [][] +[28]) (./Sections/conclusion.tex [29<./figures/dynamic_cost_vs_elasticity.png>] + +Overfull \hbox (20.66867pt too wide) in paragraph at lines 4--13 +\TU/KpRoman(1)/m/n/12 the UK VAT reg-is-tra-tion thresh-old, re-leased in full- +--including its synthetic-data generator--- + +Overfull \hbox (68.06161pt too wide) in paragraph at lines 23--35 + [][] +[30]) [31] [32] (./main.bbl +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +[]\TU/KpRoman(1)/m/n/10.95 HM Rev-enue and Cus-toms (2024) ``In-creas-ing the V +AT Reg-is-tra-tion Thresh-old,'' + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpRoman(1)/m/n/10.95 Tax in-for-ma-tion and im-pact note, GOV.UK, [][]$\TU/ +KpMono(0)/m/n/10.95 https://www.gov.uk/government/ + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpMono(0)/m/n/10.95 publications/vat-[]increasing-[]the-[]registration-[]an +d-[]deregistration-[]thresholds/ +[33] +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +[]\TU/KpRoman(1)/m/n/10.95 HM Trea-sury (2018) ``VAT Reg-is-tra-tion Thresh-old +: Call for Ev-i-dence,'' HM + +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +\TU/KpRoman(1)/m/n/10.95 Trea-sury, March 2018, [][]$\TU/KpMono(0)/m/n/10.95 ht +tps://www.gov.uk/government/consultations/ + +Underfull \hbox (badness 7869) in paragraph at lines 106--109 +[] [] \TU/KpRoman(1)/m/n/10.95 (2024) ``Spring Bud-get 2024: Pol-icy Cost-ings, +'' HM Trea-sury, March 2024, + +Underfull \hbox (badness 10000) in paragraph at lines 106--109 +[][]$\TU/KpMono(0)/m/n/10.95 https://assets.publishing.service.gov.uk/media/65e +7920c08eef600155a5617/ + +Underfull \hbox (badness 4886) in paragraph at lines 133--137 +[]\TU/KpRoman(1)/m/n/10.95 Liu, Li, Ben Lock-wood, and Eddy H. F. Tam (2024) `` +Small Firm Growth and the + +Underfull \hbox (badness 2865) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 VAT Thresh-old: Ev-i-dence for the UK,'' IMF Work-ing +Pa-perWP/24/33, In-ter-na-tional + +Underfull \hbox (badness 10000) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 Mon-e-tary Fund, [][]$\TU/KpMono(0)/m/n/10.95 https:// +www.imf.org/en/publications/wp/issues/2024/02/16/ + +Underfull \hbox (badness 1490) in paragraph at lines 139--143 +\TU/KpRoman(1)/m/n/10.95 West Ben-gal, In-dia,'' TaxDev / In-sti-tute for Fis-c +al Stud-ies, [][]$\TU/KpMono(0)/m/n/10.95 https://www.taxdev.org/ + +Underfull \hbox (badness 10000) in paragraph at lines 146--149 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice for Bud-get Re-spon-si-bil-ity (2023) ``The +Im-pact of the Frozen VAT Reg-is-tra- + +Underfull \hbox (badness 4886) in paragraph at lines 146--149 +\TU/KpRoman(1)/m/n/10.95 tion Thresh-old,'' Eco-nomic and Fis-cal Out-look, Mar +ch 2023, [][]$\TU/KpMono(0)/m/n/10.95 https://obr.uk/box/ + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice of Tax Sim-pli-fi-ca-tion (2017) ``Value Add +ed Tax: Routes to Sim-pli-fi-ca-tion,'' + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +\TU/KpRoman(1)/m/n/10.95 OTS re-port, Novem-ber 2017, [][]$\TU/KpMono(0)/m/n/10 +.95 https://assets.publishing.service.gov.uk/media/ +[34]) [35] (./Appendix/appendix.tex (./Appendix/a_data.tex +Overfull \hbox (11.12668pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion check rather than a silent re-place-ment. The snap-s +hot used here is Pol-i-cyEngine/ledger + +Overfull \hbox (30.38661pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 and max-i-mum nu-meric dif-fer-ence zero. (The ``2024--25 + vin-tage'' here de-notes the HMRC/ONS + +Overfull \hbox (3.00157pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion cal-i-brates to.) A 1,000-iteration Pop-u-lace run f +rom those tar-gets gen-er-ated 2,946,015 + +Overfull \hbox (79.53078pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 into \TU/KpMono(0)/m/n/12 results/populace_ledger_compari +son.txt \TU/KpRoman(1)/m/n/12 and \TU/KpMono(0)/m/n/12 results/populace_ledger_ +provenance.json\TU/KpRoman(1)/m/n/12 . +[36]) (./Appendix/a_inference.tex +Overfull \hbox (103.32681pt too wide) in paragraph at lines 4--26 +\TU/KpMono(0)/m/n/12 results/bunching_inference.txt\TU/KpRoman(1)/m/n/12 , \TU/ +KpMono(0)/m/n/12 results/placebo_bunching.txt\TU/KpRoman(1)/m/n/12 , \TU/KpMono +(0)/m/n/12 results/recovery_bunching.txt +[37] [38] +Underfull \hbox (badness 1845) in paragraph at lines 159--159 +[][]\TU/KpRoman(1)/b/n/12 Ta-ble A.3[][]: []|\TU/KpRoman(1)/m/n/12 Power (re-co +v-ery) test on the step-free pop-u-la-tion: Kleven--Waseem- +[39]))) [40] (./main.aux)) +(see the transcript file for additional information) + 1305 words of node memory still in use: + 6 hlist, 2 vlist, 2 rule, 13 glue, 4 kern, 1 glyph, 161 attribute, 77 glue_s +pec, 81 attribute_list, 2 write, 26 pdf_action nodes + avail lists: 1:1,2:942,3:445,4:211,5:829,6:33,7:10233,8:146,9:439,10:28,11:7 +48 + +warning (pdf backend): unreferenced destination with name 'Hfootnote.2' + +warning (pdf backend): unreferenced destination with name 'Hfootnote.1' + + +Output written on main.pdf (40 pages, 2158405 bytes). +Transcript written on main.log. +Latexmk: Getting log file 'main.log' +Latexmk: Examining 'main.fls' +Latexmk: Examining 'main.log' +Latexmk: Found input bbl file 'main.bbl' +Latexmk: Log file says output to 'main.pdf' +Latexmk: Using bibtex to make bibliography file(s). + ===Source file 'main.bbl' for 'lualatex' +Latexmk: Found bibliography file(s): + ./references.bib +Latexmk: Summary of warnings from last run of *latex: + Latex failed to resolve 2 reference(s) +Latexmk: ====Problematic refs and citations with line #s in .tex file: + (pdf backend): unreferenced destination with name 'Hfootnote.2' + (pdf backend): unreferenced destination with name 'Hfootnote.1' +Latexmk: All targets (main.pdf) are up-to-date + diff --git a/latex_build.log b/latex_build.log new file mode 100644 index 0000000..01aca81 --- /dev/null +++ b/latex_build.log @@ -0,0 +1,3359 @@ +Rc files read (in order): + NONE +Latexmk: This is Latexmk, John Collins, 9 March 2026. Version 4.88. +Latexmk: applying rule 'lualatex'... +Rule 'lualatex': Reasons for rerun +Changed files or newly in use/created: + figures/bunching_analysis_85k.png + figures/bunching_analysis_90k.png +Category 'changed_user': + figures/bunching_analysis_85k.png + figures/bunching_analysis_90k.png + +------------ +Run number 1 of rule 'lualatex' +------------ +------------ +Running 'lualatex -interaction=nonstopmode -halt-on-error -recorder "main.tex"' +------------ +This is LuaHBTeX, Version 1.24.0 (TeX Live 2026) + restricted system commands enabled. +(./main.tex +LaTeX2e <2025-11-01> +L3 programming layer <2026-01-19> + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/article.cls +Document Class: article 2025/01/22 v1.4n Standard LaTeX document class +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/size12.clo)) +(./YGTemplate.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3kernel/expl3.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3backend/l3backend-luatex.def))) + (/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec-luatex.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/babel.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/locale/en/babel-english.t +ex) (/usr/local/texlive/2026/texmf-dist/tex/generic/babel-english/english.ldf)) + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/lm/t1lmr.fd)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/a4wide/a4wide.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/ntgclass/a4.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/xcolor/xcolor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/color.cfg) + +Package xcolor Warning: Package option `usenames' is obsolete and ignored on in +put line 265. + +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-def/luatex.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/mathcolor.ltx)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/dvipsnam.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphicx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/keyval.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphics.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/trig.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/graphics.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/tabularx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/array.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.sty +**************************************** +* Local config file subfigure.cfg used * +**************************************** +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/float/float.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption3.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/subcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fnpct/fnpct.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/etoolbox/etoolbox.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/infwarerr/infwarerr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/iftex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty)))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts/kpfonts.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/kpfonts-otf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/realscripts/realscripts.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpRoman.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpLight.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpSans.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMono.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-luatex. +sty (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fix-cm.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ts1enc.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsmath.sty +For additional information on amsmath, use the `?' option. +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amstext.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsgen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsbsy.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsopn.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/lualatex/lualatex-math/lualatex-math.st +y) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-table.t +ex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMath-Regular.fontsp +ec))) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/pgf.revision.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeyslibraryfil +tered.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-luatex.d +ef +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-p +df.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol. +code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigo +nometric.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.rando +m.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.compa +rison.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integ +erarithmetics.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfint.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconst +ruct.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicst +ate.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransform +ations.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathproce +ssing.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretranspare +ncy.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code. +tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-0-65.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-1-18.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/math/pgfmath.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex)) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.cod +e.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothan +dlers.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarytopaths.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplots.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgfplotssysgeneric +.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgfplotslibrary.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_loader.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryfpu.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_pgfutil-common-lists.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/luamath/pgflibrar +yluamath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code +.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructure.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructureext.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +array.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +matrix.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +shared.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +deque.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.co +de.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.da +ta.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.verb +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgflibrarypgfplot +s.surfshading.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgflibrarypgfplots +.surfshading.pgfsys-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolormap. +code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolor.cod +e.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.c +ode.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplothandle +r.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplotimage. +code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscoordprocessin +g.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.errorbars.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.markers.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.paths.code.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduledecoration +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathmorphing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathmorphing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathreplacing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathreplacing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.contourlua.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryplotmarks.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplotmar +ks.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplotstable.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.coltype.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesome.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifxetex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifluatex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-ge +neric.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-xe +luatex.tex)) (/usr/local/texlive/2026/texmf-dist/tex/latex/psfrag/psfrag.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryintersections.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryinterse +ctions.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypatterns.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibrarypattern +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +decorations.softclip.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryf +illbetween.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.decorations.softclip.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/booktabs/booktabs.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/bm.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/rotating.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ifthen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hyperref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdfescape/pdfescape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hycolor/hycolor.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/nameref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/refcount/refcount.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/gettitlestring/gettitlestring.s +ty (/usr/local/texlive/2026/texmf-dist/tex/latex/kvoptions/kvoptions.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/stringenc/stringenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/pd1enc.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/intcalc/intcalc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/puenc.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/url/url.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/bitset/bitset.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hluatex.def +(/usr/local/texlive/2026/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty + +(/usr/local/texlive/2026/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +))) (/usr/local/texlive/2026/texmf-dist/tex/latex/todonotes/todonotes.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/xkeyval/xkeyval.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkeyval.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkvutils.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypositioning.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/calc.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/natbib/natbib.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/paralist/paralist.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/multicol.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/longtable.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/multirow/multirow.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/lscape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/chngcntr/chngcntr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/footmisc/footmisc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fmtcount.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcprefix.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcnumparser.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fc-english.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime-defaults.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/threeparttable/threeparttable.sty +) (/usr/local/texlive/2026/texmf-dist/tex/latex/diagbox/diagbox.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/p2e-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/sectsty/sectsty.sty + +LaTeX Warning: Command \underbar has changed. + Check if current package is valid. + + +LaTeX Warning: Command \underline has changed. + Check if current package is valid. + +)) (./title_metadata.tex) (./main.aux) +(/usr/local/texlive/2026/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +) (/usr/local/texlive/2026/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/ltcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations-basic-d +ictionary-english.trsl) + +Package pgfplots Warning: running in backwards compatibility mode (unsuitable t +ick labels; missing features). Consider writing \pgfplotsset{compat=1.18} into +your preamble. + on input line 12. + +(./main.out) (./main.out) + +Package todonotes Warning: The length marginparwidth is less than 2cm and will +most likely cause issues with the appearance of inserted todonotes. The issue c +an be solved by adding a line like \setlength {\marginparwidth }{2cm} prior to +loading the todonotes package. on input line 12. + +(./frontmatter.tex +Overfull \hbox (8.09319pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 registration-threshold re-forms, re-leased with its sy +nthetic-data gen-er-a-tor. The thresh- +[1 +Non-PDF special ignored!{/usr/local/texlive/2026/texmf-var/fonts/map/pdftex/upd +map/pdftex.map}]) (./body.tex (./Sections/intro.tex + +Package natbib Warning: Citation `hoc_vat' on page 2 undefined on input line 3. + + + +Package natbib Warning: Citation `hmrc_threshold' on page 2 undefined on input +line 3. + + +Package natbib Warning: Citation `obr2023vat' on page 2 undefined on input line + 31. + + +Package natbib Warning: Citation `liuetal2021' on page 2 undefined on input lin +e 32. + + +Package natbib Warning: Citation `liulockwoodtam2024' on page 2 undefined on in +put line 34. + +[2<./figures/firms_by_turnover_band_85k.png><./figures/vat_firms_by_turnover_ba +nd_85k.png>] + +Package natbib Warning: Citation `liuetal2021' on page 3 undefined on input lin +e 45. + + +Package natbib Warning: Citation `hmt_spring_budget_2024' on page 3 undefined o +n input line 45. + + +LaTeX Warning: Reference `sec:behavioural' on page 3 undefined on input line 47 +. + + +LaTeX Warning: Reference `sec:conclusion' on page 3 undefined on input line 47. + + +[3] + +Package natbib Warning: Citation `klevenwaseem2013' on page 4 undefined on inpu +t line 49. + + +Package natbib Warning: Citation `liuetal2021' on page 4 undefined on input lin +e 49. + + +Overfull \hbox (0.9187pt too wide) in paragraph at lines 49--50 +[]\TU/KpRoman(1)/m/n/12 Third, con-di-tional on the as-sumed elas-tic-ity, inte +nsive-margin re-sponses barely move + +Package natbib Warning: Citation `liuetal2021' on page 4 undefined on input lin +e 51. + +[4] + +Package natbib Warning: Citation `chettyetal2011' on page 5 undefined on input +line 55. + + +Package natbib Warning: Citation `saez2010' on page 5 undefined on input line 5 +5. + + +Package natbib Warning: Citation `klevenwaseem2013' on page 5 undefined on inpu +t line 55. + + +Package natbib Warning: Citation `kleven2016' on page 5 undefined on input line + 55. + + +Package natbib Warning: Citation `best2015' on page 5 undefined on input line 5 +5. + + +Package natbib Warning: Citation `liuetal2021' on page 5 undefined on input lin +e 57. + + +Package natbib Warning: Citation `liulockwoodtam2024' on page 5 undefined on in +put line 57. + + +Package natbib Warning: Citation `onji2009' on page 5 undefined on input line 5 +7. + + +Package natbib Warning: Citation `harju2019' on page 5 undefined on input line +57. + + +Package natbib Warning: Citation `asatryanpeichl2017' on page 5 undefined on in +put line 57. + + +Package natbib Warning: Citation `nandiwarwick2020' on page 5 undefined on inpu +t line 57. + + +Package natbib Warning: Citation `waseem2024' on page 5 undefined on input line + 57. + + +Package natbib Warning: Citation `liuetal2021' on page 5 undefined on input lin +e 57. + + +Package natbib Warning: Citation `harju2019' on page 5 undefined on input line +57. + + +Package natbib Warning: Citation `onji2009' on page 5 undefined on input line 5 +7. + + +Package natbib Warning: Citation `asatryanpeichl2017' on page 5 undefined on in +put line 57. + + +Package natbib Warning: Citation `nandiwarwick2020' on page 5 undefined on inpu +t line 57. + + +Package natbib Warning: Citation `blomquistetal2021' on page 5 undefined on inp +ut line 59. + + +Package natbib Warning: Citation `bertanhaetal2023' on page 5 undefined on inpu +t line 59. + + +Package natbib Warning: Citation `garicano2016' on page 5 undefined on input li +ne 59. + + +Package natbib Warning: Citation `gourioroys2014' on page 5 undefined on input +line 59. + + +LaTeX Warning: Reference `sec:model' on page 5 undefined on input line 63. + + +LaTeX Warning: Reference `sec:behavioural' on page 5 undefined on input line 63 +. + + +LaTeX Warning: Reference `sec:conclusion' on page 5 undefined on input line 63. + + +) (./Sections/background.tex [5] + +Package natbib Warning: Citation `liuetal2021' on page 6 undefined on input lin +e 13. + + +Package natbib Warning: Citation `klevenwaseem2013' on page 6 undefined on inpu +t line 13. + + +LaTeX Warning: Reference `sec:model' on page 6 undefined on input line 21. + + +Package natbib Warning: Citation `liuetal2021' on page 6 undefined on input lin +e 24. + + +Package natbib Warning: Citation `hmrc_threshold' on page 6 undefined on input +line 35. + + +Package natbib Warning: Citation `hoc_vat' on page 6 undefined on input line 35 +. + +[6] + +Package natbib Warning: Citation `hmrc_threshold' on page 7 undefined on input +line 57. + + +Package natbib Warning: Citation `ots2017vat' on page 7 undefined on input line + 67. + + +Package natbib Warning: Citation `hmt2018cfe' on page 7 undefined on input line + 70. + + +Package natbib Warning: Citation `eudirective2020285' on page 7 undefined on in +put line 73. + +) (./Sections/data.tex + +Package natbib Warning: Citation `policyengine' on page 7 undefined on input li +ne 10. + + +LaTeX Warning: Reference `app:data' on page 7 undefined on input line 12. + + +Overfull \hbox (0.61864pt too wide) in paragraph at lines 4--16 +\TU/KpRoman(1)/m/n/12 Study-ing firm re-sponses at the thresh-old needs firm-le +vel turnover near the cut-off, which +[7<./figures/obr_vat_bunching_85k.png>] + +LaTeX Warning: Reference `app:data' on page 8 undefined on input line 20. + + +Overfull \hbox (0.3166pt too wide) in paragraph at lines 60--64 +[]\TU/KpRoman(1)/m/n/12 The base pop-u-la-tion re-pro-duces the ONS struc-ture +but not the HMRC VAT-registered +[8] + +LaTeX Warning: Reference `app:data' on page 9 undefined on input line 107. + + +Package natbib Warning: Citation `obr2023vat' on page 9 undefined on input line + 123. + + +Package natbib Warning: Citation `liuetal2021' on page 9 undefined on input lin +e 123. + + +LaTeX Warning: Reference `sec:behavioural' on page 9 undefined on input line 13 +3. + + +Overfull \hbox (14.26959pt too wide) in paragraph at lines 112--134 +\TU/KpRoman(1)/m/n/12 statu-tory thresh-old was £85,000. The HMRC band tar-get +s step down across the threshold--- +[9]) (./Sections/static.tex [10<./figures/turnover_distribution_85k.png>] + +Package natbib Warning: Citation `liuetal2021' on page 11 undefined on input li +ne 17. + + +LaTeX Warning: Reference `sec:behavioural' on page 11 undefined on input line 2 +9. + + +Package natbib Warning: Citation `hmt_spring_budget_2024' on page 11 undefined +on input line 52. + + +Package natbib Warning: Citation `liuetal2021' on page 11 undefined on input li +ne 65. + +[11] + +LaTeX Warning: Reference `sec:behavioural' on page 12 undefined on input line 1 +13. + +[12<./figures/vat_threshold_revenue_impact.png>] +Overfull \hbox (13.10669pt too wide) in paragraph at lines 164--178 +\TU/KpRoman(1)/m/n/12 The thresh-old sweep above moves the \TU/KpRoman(1)/m/it/ +12 lo-ca-tion \TU/KpRoman(1)/m/n/12 of a sin-gle cut-off. The same static princ +iple--- +[13] + +LaTeX Warning: Reference `sec:model' on page 14 undefined on input line 189. + + +LaTeX Warning: Reference `sec:conclusion' on page 14 undefined on input line 19 +2. + +[14<./figures/revenue_impact_2025_26.png><./figures/firms_impact_2025_26.png>] + +LaTeX Warning: Reference `sec:behavioural' on page 15 undefined on input line 2 +28. + + +LaTeX Warning: Reference `sec:model' on page 15 undefined on input line 233. + +) (./Sections/bunching.tex + +Package natbib Warning: Citation `chettyetal2011' on page 15 undefined on input + line 5. + + +Package natbib Warning: Citation `klevenwaseem2013' on page 15 undefined on inp +ut line 5. + + +Package natbib Warning: Citation `liuetal2021' on page 15 undefined on input li +ne 6. + + +Package natbib Warning: Citation `liuetal2021' on page 15 undefined on input li +ne 17. + +[15] + +Package natbib Warning: Citation `liuetal2021' on page 16 undefined on input li +ne 38. + + +LaTeX Warning: Reference `app:inference' on page 16 undefined on input line 53. + + + +Package natbib Warning: Citation `blomquistetal2021' on page 16 undefined on in +put line 68. + + +Package natbib Warning: Citation `bertanhaetal2023' on page 16 undefined on inp +ut line 68. + + +Overfull \hbox (25.36118pt too wide) in paragraph at lines 59--70 +\TU/KpRoman(1)/m/n/12 the ap-prox-i-ma-tion hold-ing when $\TU/KpMath-Regular.o +tf(1)/m/n/12 𝑔$ \TU/KpRoman(1)/m/n/12 is lo-cally smooth. The bunch-ing ra-t +io $\TU/KpMath-Regular.otf(1)/m/n/12 𝑏(𝑦[]) = 𝐵(𝑦[])/𝑔(𝑦[]) +≈ +[16] + +Package natbib Warning: Citation `liuetal2021' on page 17 undefined on input li +ne 85. + + +LaTeX Warning: Reference `fig:bunch85' on page 17 undefined on input line 90. + +[17<./figures/bunching_analysis_85k.png><./figures/bunching_analysis_90k.png>] + +Package natbib Warning: Citation `liuetal2021' on page 18 undefined on input li +ne 165. + + +Package natbib Warning: Citation `obr2023vat' on page 18 undefined on input lin +e 180. + +[18] + +LaTeX Warning: Reference `sec:model' on page 19 undefined on input line 193. + + +LaTeX Warning: Reference `sec:behavioural' on page 19 undefined on input line 1 +99. + +) (./Sections/model.tex + +Package natbib Warning: Citation `liuetal2021' on page 19 undefined on input li +ne 5. + + +Package natbib Warning: Citation `klevenwaseem2013' on page 19 undefined on inp +ut line 9. + + +Package natbib Warning: Citation `saez2010' on page 19 undefined on input line +9. + + +Package natbib Warning: Citation `kleven2016' on page 19 undefined on input lin +e 10. + + +Package natbib Warning: Citation `liuetal2021' on page 19 undefined on input li +ne 10. + + +LaTeX Warning: Reference `ssec:dominated' on page 19 undefined on input line 16 +. + + +LaTeX Warning: Reference `sec:behavioural' on page 19 undefined on input line 1 +8. + + +Package natbib Warning: Citation `liuetal2021' on page 19 undefined on input li +ne 25. + + +Overfull \hbox (9.26462pt too wide) in paragraph at lines 22--29 +\TU/KpRoman(1)/m/n/12 Two pop-u-la-tions are out-side its scope and are treated + as such through-out: below-threshold +[19] + +LaTeX Warning: Reference `eq:firm-problem' on page 20 undefined on input line 5 +6. + + +Package natbib Warning: Citation `klevenwaseem2013' on page 20 undefined on inp +ut line 77. + + +LaTeX Warning: Reference `fig:notch_fit' on page 20 undefined on input line 81. + + + +Overfull \hbox (15.01466pt too wide) in paragraph at lines 76--82 +\TU/KpMath-Regular.otf(1)/m/n/12 £85[]000 × 0.20/0.80 = £21[]250$\TU/KpRoman +(1)/m/n/12 , so the dom-i-nated re-gion is $\TU/KpMath-Regular.otf(1)/m/n/12 ( +𝑇[], 𝑇[] + 𝑎) = (£85[]000, £106[]250)$\TU/KpRoman(1)/m/n/12 , +[20] + +LaTeX Warning: Reference `sec:behavioural' on page 21 undefined on input line 1 +12. + + +LaTeX Warning: Reference `sec:behavioural' on page 21 undefined on input line 1 +12. + + +LaTeX Warning: Reference `eq:dominated' on page 21 undefined on input line 120. + + + +LaTeX Warning: Reference `eq:dominated-secondary' on page 21 undefined on input + line 120. + + +LaTeX Warning: Reference `sec:conclusion' on page 21 undefined on input line 15 +9. + +) (./Sections/behavioural.tex +Overfull \hbox (8.2552pt too wide) in paragraph at lines 139--1 +\TU/KpMath-Regular.otf(1)/m/n/12 (𝜏 − 𝑟) 𝑇[] = £5[]250$\TU/KpRoman( +1)/m/n/12 . The firm counts con-firm this (\TU/KpMono(0)/m/n/12 results/dominat +ed_region_mass.txt\TU/KpRoman(1)/m/n/12 ): +[21] [22<./figures/dynamic_notch_fit_e017.png>] + +LaTeX Warning: Reference `sec:model' on page 23 undefined on input line 8. + + +Package natbib Warning: Citation `klevenwaseem2013' on page 23 undefined on inp +ut line 23. + + +Package natbib Warning: Citation `saez2010' on page 23 undefined on input line +24. + + +Package natbib Warning: Citation `liuetal2021' on page 23 undefined on input li +ne 25. + +[23] + +LaTeX Warning: Reference `fig:formulation_a_optima' on page 24 undefined on inp +ut line 59. + + +LaTeX Warning: Reference `eq:isoelastic' on page 24 undefined on input line 72. + + + +LaTeX Warning: Reference `eq:isoelastic' on page 24 undefined on input line 72. + + + +LaTeX Warning: Reference `eq:flat-optimum' on page 24 undefined on input line 7 +9. + + +Overfull \hbox (0.45064pt too wide) in paragraph at lines 76--83 +\TU/KpRoman(1)/m/n/12 firm’s op-ti-mal turnover un-der a coun-ter-fac-tual sc +hed-ule, \TU/KpRoman(1)/m/it/12 given \TU/KpRoman(1)/m/n/12 that its ob-served +turnover + +Overfull \hbox (2.70668pt too wide) in paragraph at lines 87--96 +\TU/KpRoman(1)/m/n/12 The in-ten-sive re-sponse de-pends only on $\TU/KpMath-Re +gular.otf(1)/m/n/12 𝑒$\TU/KpRoman(1)/m/n/12 , the statu-tory rate, and the s +ched-ule fractions--- +[24<./figures/formulation_a_optima.png>] + +LaTeX Warning: Reference `eq:rescale' on page 25 undefined on input line 99. + + +LaTeX Warning: Reference `sec:model' on page 25 undefined on input line 102. + + +Overfull \hbox (19.06874pt too wide) in paragraph at lines 97--117 +[]\TU/KpRoman(1)/b/n/12 Region-confined scope.[] \TU/KpRoman(1)/m/n/12 The mar- +gin priced here is purely \TU/KpRoman(1)/m/it/12 in-ten-sive\TU/KpRoman(1)/m/n/ +12 : each firm re-optimises + +Package natbib Warning: Citation `klevenwaseem2013' on page 25 undefined on inp +ut line 122. + + +Package natbib Warning: Citation `liuetal2021' on page 25 undefined on input li +ne 125. + + +LaTeX Warning: Reference `sec:model' on page 25 undefined on input line 128. + + +Overfull \hbox (1.25473pt too wide) in paragraph at lines 118--129 +[]\TU/KpRoman(1)/b/n/12 Con-di-tional on $\TU/KpMath-Regular.otf(1)/m/n/12 +𝑒$\TU/KpRoman(1)/b/n/12 .[] \TU/KpRoman(1)/m/n/12 The elas-tic-ity $\TU/KpMa +th-Regular.otf(1)/m/n/12 𝑒$ \TU/KpRoman(1)/m/n/12 is not iden-ti-fied from t +hese data, so ev-ery be-havioural + +LaTeX Warning: Reference `tab:behavioural_costs' on page 25 undefined on input +line 133. + + +LaTeX Warning: Reference `eq:rescale' on page 25 undefined on input line 152. + + +LaTeX Warning: Reference `ssec:simulator' on page 25 undefined on input line 15 +2. + + +LaTeX Warning: Reference `eq:rescale' on page 25 undefined on input line 152. + + +LaTeX Warning: Reference `ssec:simulator' on page 25 undefined on input line 15 +2. + + +Overfull \hbox (34.0586pt too wide) in paragraph at lines 154--166 + [][] + +LaTeX Warning: Reference `sec:model' on page 25 undefined on input line 173. + + +LaTeX Warning: Reference `eq:rescale' on page 25 undefined on input line 182. + +[25] + +LaTeX Warning: Reference `eq:rescale' on page 26 undefined on input line 198. + + +LaTeX Warning: Reference `fig:reform_dist' on page 26 undefined on input line 2 +04. + + +LaTeX Warning: Reference `ssec:simulator' on page 26 undefined on input line 22 +7. + + +LaTeX Warning: Reference `ssec:simulator' on page 26 undefined on input line 22 +7. + + +LaTeX Warning: Reference `sec:model' on page 26 undefined on input line 233. + +) (./Sections/conclusion.tex [26] [27<./figures/dynamic_cost_vs_elasticity.png> +] + +Package natbib Warning: Citation `garicano2016' on page 28 undefined on input l +ine 8. + + +Package natbib Warning: Citation `gourioroys2014' on page 28 undefined on input + line 9. + + +LaTeX Warning: Reference `tab:summary' on page 28 undefined on input line 12. + + +Overfull \hbox (20.66867pt too wide) in paragraph at lines 4--13 +\TU/KpRoman(1)/m/n/12 the UK VAT reg-is-tra-tion thresh-old, re-leased in full- +--including its synthetic-data generator--- + +LaTeX Warning: Reference `ssec:dominated' on page 28 undefined on input line 29 +. + + +LaTeX Warning: Reference `ssec:dominated' on page 28 undefined on input line 30 +. + + +LaTeX Warning: Reference `sec:behavioural' on page 28 undefined on input line 3 +1. + + +Overfull \hbox (71.13858pt too wide) in paragraph at lines 23--35 + [][] + +Overfull \hbox (5.21452pt too wide) in paragraph at lines 37--48 +\TU/KpRoman(1)/m/n/12 2025--26 and the voluntary-retention con-ven-tion $\TU/Kp +Math-Regular.otf(1)/m/n/12 −$\TU/KpRoman(1)/m/n/12 £141m, against the pub-li +shed $\TU/KpMath-Regular.otf(1)/m/n/12 −$\TU/KpRoman(1)/m/n/12 £185m, + +Package natbib Warning: Citation `klevenwaseem2013' on page 28 undefined on inp +ut line 50. + +[28] + +Package natbib Warning: Citation `liuetal2021' on page 29 undefined on input li +ne 77. + + +Package natbib Warning: Citation `keenmintz2004' on page 29 undefined on input +line 104. + + +Package natbib Warning: Citation `benedek2015' on page 29 undefined on input li +ne 114. + + +Package natbib Warning: Citation `belloncopestake2022' on page 29 undefined on +input line 114. + +) [29] [30] +No file main.bbl. +(./Appendix/appendix.tex + +LaTeX Warning: Reference `app:data' on page 31 undefined on input line 5. + + +LaTeX Warning: Reference `app:inference' on page 31 undefined on input line 7. + +(./Appendix/a_data.tex +Overfull \hbox (11.12668pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion check rather than a silent re-place-ment. The snap-s +hot used here is Pol-i-cyEngine/ledger + +Overfull \hbox (30.38661pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 and max-i-mum nu-meric dif-fer-ence zero. (The ``2024--25 + vin-tage'' here de-notes the HMRC/ONS + +Overfull \hbox (3.00157pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion cal-i-brates to.) A 1,000-iteration Pop-u-lace run f +rom those tar-gets gen-er-ated 2,946,015 + +Overfull \hbox (58.07478pt too wide) in paragraph at lines 32--61 +\TU/KpMono(0)/m/n/12 firm-microsim-populace-ledger \TU/KpRoman(1)/m/n/12 and ch +ecked into \TU/KpMono(0)/m/n/12 results/populace_ledger_comparison.txt +[31] + +LaTeX Warning: Reference `app:inference' on page 32 undefined on input line 71. + + +) (./Appendix/a_inference.tex + +Package natbib Warning: Citation `liuetal2021' on page 32 undefined on input li +ne 14. + + +Package natbib Warning: Citation `blomquistetal2021' on page 32 undefined on in +put line 18. + + +Package natbib Warning: Citation `bertanhaetal2023' on page 32 undefined on inp +ut line 18. + + +Overfull \hbox (8.25868pt too wide) in paragraph at lines 4--25 +\TU/KpMono(0)/m/n/12 results/recovery_bunching.txt\TU/KpRoman(1)/m/n/12 . The e +s-ti-ma-tor re-ports the ge-om-e-try only---the bunch- + +Overfull \hbox (16.15141pt too wide) in paragraph at lines 4--25 +\TU/KpRoman(1)/m/n/12 ing ra-tio $\TU/KpMath-Regular.otf(1)/m/n/12 𝑏$\TU/KpR +oman(1)/m/n/12 , its \TU/KpRoman(1)/b/n/12 ?\TU/KpRoman(1)/m/n/12 -normalised c +oun-ter-part $\TU/KpMath-Regular.otf(1)/m/n/12 𝑏[]$\TU/KpRoman(1)/m/n/12 , t +he ex-cess mass $\TU/KpMath-Regular.otf(1)/m/n/12 𝐸$\TU/KpRoman(1)/m/n/12 , +and the mass-conservation + +Package natbib Warning: Citation `chettyetal2011' on page 32 undefined on input + line 28. + + +Package natbib Warning: Citation `klevenwaseem2013' on page 32 undefined on inp +ut line 29. + +[32] + +LaTeX Warning: Reference `tab:boot' on page 33 undefined on input line 71. + +[33] + +LaTeX Warning: Reference `tab:placebo' on page 34 undefined on input line 109. + + +LaTeX Warning: Reference `ssec:bunch-placebo' on page 34 undefined on input lin +e 109. + + +LaTeX Warning: Reference `tab:recovery' on page 34 undefined on input line 145. + + + +Underfull \hbox (badness 1845) in paragraph at lines 156--156 +[][]\TU/KpRoman(1)/b/n/12 Ta-ble A.3[][]: []|\TU/KpRoman(1)/m/n/12 Power (re-co +v-ery) test on the step-free pop-u-la-tion: Kleven--Waseem- +[34]))) + +Package natbib Warning: There were undefined citations. + +[35] (./main.aux) + +LaTeX Warning: There were undefined references. + + +LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right. + + +Package rerunfilecheck Warning: File `main.out' has changed. +(rerunfilecheck) Rerun to get outlines right +(rerunfilecheck) or use package `bookmark'. + +) +(see the transcript file for additional information) + 1044 words of node memory still in use: + 6 hlist, 2 vlist, 2 rule, 16 glue, 4 kern, 1 glyph, 117 attribute, 77 glue_s +pec, 59 attribute_list, 2 write, 1 pdf_action nodes + avail lists: 1:1,2:934,3:178,4:65,5:777,6:32,7:10169,8:70,9:368,10:28,11:735 + + +warning (pdf backend): unreferenced destination with name 'Hfootnote.2' + +warning (pdf backend): unreferenced destination with name 'Hfootnote.1' + + +Output written on main.pdf (35 pages, 2115080 bytes). +Transcript written on main.log. +Latexmk: Getting log file 'main.log' +Latexmk: Examining 'main.fls' +Latexmk: Examining 'main.log' +Latexmk: Missing bbl file 'main.bbl' in following: + No file main.bbl. +Latexmk: References changed. +Latexmk: References changed. +Latexmk: References changed. +Latexmk: Log file says output to 'main.pdf' +Latexmk: Using bibtex to make bibliography file(s). + ===Source file 'main.bbl' for 'lualatex' +Create bibtex main +Latexmk: Found bibliography file(s): + ./references.bib +Latexmk: applying rule 'bibtex main'... +Rule 'bibtex main': Reasons for rerun +Category 'other': + Rerun of 'bibtex main' forced or previously required: + Reason or flag: 'Initial set up of rule' + +------------ +Run number 1 of rule 'bibtex main' +------------ +------------ +Running 'bibtex "main.aux"' +------------ +This is BibTeX, Version 0.99e (TeX Live 2026) +The top-level auxiliary file: main.aux +The style file: econ.bst +Database file #1: references.bib +Latexmk: applying rule 'lualatex'... +Rule 'lualatex': Reasons for rerun +Changed files or newly in use/created: + main.aux + main.bbl + main.out + +------------ +Run number 2 of rule 'lualatex' +------------ +------------ +Running 'lualatex -interaction=nonstopmode -halt-on-error -recorder "main.tex"' +------------ +This is LuaHBTeX, Version 1.24.0 (TeX Live 2026) + restricted system commands enabled. +(./main.tex +LaTeX2e <2025-11-01> +L3 programming layer <2026-01-19> + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/article.cls +Document Class: article 2025/01/22 v1.4n Standard LaTeX document class +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/size12.clo)) +(./YGTemplate.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3kernel/expl3.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3backend/l3backend-luatex.def))) + (/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec-luatex.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/babel.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/locale/en/babel-english.t +ex) (/usr/local/texlive/2026/texmf-dist/tex/generic/babel-english/english.ldf)) + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/lm/t1lmr.fd)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/a4wide/a4wide.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/ntgclass/a4.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/xcolor/xcolor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/color.cfg) + +Package xcolor Warning: Package option `usenames' is obsolete and ignored on in +put line 265. + +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-def/luatex.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/mathcolor.ltx)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/dvipsnam.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphicx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/keyval.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphics.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/trig.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/graphics.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/tabularx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/array.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.sty +**************************************** +* Local config file subfigure.cfg used * +**************************************** +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/float/float.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption3.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/subcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fnpct/fnpct.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/etoolbox/etoolbox.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/infwarerr/infwarerr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/iftex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty)))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts/kpfonts.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/kpfonts-otf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/realscripts/realscripts.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpRoman.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpLight.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpSans.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMono.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-luatex. +sty (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fix-cm.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ts1enc.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsmath.sty +For additional information on amsmath, use the `?' option. +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amstext.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsgen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsbsy.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsopn.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/lualatex/lualatex-math/lualatex-math.st +y) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-table.t +ex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMath-Regular.fontsp +ec))) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/pgf.revision.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeyslibraryfil +tered.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-luatex.d +ef +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-p +df.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol. +code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigo +nometric.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.rando +m.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.compa +rison.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integ +erarithmetics.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfint.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconst +ruct.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicst +ate.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransform +ations.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathproce +ssing.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretranspare +ncy.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code. +tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-0-65.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-1-18.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/math/pgfmath.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex)) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.cod +e.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothan +dlers.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarytopaths.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplots.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgfplotssysgeneric +.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgfplotslibrary.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_loader.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryfpu.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_pgfutil-common-lists.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/luamath/pgflibrar +yluamath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code +.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructure.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructureext.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +array.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +matrix.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +shared.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +deque.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.co +de.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.da +ta.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.verb +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgflibrarypgfplot +s.surfshading.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgflibrarypgfplots +.surfshading.pgfsys-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolormap. +code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolor.cod +e.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.c +ode.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplothandle +r.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplotimage. +code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscoordprocessin +g.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.errorbars.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.markers.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.paths.code.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduledecoration +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathmorphing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathmorphing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathreplacing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathreplacing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.contourlua.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryplotmarks.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplotmar +ks.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplotstable.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.coltype.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesome.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifxetex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifluatex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-ge +neric.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-xe +luatex.tex)) (/usr/local/texlive/2026/texmf-dist/tex/latex/psfrag/psfrag.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryintersections.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryinterse +ctions.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypatterns.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibrarypattern +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +decorations.softclip.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryf +illbetween.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.decorations.softclip.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/booktabs/booktabs.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/bm.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/rotating.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ifthen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hyperref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdfescape/pdfescape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hycolor/hycolor.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/nameref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/refcount/refcount.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/gettitlestring/gettitlestring.s +ty (/usr/local/texlive/2026/texmf-dist/tex/latex/kvoptions/kvoptions.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/stringenc/stringenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/pd1enc.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/intcalc/intcalc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/puenc.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/url/url.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/bitset/bitset.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hluatex.def +(/usr/local/texlive/2026/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty + +(/usr/local/texlive/2026/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +))) (/usr/local/texlive/2026/texmf-dist/tex/latex/todonotes/todonotes.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/xkeyval/xkeyval.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkeyval.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkvutils.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypositioning.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/calc.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/natbib/natbib.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/paralist/paralist.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/multicol.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/longtable.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/multirow/multirow.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/lscape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/chngcntr/chngcntr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/footmisc/footmisc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fmtcount.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcprefix.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcnumparser.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fc-english.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime-defaults.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/threeparttable/threeparttable.sty +) (/usr/local/texlive/2026/texmf-dist/tex/latex/diagbox/diagbox.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/p2e-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/sectsty/sectsty.sty + +LaTeX Warning: Command \underbar has changed. + Check if current package is valid. + + +LaTeX Warning: Command \underline has changed. + Check if current package is valid. + +)) (./title_metadata.tex) (./main.aux) +(/usr/local/texlive/2026/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +) (/usr/local/texlive/2026/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/ltcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations-basic-d +ictionary-english.trsl) + +Package pgfplots Warning: running in backwards compatibility mode (unsuitable t +ick labels; missing features). Consider writing \pgfplotsset{compat=1.18} into +your preamble. + on input line 12. + +(./main.out) (./main.out) + +Package todonotes Warning: The length marginparwidth is less than 2cm and will +most likely cause issues with the appearance of inserted todonotes. The issue c +an be solved by adding a line like \setlength {\marginparwidth }{2cm} prior to +loading the todonotes package. on input line 12. + +(./frontmatter.tex +Overfull \hbox (8.09319pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 registration-threshold re-forms, re-leased with its sy +nthetic-data gen-er-a-tor. The thresh- +[1 +Non-PDF special ignored!{/usr/local/texlive/2026/texmf-var/fonts/map/pdftex/upd +map/pdftex.map}]) (./body.tex (./Sections/intro.tex + +Package natbib Warning: Citation `hoc_vat' on page 2 undefined on input line 3. + + + +Package natbib Warning: Citation `hmrc_threshold' on page 2 undefined on input +line 3. + + +Package natbib Warning: Citation `obr2023vat' on page 2 undefined on input line + 31. + + +Package natbib Warning: Citation `liuetal2021' on page 2 undefined on input lin +e 32. + + +Package natbib Warning: Citation `liulockwoodtam2024' on page 2 undefined on in +put line 34. + +[2<./figures/firms_by_turnover_band_85k.png><./figures/vat_firms_by_turnover_ba +nd_85k.png>] + +Package natbib Warning: Citation `liuetal2021' on page 3 undefined on input lin +e 45. + + +Package natbib Warning: Citation `hmt_spring_budget_2024' on page 3 undefined o +n input line 45. + +[3] + +Package natbib Warning: Citation `klevenwaseem2013' on page 4 undefined on inpu +t line 49. + + +Package natbib Warning: Citation `liuetal2021' on page 4 undefined on input lin +e 49. + + +Overfull \hbox (0.9187pt too wide) in paragraph at lines 49--50 +[]\TU/KpRoman(1)/m/n/12 Third, con-di-tional on the as-sumed elas-tic-ity, inte +nsive-margin re-sponses barely move + +Package natbib Warning: Citation `liuetal2021' on page 4 undefined on input lin +e 51. + +[4] + +Package natbib Warning: Citation `chettyetal2011' on page 5 undefined on input +line 55. + + +Package natbib Warning: Citation `saez2010' on page 5 undefined on input line 5 +5. + + +Package natbib Warning: Citation `klevenwaseem2013' on page 5 undefined on inpu +t line 55. + + +Package natbib Warning: Citation `kleven2016' on page 5 undefined on input line + 55. + + +Package natbib Warning: Citation `best2015' on page 5 undefined on input line 5 +5. + + +Package natbib Warning: Citation `liuetal2021' on page 5 undefined on input lin +e 57. + + +Package natbib Warning: Citation `liulockwoodtam2024' on page 5 undefined on in +put line 57. + + +Package natbib Warning: Citation `onji2009' on page 5 undefined on input line 5 +7. + + +Package natbib Warning: Citation `harju2019' on page 5 undefined on input line +57. + + +Package natbib Warning: Citation `asatryanpeichl2017' on page 5 undefined on in +put line 57. + + +Package natbib Warning: Citation `nandiwarwick2020' on page 5 undefined on inpu +t line 57. + + +Package natbib Warning: Citation `waseem2024' on page 5 undefined on input line + 57. + + +Package natbib Warning: Citation `liuetal2021' on page 5 undefined on input lin +e 57. + + +Package natbib Warning: Citation `harju2019' on page 5 undefined on input line +57. + + +Package natbib Warning: Citation `onji2009' on page 5 undefined on input line 5 +7. + + +Package natbib Warning: Citation `asatryanpeichl2017' on page 5 undefined on in +put line 57. + + +Package natbib Warning: Citation `nandiwarwick2020' on page 5 undefined on inpu +t line 57. + + +Package natbib Warning: Citation `blomquistetal2021' on page 5 undefined on inp +ut line 59. + + +Package natbib Warning: Citation `bertanhaetal2023' on page 5 undefined on inpu +t line 59. + + +Package natbib Warning: Citation `garicano2016' on page 5 undefined on input li +ne 59. + + +Package natbib Warning: Citation `gourioroys2014' on page 5 undefined on input +line 59. + +) (./Sections/background.tex [5] + +Package natbib Warning: Citation `liuetal2021' on page 6 undefined on input lin +e 13. + + +Package natbib Warning: Citation `klevenwaseem2013' on page 6 undefined on inpu +t line 13. + + +Package natbib Warning: Citation `liuetal2021' on page 6 undefined on input lin +e 24. + + +Package natbib Warning: Citation `hmrc_threshold' on page 6 undefined on input +line 35. + + +Package natbib Warning: Citation `hoc_vat' on page 6 undefined on input line 35 +. + +[6] + +Package natbib Warning: Citation `hmrc_threshold' on page 7 undefined on input +line 57. + + +Package natbib Warning: Citation `ots2017vat' on page 7 undefined on input line + 67. + + +Package natbib Warning: Citation `hmt2018cfe' on page 7 undefined on input line + 70. + + +Package natbib Warning: Citation `eudirective2020285' on page 7 undefined on in +put line 73. + +) (./Sections/data.tex + +Package natbib Warning: Citation `policyengine' on page 7 undefined on input li +ne 10. + + +Overfull \hbox (0.61864pt too wide) in paragraph at lines 4--16 +\TU/KpRoman(1)/m/n/12 Study-ing firm re-sponses at the thresh-old needs firm-le +vel turnover near the cut-off, which +[7<./figures/obr_vat_bunching_85k.png>] +Overfull \hbox (0.3166pt too wide) in paragraph at lines 60--64 +[]\TU/KpRoman(1)/m/n/12 The base pop-u-la-tion re-pro-duces the ONS struc-ture +but not the HMRC VAT-registered +[8] + +Package natbib Warning: Citation `obr2023vat' on page 9 undefined on input line + 123. + + +Package natbib Warning: Citation `liuetal2021' on page 9 undefined on input lin +e 123. + + +Overfull \hbox (14.26959pt too wide) in paragraph at lines 112--134 +\TU/KpRoman(1)/m/n/12 statu-tory thresh-old was £85,000. The HMRC band tar-get +s step down across the threshold--- +[9]) (./Sections/static.tex [10<./figures/turnover_distribution_85k.png>] + +Package natbib Warning: Citation `liuetal2021' on page 11 undefined on input li +ne 17. + + +Package natbib Warning: Citation `hmt_spring_budget_2024' on page 11 undefined +on input line 52. + + +Package natbib Warning: Citation `liuetal2021' on page 11 undefined on input li +ne 65. + +[11] [12<./figures/vat_threshold_revenue_impact.png>] +Overfull \hbox (13.10669pt too wide) in paragraph at lines 164--178 +\TU/KpRoman(1)/m/n/12 The thresh-old sweep above moves the \TU/KpRoman(1)/m/it/ +12 lo-ca-tion \TU/KpRoman(1)/m/n/12 of a sin-gle cut-off. The same static princ +iple--- +[13] [14<./figures/revenue_impact_2025_26.png><./figures/firms_impact_2025_26.p +ng>]) (./Sections/bunching.tex + +Package natbib Warning: Citation `chettyetal2011' on page 15 undefined on input + line 5. + + +Package natbib Warning: Citation `klevenwaseem2013' on page 15 undefined on inp +ut line 5. + + +Package natbib Warning: Citation `liuetal2021' on page 15 undefined on input li +ne 6. + + +Package natbib Warning: Citation `liuetal2021' on page 15 undefined on input li +ne 17. + +[15] + +Package natbib Warning: Citation `liuetal2021' on page 16 undefined on input li +ne 38. + + +Package natbib Warning: Citation `blomquistetal2021' on page 16 undefined on in +put line 68. + + +Package natbib Warning: Citation `bertanhaetal2023' on page 16 undefined on inp +ut line 68. + + +Overfull \hbox (25.36118pt too wide) in paragraph at lines 59--70 +\TU/KpRoman(1)/m/n/12 the ap-prox-i-ma-tion hold-ing when $\TU/KpMath-Regular.o +tf(1)/m/n/12 𝑔$ \TU/KpRoman(1)/m/n/12 is lo-cally smooth. The bunch-ing ra-t +io $\TU/KpMath-Regular.otf(1)/m/n/12 𝑏(𝑦[]) = 𝐵(𝑦[])/𝑔(𝑦[]) +≈ +[16] + +Package natbib Warning: Citation `liuetal2021' on page 17 undefined on input li +ne 85. + +[17<./figures/bunching_analysis_85k.png><./figures/bunching_analysis_90k.png>] + +Package natbib Warning: Citation `liuetal2021' on page 18 undefined on input li +ne 165. + + +Package natbib Warning: Citation `obr2023vat' on page 18 undefined on input lin +e 180. + +[18]) (./Sections/model.tex + +Package natbib Warning: Citation `liuetal2021' on page 19 undefined on input li +ne 5. + + +Package natbib Warning: Citation `klevenwaseem2013' on page 19 undefined on inp +ut line 9. + + +Package natbib Warning: Citation `saez2010' on page 19 undefined on input line +9. + + +Package natbib Warning: Citation `kleven2016' on page 19 undefined on input lin +e 10. + + +Package natbib Warning: Citation `liuetal2021' on page 19 undefined on input li +ne 10. + + +Package natbib Warning: Citation `liuetal2021' on page 19 undefined on input li +ne 25. + + +Overfull \hbox (9.26462pt too wide) in paragraph at lines 22--29 +\TU/KpRoman(1)/m/n/12 Two pop-u-la-tions are out-side its scope and are treated + as such through-out: below-threshold +[19] + +Package natbib Warning: Citation `klevenwaseem2013' on page 20 undefined on inp +ut line 77. + + +Overfull \hbox (15.01466pt too wide) in paragraph at lines 76--82 +\TU/KpMath-Regular.otf(1)/m/n/12 £85[]000 × 0.20/0.80 = £21[]250$\TU/KpRoman +(1)/m/n/12 , so the dom-i-nated re-gion is $\TU/KpMath-Regular.otf(1)/m/n/12 ( +𝑇[], 𝑇[] + 𝑎) = (£85[]000, £106[]250)$\TU/KpRoman(1)/m/n/12 , +[20]) (./Sections/behavioural.tex +Overfull \hbox (8.2552pt too wide) in paragraph at lines 139--1 +\TU/KpMath-Regular.otf(1)/m/n/12 (𝜏 − 𝑟) 𝑇[] = £5[]250$\TU/KpRoman( +1)/m/n/12 . The firm counts con-firm this (\TU/KpMono(0)/m/n/12 results/dominat +ed_region_mass.txt\TU/KpRoman(1)/m/n/12 ): +[21] [22<./figures/dynamic_notch_fit_e017.png>] + +Package natbib Warning: Citation `klevenwaseem2013' on page 23 undefined on inp +ut line 23. + + +Package natbib Warning: Citation `saez2010' on page 23 undefined on input line +24. + + +Package natbib Warning: Citation `liuetal2021' on page 23 undefined on input li +ne 25. + +[23] +Overfull \hbox (0.45064pt too wide) in paragraph at lines 76--83 +\TU/KpRoman(1)/m/n/12 firm’s op-ti-mal turnover un-der a coun-ter-fac-tual sc +hed-ule, \TU/KpRoman(1)/m/it/12 given \TU/KpRoman(1)/m/n/12 that its ob-served +turnover + +Overfull \hbox (2.70668pt too wide) in paragraph at lines 87--96 +\TU/KpRoman(1)/m/n/12 The in-ten-sive re-sponse de-pends only on $\TU/KpMath-Re +gular.otf(1)/m/n/12 𝑒$\TU/KpRoman(1)/m/n/12 , the statu-tory rate, and the s +ched-ule fractions--- +[24<./figures/formulation_a_optima.png>] +Overfull \hbox (19.06874pt too wide) in paragraph at lines 97--117 +[]\TU/KpRoman(1)/b/n/12 Region-confined scope.[] \TU/KpRoman(1)/m/n/12 The mar- +gin priced here is purely \TU/KpRoman(1)/m/it/12 in-ten-sive\TU/KpRoman(1)/m/n/ +12 : each firm re-optimises + +Package natbib Warning: Citation `klevenwaseem2013' on page 25 undefined on inp +ut line 122. + + +Package natbib Warning: Citation `liuetal2021' on page 25 undefined on input li +ne 125. + + +Overfull \hbox (1.25473pt too wide) in paragraph at lines 118--129 +[]\TU/KpRoman(1)/b/n/12 Con-di-tional on $\TU/KpMath-Regular.otf(1)/m/n/12 +𝑒$\TU/KpRoman(1)/b/n/12 .[] \TU/KpRoman(1)/m/n/12 The elas-tic-ity $\TU/KpMa +th-Regular.otf(1)/m/n/12 𝑒$ \TU/KpRoman(1)/m/n/12 is not iden-ti-fied from t +hese data, so ev-ery be-havioural + +Overfull \hbox (34.0586pt too wide) in paragraph at lines 154--166 + [][] +[25]) (./Sections/conclusion.tex [26] [27<./figures/dynamic_cost_vs_elasticity. +png>] + +Package natbib Warning: Citation `garicano2016' on page 28 undefined on input l +ine 8. + + +Package natbib Warning: Citation `gourioroys2014' on page 28 undefined on input + line 9. + + +Overfull \hbox (20.66867pt too wide) in paragraph at lines 4--13 +\TU/KpRoman(1)/m/n/12 the UK VAT reg-is-tra-tion thresh-old, re-leased in full- +--including its synthetic-data generator--- + +Overfull \hbox (68.06161pt too wide) in paragraph at lines 23--35 + [][] + +Overfull \hbox (5.21452pt too wide) in paragraph at lines 37--48 +\TU/KpRoman(1)/m/n/12 2025--26 and the voluntary-retention con-ven-tion $\TU/Kp +Math-Regular.otf(1)/m/n/12 −$\TU/KpRoman(1)/m/n/12 £141m, against the pub-li +shed $\TU/KpMath-Regular.otf(1)/m/n/12 −$\TU/KpRoman(1)/m/n/12 £185m, + +Package natbib Warning: Citation `klevenwaseem2013' on page 28 undefined on inp +ut line 50. + +[28] + +Package natbib Warning: Citation `liuetal2021' on page 29 undefined on input li +ne 77. + + +Package natbib Warning: Citation `keenmintz2004' on page 29 undefined on input +line 104. + + +Package natbib Warning: Citation `benedek2015' on page 29 undefined on input li +ne 114. + + +Package natbib Warning: Citation `belloncopestake2022' on page 29 undefined on +input line 114. + +) [29] [30] (./main.bbl +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +[]\TU/KpRoman(1)/m/n/10.95 HM Rev-enue and Cus-toms (2024) ``In-creas-ing the V +AT Reg-is-tra-tion Thresh-old,'' + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpRoman(1)/m/n/10.95 Tax in-for-ma-tion and im-pact note, GOV.UK, [][]$\TU/ +KpMono(0)/m/n/10.95 https://www.gov.uk/government/ + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpMono(0)/m/n/10.95 publications/vat-[]increasing-[]the-[]registration-[]an +d-[]deregistration-[]thresholds/ +[31] +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +[]\TU/KpRoman(1)/m/n/10.95 HM Trea-sury (2018) ``VAT Reg-is-tra-tion Thresh-old +: Call for Ev-i-dence,'' HM + +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +\TU/KpRoman(1)/m/n/10.95 Trea-sury, March 2018, [][]$\TU/KpMono(0)/m/n/10.95 ht +tps://www.gov.uk/government/consultations/ + +Underfull \hbox (badness 7869) in paragraph at lines 106--109 +[] [] \TU/KpRoman(1)/m/n/10.95 (2024) ``Spring Bud-get 2024: Pol-icy Cost-ings, +'' HM Trea-sury, March 2024, + +Underfull \hbox (badness 10000) in paragraph at lines 106--109 +[][]$\TU/KpMono(0)/m/n/10.95 https://assets.publishing.service.gov.uk/media/65e +7920c08eef600155a5617/ + +Underfull \hbox (badness 4886) in paragraph at lines 133--137 +[]\TU/KpRoman(1)/m/n/10.95 Liu, Li, Ben Lock-wood, and Eddy H. F. Tam (2024) `` +Small Firm Growth and the + +Underfull \hbox (badness 2865) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 VAT Thresh-old: Ev-i-dence for the UK,'' IMF Work-ing +Pa-perWP/24/33, In-ter-na-tional + +Underfull \hbox (badness 10000) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 Mon-e-tary Fund, [][]$\TU/KpMono(0)/m/n/10.95 https:// +www.imf.org/en/publications/wp/issues/2024/02/16/ + +Underfull \hbox (badness 1490) in paragraph at lines 139--143 +\TU/KpRoman(1)/m/n/10.95 West Ben-gal, In-dia,'' TaxDev / In-sti-tute for Fis-c +al Stud-ies, [][]$\TU/KpMono(0)/m/n/10.95 https://www.taxdev.org/ + +Underfull \hbox (badness 10000) in paragraph at lines 146--149 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice for Bud-get Re-spon-si-bil-ity (2023) ``The +Im-pact of the Frozen VAT Reg-is-tra- + +Underfull \hbox (badness 4886) in paragraph at lines 146--149 +\TU/KpRoman(1)/m/n/10.95 tion Thresh-old,'' Eco-nomic and Fis-cal Out-look, Mar +ch 2023, [][]$\TU/KpMono(0)/m/n/10.95 https://obr.uk/box/ + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice of Tax Sim-pli-fi-ca-tion (2017) ``Value Add +ed Tax: Routes to Sim-pli-fi-ca-tion,'' + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +\TU/KpRoman(1)/m/n/10.95 OTS re-port, Novem-ber 2017, [][]$\TU/KpMono(0)/m/n/10 +.95 https://assets.publishing.service.gov.uk/media/ +[32]) [33] (./Appendix/appendix.tex (./Appendix/a_data.tex +Overfull \hbox (11.12668pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion check rather than a silent re-place-ment. The snap-s +hot used here is Pol-i-cyEngine/ledger + +Overfull \hbox (30.38661pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 and max-i-mum nu-meric dif-fer-ence zero. (The ``2024--25 + vin-tage'' here de-notes the HMRC/ONS + +Overfull \hbox (3.00157pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion cal-i-brates to.) A 1,000-iteration Pop-u-lace run f +rom those tar-gets gen-er-ated 2,946,015 + +Overfull \hbox (58.07478pt too wide) in paragraph at lines 32--61 +\TU/KpMono(0)/m/n/12 firm-microsim-populace-ledger \TU/KpRoman(1)/m/n/12 and ch +ecked into \TU/KpMono(0)/m/n/12 results/populace_ledger_comparison.txt +[34]) (./Appendix/a_inference.tex + +Package natbib Warning: Citation `liuetal2021' on page 35 undefined on input li +ne 14. + + +Package natbib Warning: Citation `blomquistetal2021' on page 35 undefined on in +put line 18. + + +Package natbib Warning: Citation `bertanhaetal2023' on page 35 undefined on inp +ut line 18. + + +Overfull \hbox (8.25868pt too wide) in paragraph at lines 4--25 +\TU/KpMono(0)/m/n/12 results/recovery_bunching.txt\TU/KpRoman(1)/m/n/12 . The e +s-ti-ma-tor re-ports the ge-om-e-try only---the bunch- + +Overfull \hbox (16.15141pt too wide) in paragraph at lines 4--25 +\TU/KpRoman(1)/m/n/12 ing ra-tio $\TU/KpMath-Regular.otf(1)/m/n/12 𝑏$\TU/KpR +oman(1)/m/n/12 , its \TU/KpRoman(1)/b/n/12 ?\TU/KpRoman(1)/m/n/12 -normalised c +oun-ter-part $\TU/KpMath-Regular.otf(1)/m/n/12 𝑏[]$\TU/KpRoman(1)/m/n/12 , t +he ex-cess mass $\TU/KpMath-Regular.otf(1)/m/n/12 𝐸$\TU/KpRoman(1)/m/n/12 , +and the mass-conservation + +Package natbib Warning: Citation `chettyetal2011' on page 35 undefined on input + line 28. + + +Package natbib Warning: Citation `klevenwaseem2013' on page 35 undefined on inp +ut line 29. + +[35] [36] +Underfull \hbox (badness 1845) in paragraph at lines 156--156 +[][]\TU/KpRoman(1)/b/n/12 Ta-ble A.3[][]: []|\TU/KpRoman(1)/m/n/12 Power (re-co +v-ery) test on the step-free pop-u-la-tion: Kleven--Waseem- +[37]))) + +Package natbib Warning: There were undefined citations. + +[38] (./main.aux + +Package natbib Warning: Citation(s) may have changed. +(natbib) Rerun to get citations correct. + +) + +LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right. + +) +(see the transcript file for additional information) + 1248 words of node memory still in use: + 6 hlist, 2 vlist, 2 rule, 16 glue, 4 kern, 1 glyph, 151 attribute, 77 glue_s +pec, 76 attribute_list, 2 write, 18 pdf_action nodes + avail lists: 1:1,2:883,3:445,4:110,5:778,6:28,7:10161,8:146,9:368,10:28,11:7 +35 + +warning (pdf backend): unreferenced destination with name 'table.caption.45' + +warning (pdf backend): unreferenced destination with name 'table.caption.43' + +warning (pdf backend): unreferenced destination with name 'table.caption.40' + +warning (pdf backend): unreferenced destination with name 'Hfootnote.2' + +warning (pdf backend): unreferenced destination with name 'Hfootnote.1' + + +Output written on main.pdf (38 pages, 2132531 bytes). +Transcript written on main.log. +Latexmk: Getting log file 'main.log' +Latexmk: Examining 'main.fls' +Latexmk: Examining 'main.log' +Latexmk: Found input bbl file 'main.bbl' +Latexmk: References changed. +Latexmk: References changed. +Latexmk: References changed. +Latexmk: Log file says output to 'main.pdf' +Latexmk: Using bibtex to make bibliography file(s). + ===Source file 'main.bbl' for 'lualatex' +Latexmk: Found bibliography file(s): + ./references.bib +Latexmk: applying rule 'bibtex main'... +Rule 'bibtex main': Reasons for rerun +Changed files or newly in use/created: + main.aux + +------------ +Run number 2 of rule 'bibtex main' +------------ +------------ +Running 'bibtex "main.aux"' +------------ +This is BibTeX, Version 0.99e (TeX Live 2026) +The top-level auxiliary file: main.aux +The style file: econ.bst +Database file #1: references.bib +Latexmk: applying rule 'lualatex'... +Rule 'lualatex': Reasons for rerun +Changed files or newly in use/created: + main.aux + +------------ +Run number 3 of rule 'lualatex' +------------ +------------ +Running 'lualatex -interaction=nonstopmode -halt-on-error -recorder "main.tex"' +------------ +This is LuaHBTeX, Version 1.24.0 (TeX Live 2026) + restricted system commands enabled. +(./main.tex +LaTeX2e <2025-11-01> +L3 programming layer <2026-01-19> + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/article.cls +Document Class: article 2025/01/22 v1.4n Standard LaTeX document class +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/size12.clo)) +(./YGTemplate.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3kernel/expl3.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3backend/l3backend-luatex.def))) + (/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec-luatex.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/babel.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/locale/en/babel-english.t +ex) (/usr/local/texlive/2026/texmf-dist/tex/generic/babel-english/english.ldf)) + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/lm/t1lmr.fd)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/a4wide/a4wide.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/ntgclass/a4.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/xcolor/xcolor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/color.cfg) + +Package xcolor Warning: Package option `usenames' is obsolete and ignored on in +put line 265. + +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-def/luatex.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/mathcolor.ltx)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/dvipsnam.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphicx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/keyval.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphics.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/trig.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/graphics.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/tabularx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/array.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.sty +**************************************** +* Local config file subfigure.cfg used * +**************************************** +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/float/float.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption3.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/subcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fnpct/fnpct.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/etoolbox/etoolbox.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/infwarerr/infwarerr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/iftex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty)))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts/kpfonts.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/kpfonts-otf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/realscripts/realscripts.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpRoman.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpLight.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpSans.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMono.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-luatex. +sty (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fix-cm.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ts1enc.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsmath.sty +For additional information on amsmath, use the `?' option. +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amstext.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsgen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsbsy.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsopn.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/lualatex/lualatex-math/lualatex-math.st +y) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-table.t +ex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMath-Regular.fontsp +ec))) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/pgf.revision.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeyslibraryfil +tered.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-luatex.d +ef +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-p +df.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol. +code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigo +nometric.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.rando +m.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.compa +rison.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integ +erarithmetics.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfint.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconst +ruct.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicst +ate.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransform +ations.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathproce +ssing.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretranspare +ncy.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code. +tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-0-65.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-1-18.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/math/pgfmath.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex)) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.cod +e.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothan +dlers.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarytopaths.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplots.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgfplotssysgeneric +.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgfplotslibrary.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_loader.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryfpu.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_pgfutil-common-lists.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/luamath/pgflibrar +yluamath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code +.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructure.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructureext.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +array.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +matrix.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +shared.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +deque.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.co +de.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.da +ta.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.verb +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgflibrarypgfplot +s.surfshading.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgflibrarypgfplots +.surfshading.pgfsys-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolormap. +code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolor.cod +e.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.c +ode.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplothandle +r.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplotimage. +code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscoordprocessin +g.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.errorbars.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.markers.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.paths.code.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduledecoration +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathmorphing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathmorphing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathreplacing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathreplacing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.contourlua.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryplotmarks.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplotmar +ks.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplotstable.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.coltype.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesome.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifxetex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifluatex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-ge +neric.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-xe +luatex.tex)) (/usr/local/texlive/2026/texmf-dist/tex/latex/psfrag/psfrag.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryintersections.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryinterse +ctions.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypatterns.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibrarypattern +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +decorations.softclip.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryf +illbetween.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.decorations.softclip.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/booktabs/booktabs.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/bm.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/rotating.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ifthen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hyperref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdfescape/pdfescape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hycolor/hycolor.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/nameref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/refcount/refcount.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/gettitlestring/gettitlestring.s +ty (/usr/local/texlive/2026/texmf-dist/tex/latex/kvoptions/kvoptions.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/stringenc/stringenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/pd1enc.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/intcalc/intcalc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/puenc.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/url/url.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/bitset/bitset.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hluatex.def +(/usr/local/texlive/2026/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty + +(/usr/local/texlive/2026/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +))) (/usr/local/texlive/2026/texmf-dist/tex/latex/todonotes/todonotes.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/xkeyval/xkeyval.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkeyval.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkvutils.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypositioning.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/calc.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/natbib/natbib.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/paralist/paralist.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/multicol.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/longtable.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/multirow/multirow.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/lscape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/chngcntr/chngcntr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/footmisc/footmisc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fmtcount.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcprefix.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcnumparser.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fc-english.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime-defaults.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/threeparttable/threeparttable.sty +) (/usr/local/texlive/2026/texmf-dist/tex/latex/diagbox/diagbox.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/p2e-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/sectsty/sectsty.sty + +LaTeX Warning: Command \underbar has changed. + Check if current package is valid. + + +LaTeX Warning: Command \underline has changed. + Check if current package is valid. + +)) (./title_metadata.tex) (./main.aux) +(/usr/local/texlive/2026/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +) (/usr/local/texlive/2026/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/ltcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations-basic-d +ictionary-english.trsl) + +Package pgfplots Warning: running in backwards compatibility mode (unsuitable t +ick labels; missing features). Consider writing \pgfplotsset{compat=1.18} into +your preamble. + on input line 12. + +(./main.out) (./main.out) + +Package todonotes Warning: The length marginparwidth is less than 2cm and will +most likely cause issues with the appearance of inserted todonotes. The issue c +an be solved by adding a line like \setlength {\marginparwidth }{2cm} prior to +loading the todonotes package. on input line 12. + +(./frontmatter.tex +Overfull \hbox (8.09319pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 registration-threshold re-forms, re-leased with its sy +nthetic-data gen-er-a-tor. The thresh- +[1 +Non-PDF special ignored!{/usr/local/texlive/2026/texmf-var/fonts/map/pdftex/upd +map/pdftex.map}]) (./body.tex (./Sections/intro.tex [2<./figures/firms_by_turno +ver_band_85k.png><./figures/vat_firms_by_turnover_band_85k.png>] [3] +Overfull \hbox (0.9187pt too wide) in paragraph at lines 49--50 +[]\TU/KpRoman(1)/m/n/12 Third, con-di-tional on the as-sumed elas-tic-ity, inte +nsive-margin re-sponses barely move +[4] [5]) (./Sections/background.tex [6]) (./Sections/data.tex [7<./figures/obr_ +vat_bunching_85k.png>] +Overfull \hbox (0.61864pt too wide) in paragraph at lines 4--16 +\TU/KpRoman(1)/m/n/12 Study-ing firm re-sponses at the thresh-old needs firm-le +vel turnover near the cut-off, which +[8] +Overfull \hbox (0.3166pt too wide) in paragraph at lines 60--64 +[]\TU/KpRoman(1)/m/n/12 The base pop-u-la-tion re-pro-duces the ONS struc-ture +but not the HMRC VAT-registered +[9] +Overfull \hbox (14.26959pt too wide) in paragraph at lines 112--134 +\TU/KpRoman(1)/m/n/12 statu-tory thresh-old was £85,000. The HMRC band tar-get +s step down across the threshold--- +) (./Sections/static.tex [10] [11<./figures/turnover_distribution_85k.png>] +[12] [13<./figures/vat_threshold_revenue_impact.png>] [14<./figures/revenue_imp +act_2025_26.png><./figures/firms_impact_2025_26.png>] +Overfull \hbox (13.10669pt too wide) in paragraph at lines 164--178 +\TU/KpRoman(1)/m/n/12 The thresh-old sweep above moves the \TU/KpRoman(1)/m/it/ +12 lo-ca-tion \TU/KpRoman(1)/m/n/12 of a sin-gle cut-off. The same static princ +iple--- +) (./Sections/bunching.tex [15] +Overfull \hbox (6.67659pt too wide) in paragraph at lines 4--18 +\TU/KpRoman(1)/m/n/12 ([][]2011[][]) and [][]Kleven and Waseem[][] ([][]2013[][ +])---as ap-plied to UK VAT data by [][]Liu et al.[][] ([][]2021[][])---to +[16] +Overfull \hbox (25.36118pt too wide) in paragraph at lines 59--70 +\TU/KpRoman(1)/m/n/12 the ap-prox-i-ma-tion hold-ing when $\TU/KpMath-Regular.o +tf(1)/m/n/12 𝑔$ \TU/KpRoman(1)/m/n/12 is lo-cally smooth. The bunch-ing ra-t +io $\TU/KpMath-Regular.otf(1)/m/n/12 𝑏(𝑦[]) = 𝐵(𝑦[])/𝑔(𝑦[]) +≈ +[17] [18<./figures/bunching_analysis_85k.png><./figures/bunching_analysis_90k.p +ng>]) (./Sections/model.tex [19] +Overfull \hbox (9.26462pt too wide) in paragraph at lines 22--29 +\TU/KpRoman(1)/m/n/12 Two pop-u-la-tions are out-side its scope and are treated + as such through-out: below-threshold +[20] [21] [22<./figures/dynamic_notch_fit_e017.png>]) +(./Sections/behavioural.tex +Overfull \hbox (8.2552pt too wide) in paragraph at lines 139--1 +\TU/KpMath-Regular.otf(1)/m/n/12 (𝜏 − 𝑟) 𝑇[] = £5[]250$\TU/KpRoman( +1)/m/n/12 . The firm counts con-firm this (\TU/KpMono(0)/m/n/12 results/dominat +ed_region_mass.txt\TU/KpRoman(1)/m/n/12 ): +[23] +Overfull \hbox (0.45064pt too wide) in paragraph at lines 76--83 +\TU/KpRoman(1)/m/n/12 firm’s op-ti-mal turnover un-der a coun-ter-fac-tual sc +hed-ule, \TU/KpRoman(1)/m/it/12 given \TU/KpRoman(1)/m/n/12 that its ob-served +turnover + +Overfull \hbox (2.70668pt too wide) in paragraph at lines 87--96 +\TU/KpRoman(1)/m/n/12 The in-ten-sive re-sponse de-pends only on $\TU/KpMath-Re +gular.otf(1)/m/n/12 𝑒$\TU/KpRoman(1)/m/n/12 , the statu-tory rate, and the s +ched-ule fractions--- + +Overfull \hbox (19.06874pt too wide) in paragraph at lines 97--117 +[]\TU/KpRoman(1)/b/n/12 Region-confined scope.[] \TU/KpRoman(1)/m/n/12 The mar- +gin priced here is purely \TU/KpRoman(1)/m/it/12 in-ten-sive\TU/KpRoman(1)/m/n/ +12 : each firm re-optimises +[24] +Overfull \hbox (1.25473pt too wide) in paragraph at lines 118--129 +[]\TU/KpRoman(1)/b/n/12 Con-di-tional on $\TU/KpMath-Regular.otf(1)/m/n/12 +𝑒$\TU/KpRoman(1)/b/n/12 .[] \TU/KpRoman(1)/m/n/12 The elas-tic-ity $\TU/KpMa +th-Regular.otf(1)/m/n/12 𝑒$ \TU/KpRoman(1)/m/n/12 is not iden-ti-fied from t +hese data, so ev-ery be-havioural +[25<./figures/formulation_a_optima.png>] +Overfull \hbox (34.0586pt too wide) in paragraph at lines 154--166 + [][] +[26]) (./Sections/conclusion.tex [27<./figures/dynamic_cost_vs_elasticity.png>] + +Overfull \hbox (20.66867pt too wide) in paragraph at lines 4--13 +\TU/KpRoman(1)/m/n/12 the UK VAT reg-is-tra-tion thresh-old, re-leased in full- +--including its synthetic-data generator--- + +Overfull \hbox (68.06161pt too wide) in paragraph at lines 23--35 + [][] + +Overfull \hbox (5.21452pt too wide) in paragraph at lines 37--48 +\TU/KpRoman(1)/m/n/12 2025--26 and the voluntary-retention con-ven-tion $\TU/Kp +Math-Regular.otf(1)/m/n/12 −$\TU/KpRoman(1)/m/n/12 £141m, against the pub-li +shed $\TU/KpMath-Regular.otf(1)/m/n/12 −$\TU/KpRoman(1)/m/n/12 £185m, +[28]) [29] [30] (./main.bbl +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +[]\TU/KpRoman(1)/m/n/10.95 HM Rev-enue and Cus-toms (2024) ``In-creas-ing the V +AT Reg-is-tra-tion Thresh-old,'' + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpRoman(1)/m/n/10.95 Tax in-for-ma-tion and im-pact note, GOV.UK, [][]$\TU/ +KpMono(0)/m/n/10.95 https://www.gov.uk/government/ + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpMono(0)/m/n/10.95 publications/vat-[]increasing-[]the-[]registration-[]an +d-[]deregistration-[]thresholds/ +[31] +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +[]\TU/KpRoman(1)/m/n/10.95 HM Trea-sury (2018) ``VAT Reg-is-tra-tion Thresh-old +: Call for Ev-i-dence,'' HM + +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +\TU/KpRoman(1)/m/n/10.95 Trea-sury, March 2018, [][]$\TU/KpMono(0)/m/n/10.95 ht +tps://www.gov.uk/government/consultations/ + +Underfull \hbox (badness 7869) in paragraph at lines 106--109 +[] [] \TU/KpRoman(1)/m/n/10.95 (2024) ``Spring Bud-get 2024: Pol-icy Cost-ings, +'' HM Trea-sury, March 2024, + +Underfull \hbox (badness 10000) in paragraph at lines 106--109 +[][]$\TU/KpMono(0)/m/n/10.95 https://assets.publishing.service.gov.uk/media/65e +7920c08eef600155a5617/ + +Underfull \hbox (badness 4886) in paragraph at lines 133--137 +[]\TU/KpRoman(1)/m/n/10.95 Liu, Li, Ben Lock-wood, and Eddy H. F. Tam (2024) `` +Small Firm Growth and the + +Underfull \hbox (badness 2865) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 VAT Thresh-old: Ev-i-dence for the UK,'' IMF Work-ing +Pa-perWP/24/33, In-ter-na-tional + +Underfull \hbox (badness 10000) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 Mon-e-tary Fund, [][]$\TU/KpMono(0)/m/n/10.95 https:// +www.imf.org/en/publications/wp/issues/2024/02/16/ + +Underfull \hbox (badness 1490) in paragraph at lines 139--143 +\TU/KpRoman(1)/m/n/10.95 West Ben-gal, In-dia,'' TaxDev / In-sti-tute for Fis-c +al Stud-ies, [][]$\TU/KpMono(0)/m/n/10.95 https://www.taxdev.org/ + +Underfull \hbox (badness 10000) in paragraph at lines 146--149 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice for Bud-get Re-spon-si-bil-ity (2023) ``The +Im-pact of the Frozen VAT Reg-is-tra- + +Underfull \hbox (badness 4886) in paragraph at lines 146--149 +\TU/KpRoman(1)/m/n/10.95 tion Thresh-old,'' Eco-nomic and Fis-cal Out-look, Mar +ch 2023, [][]$\TU/KpMono(0)/m/n/10.95 https://obr.uk/box/ + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice of Tax Sim-pli-fi-ca-tion (2017) ``Value Add +ed Tax: Routes to Sim-pli-fi-ca-tion,'' + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +\TU/KpRoman(1)/m/n/10.95 OTS re-port, Novem-ber 2017, [][]$\TU/KpMono(0)/m/n/10 +.95 https://assets.publishing.service.gov.uk/media/ +[32]) [33] (./Appendix/appendix.tex (./Appendix/a_data.tex +Overfull \hbox (11.12668pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion check rather than a silent re-place-ment. The snap-s +hot used here is Pol-i-cyEngine/ledger + +Overfull \hbox (30.38661pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 and max-i-mum nu-meric dif-fer-ence zero. (The ``2024--25 + vin-tage'' here de-notes the HMRC/ONS + +Overfull \hbox (3.00157pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion cal-i-brates to.) A 1,000-iteration Pop-u-lace run f +rom those tar-gets gen-er-ated 2,946,015 + +Overfull \hbox (58.07478pt too wide) in paragraph at lines 32--61 +\TU/KpMono(0)/m/n/12 firm-microsim-populace-ledger \TU/KpRoman(1)/m/n/12 and ch +ecked into \TU/KpMono(0)/m/n/12 results/populace_ledger_comparison.txt +[34]) (./Appendix/a_inference.tex +Overfull \hbox (8.25868pt too wide) in paragraph at lines 4--25 +\TU/KpMono(0)/m/n/12 results/recovery_bunching.txt\TU/KpRoman(1)/m/n/12 . The e +s-ti-ma-tor re-ports the ge-om-e-try only---the bunch- + +Overfull \hbox (11.25064pt too wide) in paragraph at lines 4--25 +\TU/KpRoman(1)/m/n/12 cess mass to an elas-tic-ity is not iden-ti-fied with-out + functional-form as-sump-tions ([][]Blomquist +[35] [36] [37] +Underfull \hbox (badness 1845) in paragraph at lines 156--156 +[][]\TU/KpRoman(1)/b/n/12 Ta-ble A.3[][]: []|\TU/KpRoman(1)/m/n/12 Power (re-co +v-ery) test on the step-free pop-u-la-tion: Kleven--Waseem- +))) [38] (./main.aux) + +LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right. + +) +(see the transcript file for additional information) + 1406 words of node memory still in use: + 6 hlist, 2 vlist, 2 rule, 18 glue, 4 kern, 1 glyph, 177 attribute, 77 glue_s +pec, 89 attribute_list, 2 write, 29 pdf_action nodes + avail lists: 1:1,2:966,3:445,4:197,5:776,6:27,7:10405,8:146,9:439,10:28,11:7 +27 + +warning (pdf backend): unreferenced destination with name 'Hfootnote.2' + +warning (pdf backend): unreferenced destination with name 'Hfootnote.1' + + +Output written on main.pdf (38 pages, 2141230 bytes). +Transcript written on main.log. +Latexmk: Getting log file 'main.log' +Latexmk: Examining 'main.fls' +Latexmk: Examining 'main.log' +Latexmk: Found input bbl file 'main.bbl' +Latexmk: References changed. +Latexmk: References changed. +Latexmk: Log file says output to 'main.pdf' +Latexmk: Using bibtex to make bibliography file(s). + ===Source file 'main.bbl' for 'lualatex' +Latexmk: Found bibliography file(s): + ./references.bib +Latexmk: applying rule 'bibtex main'... +Rule 'bibtex main': Reasons for rerun +Changed files or newly in use/created: + main.aux + +------------ +Run number 3 of rule 'bibtex main' +------------ +------------ +Running 'bibtex "main.aux"' +------------ +This is BibTeX, Version 0.99e (TeX Live 2026) +The top-level auxiliary file: main.aux +The style file: econ.bst +Database file #1: references.bib +Latexmk: applying rule 'lualatex'... +Rule 'lualatex': Reasons for rerun +Changed files or newly in use/created: + main.aux + +------------ +Run number 4 of rule 'lualatex' +------------ +------------ +Running 'lualatex -interaction=nonstopmode -halt-on-error -recorder "main.tex"' +------------ +This is LuaHBTeX, Version 1.24.0 (TeX Live 2026) + restricted system commands enabled. +(./main.tex +LaTeX2e <2025-11-01> +L3 programming layer <2026-01-19> + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/article.cls +Document Class: article 2025/01/22 v1.4n Standard LaTeX document class +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/size12.clo)) +(./YGTemplate.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3kernel/expl3.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3backend/l3backend-luatex.def))) + (/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec-luatex.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontspec/fontspec.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/babel.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/luababel.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/babel/locale/en/babel-english.t +ex) (/usr/local/texlive/2026/texmf-dist/tex/generic/babel-english/english.ldf)) + (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fontenc.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/lm/t1lmr.fd)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/a4wide/a4wide.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/ntgclass/a4.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/xcolor/xcolor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/color.cfg) + +Package xcolor Warning: Package option `usenames' is obsolete and ignored on in +put line 265. + +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-def/luatex.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/mathcolor.ltx)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/dvipsnam.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphicx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/keyval.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/graphics.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/trig.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics-cfg/graphics.cfg))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/tabularx.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/array.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.sty +**************************************** +* Local config file subfigure.cfg used * +**************************************** +(/usr/local/texlive/2026/texmf-dist/tex/latex/subfigure/subfigure.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/float/float.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/caption3.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/subcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fnpct/fnpct.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/etoolbox/etoolbox.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/infwarerr/infwarerr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/iftex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty)))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts/kpfonts.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/kpfonts-otf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/realscripts/realscripts.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpRoman.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpLight.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpSans.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMono.fontspec) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-luatex. +sty (/usr/local/texlive/2026/texmf-dist/tex/latex/base/fix-cm.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ts1enc.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsmath.sty +For additional information on amsmath, use the `?' option. +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amstext.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsgen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsbsy.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/amsmath/amsopn.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/lualatex/lualatex-math/lualatex-math.st +y) +(/usr/local/texlive/2026/texmf-dist/tex/latex/unicode-math/unicode-math-table.t +ex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/kpfonts-otf/KpMath-Regular.fontsp +ec))) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/pgf.revision.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeyslibraryfil +tered.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-luatex.d +ef +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-p +df.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol. +code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigo +nometric.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.rando +m.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.compa +rison.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integ +erarithmetics.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfint.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconst +ruct.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicst +ate.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransform +ations.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathproce +ssing.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.co +de.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretranspare +ncy.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns. +code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code. +tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-0-65.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-1-18.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex) +) (/usr/local/texlive/2026/texmf-dist/tex/latex/pgf/math/pgfmath.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex)) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.cod +e.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothan +dlers.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarytopaths.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplots.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscore.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgfplotssysgeneric +.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgfplotslibrary.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_loader.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryfpu.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplot +soldpgfsupp_pgfutil-common-lists.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/luamath/pgflibrar +yluamath.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code +.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructure.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +liststructureext.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +array.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +matrix.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +shared.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/liststructure/pgfplots +deque.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.co +de.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsbinary.da +ta.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.verb +.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/pgflibrarypgfplot +s.surfshading.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/sys/pgflibrarypgfplots +.surfshading.pgfsys-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolormap. +code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/util/pgfplotscolor.cod +e.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.c +ode.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.c +ode.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplothandle +r.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplotimage. +code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotscoordprocessin +g.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.errorbars.cod +e.tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.markers.code. +tex) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex +) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.paths.code.te +x) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/modules/pgfmoduledecoration +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathmorphing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathmorphing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarydecorations.pathreplacing.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/decorations/pgfli +brarydecorations.pathreplacing.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.contourlua.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryplotmarks.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryplotmar +ks.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pgfplots/pgfplotstable.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex) + +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable +.coltype.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesome.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifxetex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/iftex/ifluatex.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-ge +neric.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fontawesome/fontawesomesymbols-xe +luatex.tex)) (/usr/local/texlive/2026/texmf-dist/tex/latex/psfrag/psfrag.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibraryintersections.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibraryinterse +ctions.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypatterns.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/libraries/pgflibrarypattern +s.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +fillbetween.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrary +decorations.softclip.code.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryf +illbetween.code.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplo +ts.decorations.softclip.code.tex)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/booktabs/booktabs.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/bm.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/rotating.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/base/ifthen.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hyperref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pdfescape/pdfescape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hycolor/hycolor.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/nameref.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/refcount/refcount.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/gettitlestring/gettitlestring.s +ty (/usr/local/texlive/2026/texmf-dist/tex/latex/kvoptions/kvoptions.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/stringenc/stringenc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/pd1enc.def) +(/usr/local/texlive/2026/texmf-dist/tex/generic/intcalc/intcalc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/puenc.def) +(/usr/local/texlive/2026/texmf-dist/tex/latex/url/url.sty) +(/usr/local/texlive/2026/texmf-dist/tex/generic/bitset/bitset.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/hyperref/hluatex.def +(/usr/local/texlive/2026/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty + +(/usr/local/texlive/2026/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +))) (/usr/local/texlive/2026/texmf-dist/tex/latex/todonotes/todonotes.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/xkeyval/xkeyval.sty +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkeyval.tex +(/usr/local/texlive/2026/texmf-dist/tex/generic/xkeyval/xkvutils.tex))) +(/usr/local/texlive/2026/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarypositioning.code.tex) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/calc.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/natbib/natbib.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/paralist/paralist.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/multicol.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/tools/longtable.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/multirow/multirow.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/graphics/lscape.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/chngcntr/chngcntr.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/footmisc/footmisc.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fmtcount.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcprefix.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fcnumparser.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/fmtcount/fc-english.def)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/datetime/datetime-defaults.sty)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/threeparttable/threeparttable.sty +) (/usr/local/texlive/2026/texmf-dist/tex/latex/diagbox/diagbox.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/pict2e.cfg) +(/usr/local/texlive/2026/texmf-dist/tex/latex/pict2e/p2e-luatex.def))) +(/usr/local/texlive/2026/texmf-dist/tex/latex/sectsty/sectsty.sty + +LaTeX Warning: Command \underbar has changed. + Check if current package is valid. + + +LaTeX Warning: Command \underline has changed. + Check if current package is valid. + +)) (./title_metadata.tex) (./main.aux) +(/usr/local/texlive/2026/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +) (/usr/local/texlive/2026/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +(/usr/local/texlive/2026/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg)) +(/usr/local/texlive/2026/texmf-dist/tex/latex/caption/ltcaption.sty) +(/usr/local/texlive/2026/texmf-dist/tex/latex/translations/translations-basic-d +ictionary-english.trsl) + +Package pgfplots Warning: running in backwards compatibility mode (unsuitable t +ick labels; missing features). Consider writing \pgfplotsset{compat=1.18} into +your preamble. + on input line 12. + +(./main.out) (./main.out) + +Package todonotes Warning: The length marginparwidth is less than 2cm and will +most likely cause issues with the appearance of inserted todonotes. The issue c +an be solved by adding a line like \setlength {\marginparwidth }{2cm} prior to +loading the todonotes package. on input line 12. + +(./frontmatter.tex +Overfull \hbox (8.09319pt too wide) in paragraph at lines 4--5 +\TU/KpRoman(1)/m/n/10.95 registration-threshold re-forms, re-leased with its sy +nthetic-data gen-er-a-tor. The thresh- +[1 +Non-PDF special ignored!{/usr/local/texlive/2026/texmf-var/fonts/map/pdftex/upd +map/pdftex.map}]) (./body.tex (./Sections/intro.tex [2<./figures/firms_by_turno +ver_band_85k.png><./figures/vat_firms_by_turnover_band_85k.png>] [3] +Overfull \hbox (0.9187pt too wide) in paragraph at lines 49--50 +[]\TU/KpRoman(1)/m/n/12 Third, con-di-tional on the as-sumed elas-tic-ity, inte +nsive-margin re-sponses barely move +[4] [5]) (./Sections/background.tex [6]) (./Sections/data.tex [7<./figures/obr_ +vat_bunching_85k.png>] +Overfull \hbox (0.61864pt too wide) in paragraph at lines 4--16 +\TU/KpRoman(1)/m/n/12 Study-ing firm re-sponses at the thresh-old needs firm-le +vel turnover near the cut-off, which +[8] +Overfull \hbox (0.3166pt too wide) in paragraph at lines 60--64 +[]\TU/KpRoman(1)/m/n/12 The base pop-u-la-tion re-pro-duces the ONS struc-ture +but not the HMRC VAT-registered +[9] +Overfull \hbox (14.26959pt too wide) in paragraph at lines 112--134 +\TU/KpRoman(1)/m/n/12 statu-tory thresh-old was £85,000. The HMRC band tar-get +s step down across the threshold--- +) (./Sections/static.tex [10] [11<./figures/turnover_distribution_85k.png>] +[12] [13<./figures/vat_threshold_revenue_impact.png>] [14<./figures/revenue_imp +act_2025_26.png><./figures/firms_impact_2025_26.png>] +Overfull \hbox (13.10669pt too wide) in paragraph at lines 164--178 +\TU/KpRoman(1)/m/n/12 The thresh-old sweep above moves the \TU/KpRoman(1)/m/it/ +12 lo-ca-tion \TU/KpRoman(1)/m/n/12 of a sin-gle cut-off. The same static princ +iple--- +) (./Sections/bunching.tex [15] +Overfull \hbox (6.67659pt too wide) in paragraph at lines 4--18 +\TU/KpRoman(1)/m/n/12 ([][]2011[][]) and [][]Kleven and Waseem[][] ([][]2013[][ +])---as ap-plied to UK VAT data by [][]Liu et al.[][] ([][]2021[][])---to +[16] +Overfull \hbox (25.36118pt too wide) in paragraph at lines 59--70 +\TU/KpRoman(1)/m/n/12 the ap-prox-i-ma-tion hold-ing when $\TU/KpMath-Regular.o +tf(1)/m/n/12 𝑔$ \TU/KpRoman(1)/m/n/12 is lo-cally smooth. The bunch-ing ra-t +io $\TU/KpMath-Regular.otf(1)/m/n/12 𝑏(𝑦[]) = 𝐵(𝑦[])/𝑔(𝑦[]) +≈ +[17] [18<./figures/bunching_analysis_85k.png><./figures/bunching_analysis_90k.p +ng>]) (./Sections/model.tex [19] +Overfull \hbox (9.26462pt too wide) in paragraph at lines 22--29 +\TU/KpRoman(1)/m/n/12 Two pop-u-la-tions are out-side its scope and are treated + as such through-out: below-threshold +[20] [21] [22<./figures/dynamic_notch_fit_e017.png>]) +(./Sections/behavioural.tex +Overfull \hbox (8.2552pt too wide) in paragraph at lines 139--1 +\TU/KpMath-Regular.otf(1)/m/n/12 (𝜏 − 𝑟) 𝑇[] = £5[]250$\TU/KpRoman( +1)/m/n/12 . The firm counts con-firm this (\TU/KpMono(0)/m/n/12 results/dominat +ed_region_mass.txt\TU/KpRoman(1)/m/n/12 ): +[23] +Overfull \hbox (0.45064pt too wide) in paragraph at lines 76--83 +\TU/KpRoman(1)/m/n/12 firm’s op-ti-mal turnover un-der a coun-ter-fac-tual sc +hed-ule, \TU/KpRoman(1)/m/it/12 given \TU/KpRoman(1)/m/n/12 that its ob-served +turnover + +Overfull \hbox (2.70668pt too wide) in paragraph at lines 87--96 +\TU/KpRoman(1)/m/n/12 The in-ten-sive re-sponse de-pends only on $\TU/KpMath-Re +gular.otf(1)/m/n/12 𝑒$\TU/KpRoman(1)/m/n/12 , the statu-tory rate, and the s +ched-ule fractions--- + +Overfull \hbox (19.06874pt too wide) in paragraph at lines 97--117 +[]\TU/KpRoman(1)/b/n/12 Region-confined scope.[] \TU/KpRoman(1)/m/n/12 The mar- +gin priced here is purely \TU/KpRoman(1)/m/it/12 in-ten-sive\TU/KpRoman(1)/m/n/ +12 : each firm re-optimises +[24] +Overfull \hbox (1.25473pt too wide) in paragraph at lines 118--129 +[]\TU/KpRoman(1)/b/n/12 Con-di-tional on $\TU/KpMath-Regular.otf(1)/m/n/12 +𝑒$\TU/KpRoman(1)/b/n/12 .[] \TU/KpRoman(1)/m/n/12 The elas-tic-ity $\TU/KpMa +th-Regular.otf(1)/m/n/12 𝑒$ \TU/KpRoman(1)/m/n/12 is not iden-ti-fied from t +hese data, so ev-ery be-havioural +[25<./figures/formulation_a_optima.png>] +Overfull \hbox (34.0586pt too wide) in paragraph at lines 154--166 + [][] +[26]) (./Sections/conclusion.tex [27<./figures/dynamic_cost_vs_elasticity.png>] + +Overfull \hbox (20.66867pt too wide) in paragraph at lines 4--13 +\TU/KpRoman(1)/m/n/12 the UK VAT reg-is-tra-tion thresh-old, re-leased in full- +--including its synthetic-data generator--- + +Overfull \hbox (68.06161pt too wide) in paragraph at lines 23--35 + [][] + +Overfull \hbox (5.21452pt too wide) in paragraph at lines 37--48 +\TU/KpRoman(1)/m/n/12 2025--26 and the voluntary-retention con-ven-tion $\TU/Kp +Math-Regular.otf(1)/m/n/12 −$\TU/KpRoman(1)/m/n/12 £141m, against the pub-li +shed $\TU/KpMath-Regular.otf(1)/m/n/12 −$\TU/KpRoman(1)/m/n/12 £185m, +[28]) [29] [30] (./main.bbl +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +[]\TU/KpRoman(1)/m/n/10.95 HM Rev-enue and Cus-toms (2024) ``In-creas-ing the V +AT Reg-is-tra-tion Thresh-old,'' + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpRoman(1)/m/n/10.95 Tax in-for-ma-tion and im-pact note, GOV.UK, [][]$\TU/ +KpMono(0)/m/n/10.95 https://www.gov.uk/government/ + +Underfull \hbox (badness 10000) in paragraph at lines 96--99 +\TU/KpMono(0)/m/n/10.95 publications/vat-[]increasing-[]the-[]registration-[]an +d-[]deregistration-[]thresholds/ +[31] +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +[]\TU/KpRoman(1)/m/n/10.95 HM Trea-sury (2018) ``VAT Reg-is-tra-tion Thresh-old +: Call for Ev-i-dence,'' HM + +Underfull \hbox (badness 10000) in paragraph at lines 101--104 +\TU/KpRoman(1)/m/n/10.95 Trea-sury, March 2018, [][]$\TU/KpMono(0)/m/n/10.95 ht +tps://www.gov.uk/government/consultations/ + +Underfull \hbox (badness 7869) in paragraph at lines 106--109 +[] [] \TU/KpRoman(1)/m/n/10.95 (2024) ``Spring Bud-get 2024: Pol-icy Cost-ings, +'' HM Trea-sury, March 2024, + +Underfull \hbox (badness 10000) in paragraph at lines 106--109 +[][]$\TU/KpMono(0)/m/n/10.95 https://assets.publishing.service.gov.uk/media/65e +7920c08eef600155a5617/ + +Underfull \hbox (badness 4886) in paragraph at lines 133--137 +[]\TU/KpRoman(1)/m/n/10.95 Liu, Li, Ben Lock-wood, and Eddy H. F. Tam (2024) `` +Small Firm Growth and the + +Underfull \hbox (badness 2865) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 VAT Thresh-old: Ev-i-dence for the UK,'' IMF Work-ing +Pa-perWP/24/33, In-ter-na-tional + +Underfull \hbox (badness 10000) in paragraph at lines 133--137 +\TU/KpRoman(1)/m/n/10.95 Mon-e-tary Fund, [][]$\TU/KpMono(0)/m/n/10.95 https:// +www.imf.org/en/publications/wp/issues/2024/02/16/ + +Underfull \hbox (badness 1490) in paragraph at lines 139--143 +\TU/KpRoman(1)/m/n/10.95 West Ben-gal, In-dia,'' TaxDev / In-sti-tute for Fis-c +al Stud-ies, [][]$\TU/KpMono(0)/m/n/10.95 https://www.taxdev.org/ + +Underfull \hbox (badness 10000) in paragraph at lines 146--149 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice for Bud-get Re-spon-si-bil-ity (2023) ``The +Im-pact of the Frozen VAT Reg-is-tra- + +Underfull \hbox (badness 4886) in paragraph at lines 146--149 +\TU/KpRoman(1)/m/n/10.95 tion Thresh-old,'' Eco-nomic and Fis-cal Out-look, Mar +ch 2023, [][]$\TU/KpMono(0)/m/n/10.95 https://obr.uk/box/ + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +[]\TU/KpRoman(1)/m/n/10.95 Of-fice of Tax Sim-pli-fi-ca-tion (2017) ``Value Add +ed Tax: Routes to Sim-pli-fi-ca-tion,'' + +Underfull \hbox (badness 10000) in paragraph at lines 152--155 +\TU/KpRoman(1)/m/n/10.95 OTS re-port, Novem-ber 2017, [][]$\TU/KpMono(0)/m/n/10 +.95 https://assets.publishing.service.gov.uk/media/ +[32]) [33] (./Appendix/appendix.tex (./Appendix/a_data.tex +Overfull \hbox (11.12668pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion check rather than a silent re-place-ment. The snap-s +hot used here is Pol-i-cyEngine/ledger + +Overfull \hbox (30.38661pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 and max-i-mum nu-meric dif-fer-ence zero. (The ``2024--25 + vin-tage'' here de-notes the HMRC/ONS + +Overfull \hbox (3.00157pt too wide) in paragraph at lines 32--61 +\TU/KpRoman(1)/m/n/12 tion cal-i-brates to.) A 1,000-iteration Pop-u-lace run f +rom those tar-gets gen-er-ated 2,946,015 + +Overfull \hbox (58.07478pt too wide) in paragraph at lines 32--61 +\TU/KpMono(0)/m/n/12 firm-microsim-populace-ledger \TU/KpRoman(1)/m/n/12 and ch +ecked into \TU/KpMono(0)/m/n/12 results/populace_ledger_comparison.txt +[34]) (./Appendix/a_inference.tex +Overfull \hbox (8.25868pt too wide) in paragraph at lines 4--25 +\TU/KpMono(0)/m/n/12 results/recovery_bunching.txt\TU/KpRoman(1)/m/n/12 . The e +s-ti-ma-tor re-ports the ge-om-e-try only---the bunch- + +Overfull \hbox (11.25064pt too wide) in paragraph at lines 4--25 +\TU/KpRoman(1)/m/n/12 cess mass to an elas-tic-ity is not iden-ti-fied with-out + functional-form as-sump-tions ([][]Blomquist +[35] [36] [37] +Underfull \hbox (badness 1845) in paragraph at lines 156--156 +[][]\TU/KpRoman(1)/b/n/12 Ta-ble A.3[][]: []|\TU/KpRoman(1)/m/n/12 Power (re-co +v-ery) test on the step-free pop-u-la-tion: Kleven--Waseem- +))) [38] (./main.aux)) +(see the transcript file for additional information) + 1406 words of node memory still in use: + 6 hlist, 2 vlist, 2 rule, 18 glue, 4 kern, 1 glyph, 177 attribute, 77 glue_s +pec, 89 attribute_list, 2 write, 29 pdf_action nodes + avail lists: 1:1,2:966,3:445,4:197,5:776,6:27,7:10405,8:146,9:439,10:28,11:7 +27 + +warning (pdf backend): unreferenced destination with name 'Hfootnote.2' + +warning (pdf backend): unreferenced destination with name 'Hfootnote.1' + + +Output written on main.pdf (38 pages, 2141230 bytes). +Transcript written on main.log. +Latexmk: Getting log file 'main.log' +Latexmk: Examining 'main.fls' +Latexmk: Examining 'main.log' +Latexmk: Found input bbl file 'main.bbl' +Latexmk: Log file says output to 'main.pdf' +Latexmk: Using bibtex to make bibliography file(s). + ===Source file 'main.bbl' for 'lualatex' +Latexmk: Found bibliography file(s): + ./references.bib +Latexmk: Summary of warnings from last run of *latex: + Latex failed to resolve 2 reference(s) +Latexmk: ====Problematic refs and citations with line #s in .tex file: + (pdf backend): unreferenced destination with name 'Hfootnote.2' + (pdf backend): unreferenced destination with name 'Hfootnote.1' +Latexmk: All targets (main.pdf) are up-to-date + diff --git a/paper/Appendix/a_data.tex b/paper/Appendix/a_data.tex index f82a22b..c9bf415 100644 --- a/paper/Appendix/a_data.tex +++ b/paper/Appendix/a_data.tex @@ -7,16 +7,16 @@ \subsection{Data construction detail} account. Each of the approximately $2.94$ million firm rows carries a turnover, an input -expenditure, a calibration weight, and a registration status; the weights are -chosen so the weighted totals reproduce the official targets while the population -sums to about $2.5$ million firms. Because the population is calibrated \emph{to} the HMRC aggregates, -agreement between my weighted outputs and those aggregates is a check of -\emph{internal consistency}, not external validation: any target used in -calibration is reproduced by construction. I therefore read the -$\sim\!90\%$ calibration accuracy, and the close match of the static -\pounds85{,}000\,\(\to\)\,\pounds90{,}000 costing to HMRC's published figures, as -consistency checks on the pipeline rather than out-of-sample tests of firm -behaviour. +expenditure, a net VAT liability ($v_i = 0.20\,(y_i - x_i)$), a calibration +weight, and a registration status; the weights are chosen so the weighted +totals reproduce the official targets while the population sums to about +$2.5$ million firms. Because the population is calibrated \emph{to} the HMRC +aggregates, agreement between my weighted outputs and those aggregates is a +check of \emph{internal consistency}, not external validation: any target used +in calibration is reproduced by construction. The headline calibration +accuracies (89.2\% and 92.8\% for the two vintages) and the anchor comparison +of Section~\ref{sec:static} are therefore consistency checks on the pipeline, +not out-of-sample tests of firm behaviour. The reported calibration score is a bounded summary statistic. For each dimension I compute @@ -41,18 +41,21 @@ \subsection{Data construction detail} processed numeric inputs exactly after dropping presentation-only labels, totals, and the HMRC ``Unknown'' column that the generator does not calibrate: six normalized source tables checked, zero mismatches, and maximum numeric -difference zero. A 1,000-iteration Populace run from those targets generated -2,946,015 firm rows. Its own validator reports a 93.8 percent overall -calibration score, compared with the paper validator's 90.5 percent score for -the same vintage, but this overall comparison is not like-for-like: HMRC -turnover-band accuracy uses different band sets, and sector distribution -reflects different calibration-target definitions. The directly comparable rows -are ONS population, employment bands, and VAT liability by turnover band. -Populace hits VAT liability by turnover band more closely, while its weighted -population (2,945,777 versus 2,577,078) differs more from the paper population. -VAT liability by sector remains an informational diagnostic -in both runs. The comparison table and structured provenance are reproduced by -\texttt{firm-microsim-populace-ledger} and checked into +difference zero. (The ``2024--25 vintage'' here denotes the HMRC/ONS +statistical release labelled 2024--25, the same target tables the paper's +2024--25 population calibrates to.) A 1,000-iteration Populace run from those +targets generated 2,946,015 firm rows; its validator reported a 93.8 percent +overall score against the paper validator's then-90.5 percent, a comparison +that is not like-for-like (different band sets and sector-target definitions). +Two caveats now attach to that pinned snapshot. First, it predates this +paper's net-liability correction (Section~\ref{sec:data}, footnote): both +generators at the pin date shared the mis-scaled $v_i = y_i - x_i$ convention, +so the experimental Populace firm generator inherits the same defect, which I +have reported upstream; the target-parity result (zero mismatches) is +unaffected, since it concerns the input tables, not the generated population. +Second, the paper validator's scores on the corrected build are 89.2 percent +(2023--24) and 92.8 percent (2024--25). The comparison table and structured provenance are +reproduced by \texttt{firm-microsim-populace-ledger} and checked into \texttt{results/populace\_ledger\_comparison.txt} and \texttt{results/populace\_ledger\_provenance.json}. diff --git a/paper/Appendix/a_inference.tex b/paper/Appendix/a_inference.tex index 952578b..d666e7e 100644 --- a/paper/Appendix/a_inference.tex +++ b/paper/Appendix/a_inference.tex @@ -2,268 +2,184 @@ \subsection{Inference for the bunching estimator} \label{app:inference} This appendix documents the inference procedure for the reduced-form bunching -estimates of Section~\ref{sec:bunching}: the mass-conservation constraint -that disciplines the counterfactual density, the bootstrap that delivers -standard errors, the sensitivity of the estimates to the polynomial degree, -the exclusion window, and the effective wedge $\tau_{e}$, and a placebo test -demonstrating that the synthetic bunching is mechanical rather than behavioural. -All numbers reported here and in the calibration step are produced by the -released estimator (fixed seed, $B=200$ bootstrap replications), run on the -\pounds85{,}000 (2023--24) weighted synthetic firm data; the seed and $B$ are -fixed so the table is reproducible, and nothing is hardcoded as a result. +results of Section~\ref{sec:bunching}: the mass-conservation constraint that +disciplines the counterfactual density, why no standard errors are reported, +sensitivity to the polynomial degree, the exclusion window, and the generator +seed, the placebo tests, and the power (recovery) test. All numbers are +produced by the released estimator run on the regenerated weighted synthetic +populations for both vintages; the machine-readable artifacts are +\texttt{results/bunching\_inference.txt}, +\texttt{results/placebo\_bunching.txt}, +\texttt{results/recovery\_bunching.txt} and +\texttt{results/seed\_sensitivity.txt}. The estimator reports the geometry +only---the bunching ratio $b$, its \citet{liuetal2021}-normalised counterpart +$b_{\mathrm{LLAT}}$, the excess mass $E$, and the mass-conservation objects +($\Delta_R$, $y_R$)---and computes no elasticities: the mapping from excess +mass to an elasticity is not identified without functional-form assumptions +\citep{blomquistetal2021,bertanhaetal2023}, and on these data there is no +behavioural mass to convert in the first place.\footnote{Earlier versions of +the estimator also printed a CES substitution elasticity and two +wedge-normalised turnover elasticities, the latter inheriting an ad hoc +$\tau/2$ normalisation from a deleted smoothed-schedule model. These outputs +were labelled non-identified but were still reported; they have been removed +from the code and the paper.} \subsubsection*{Mass-conservation constraint} -The canonical bunching estimator of \citet{saez2010}, \citet{klevenwaseem2013} -and \citet{chettyetal2011} imposes that the counterfactual density conserves -mass: every firm removed from above the threshold reappears as excess mass below -it. An unconstrained fit by plain polynomial OLS on bins outside a hand-set -window computes the excess mass $E$ (below $T^{*}$) and the missing mass -$\Delta_{R}$ (above $T^{*}$) \emph{independently}, with no guarantee that -$E = \Delta_{R}$ and no endogenous location of the marginal buncher. - -I impose the constraint in two ways. First, the counterfactual polynomial in -$(y-T^{*})$ is fit by an iterated weighted least-squares procedure in which the -density of the bins above the excluded region is rescaled until the fitted -counterfactual integrates to the \emph{observed} total mass over the estimation -range $[\pounds20\text{k},\pounds140\text{k}]$. This forces the bunching mass to -be reabsorbed into the counterfactual rather than discarded. The regressor is -normalised to $[-1,1]$ for numerical stability of the high-degree Vandermonde -basis. Second, the upper edge of the excluded (manipulation) region---the -\emph{marginal buncher} $y_{R}$---is located \emph{endogenously} by integrating -the missing mass upward from $T^{*}$ until cumulative missing mass above equals -cumulative excess mass below, +The canonical bunching estimator of \citet{chettyetal2011} and +\citet{klevenwaseem2013} imposes that the counterfactual density conserves +mass: every firm removed from above the threshold reappears as excess mass +below it. An unconstrained polynomial fit on bins outside a hand-set window +computes the excess mass $E$ (below $T^{*}$) and the missing mass $\Delta_{R}$ +(above $T^{*}$) \emph{independently}, with no guarantee that $E=\Delta_{R}$ +and no endogenous location of the marginal buncher. I impose the constraint in +two ways. First, the counterfactual polynomial in $(y-T^{*})$ is fit by an +iterated procedure in which the density of the bins above the excluded region +is rescaled until the fitted counterfactual integrates to the observed total +mass over the estimation range $[\pounds20\text{k},\pounds140\text{k}]$ (the +regressor is normalised to $[-1,1]$ for numerical stability of the +high-degree basis). Second, the upper edge of the manipulation region---the +marginal buncher $y_{R}$---is located endogenously by integrating missing mass +upward from $T^{*}$ until it equals the excess mass below, \[ \int_{T^{*}}^{y_{R}} \bigl[f^{\mathrm{cf}}(y)-f^{\mathrm{obs}}(y)\bigr]_{+}\,dy \;=\; \int_{T^{*}-W}^{T^{*}} \bigl[f^{\mathrm{obs}}(y)-f^{\mathrm{cf}}(y)\bigr]_{+}\,dy - \;=\; E , + \;=\; E . \] -rather than being fixed at an arbitrary window edge. The excess turnover span of -the marginal buncher, $\Delta y^{*}=y_{R}-T^{*}$, is then used by the -notch-width elasticity. - -Imposing the constraint matters because the unconstrained fit grossly violates -adding-up: it delivers $E=7{,}820$ but $\Delta_{R}=16{,}524$, whereas the -constrained estimator returns $E=8{,}712$ and $\Delta_{R}=9{,}214$, which agree -to within sampling noise. Imposing the constraint thus reconciles the excess -mass below the threshold with the missing mass above it, which the -unconstrained estimator computes independently and which would otherwise diverge -by roughly a factor of two; the resulting movement in the headline estimates is -reported in the calibration step. - -\subsubsection*{Bootstrap standard errors} - -I compute standard errors by a firm-level bootstrap. In each of $B=200$ -replications I draw $n$ firms with replacement from the estimation sample, with -draw probabilities proportional to the survey weight, re-bin the resampled firms -into \pounds1{,}000 bins, and re-run the entire estimator---counterfactual fit, -marginal-buncher location, and all downstream statistics---on the replicate. The -standard error of each statistic is the standard deviation of its bootstrap -distribution, and the $95\%$ confidence interval is the $2.5$th--$97.5$th -percentile interval. Resampling firms (rather than residuals) propagates both -sampling variation and the variation induced by re-binning. Table~\ref{tab:boot} -reports the results. Because these replications resample the $\approx 2.94$ -million \emph{constructed} synthetic firm rows, whose number is itself a -modelling choice, the resulting standard errors and $95\%$ intervals quantify -only the estimator's dispersion under resampling of a synthetic file of -analyst-chosen size; they scale with that arbitrary row count and should -\emph{not} be read as population sampling error about the universe of UK firms. -They are reported for completeness and reproducibility, not as confidence -statements about UK firms. +On both populations the constraint binds at or near the window edge +($y_R = \pounds100$k at \pounds85{,}000; $\pounds101$k at \pounds90{,}000): +the OBR profile's missing mass extends beyond $+\pounds15$k (as does the +administrative pattern---LLAT's window reaches $+\pounds24$k), and the +2024--25 band-edge artifact is not a local spike at all. + +\subsubsection*{Why no standard errors are reported} + +Earlier drafts attached bootstrap standard errors to the bunching statistics +(resampling firm rows with replacement and re-running the estimator). Those +numbers are not reported anywhere in this paper, because the exercise has no +estimand: the synthetic file is a deterministic construction from published +targets, not a sample from a population, and row-resampling dispersion scales +as $1/\sqrt{n}$ in a row count the analyst chooses. A standard error that can +be made arbitrarily small by generating more synthetic rows conveys precision +that does not exist. Two reportable quantities replace them. First, the +specification grids below, which show how the point estimates move with the +estimator's own knobs. Second, generator-seed sensitivity +(\texttt{results/seed\_sensitivity.txt}): regenerating the full 2023--24 +population under three seeds moves $E$ by $\pm161$ firms ($\pm2\%$), +$b_{\mathrm{LLAT}}$ by $\pm0.02$, the raise-to-\pounds100k cost by +$\pm\pounds2.1$m, and the registered base by $\pm\pounds0.08$bn---the +pipeline's actual Monte Carlo error. Table~\ref{tab:boot} reports the point +estimates. \begin{table}[t] \centering -\caption{Bootstrap inference, \pounds85{,}000 data ($B=200$ firm resamples).} +\caption{Headline bunching statistics (point estimates; degree-7 polynomial, +$\pm\pounds15$k window). Uncertainty is characterised by the specification +grids and the generator-seed sensitivity, not by standard errors---see the +text.} \label{tab:boot} \begin{tabular}{lrrr} -\hline -Statistic & Point & Std.\ error & 95\% CI \\ -\hline -Bunching ratio $b$ & $0.060$ & $0.005$ & $[0.050,\ 0.068]$ \\ -Excess mass $E$ & $8{,}712$ & $662$ & $[7{,}920,\ 10{,}516]$ \\ -Substitution elasticity $\sigma$ & $4.85$ & $0.12$ & $[4.58,\ 5.08]$ \\ -Displaced share $\Pi$ & $0.211$ & $0.005$ & $[0.200,\ 0.219]$ \\ -Notch-width elasticity (median) & $0.448$ & $0.027$ & $[0.405,\ 0.496]$ \\ -Marginal-buncher elasticity & $0.657$ & $0.082$ & $[0.510,\ 0.821]$ \\ -\hline +\toprule +Vintage & $E$ & $b_{\mathrm{LLAT}}$ & $y_R$ (\pounds k) \\ +\midrule +2023--24 (\pounds85k, OBR fine targets) & $7{,}933$ & $1.91$ & $100.0$ \\ +2024--25 (\pounds90k, coarse bands only) & $11{,}072$ & $1.23$ & $101.0$ \\ +\bottomrule \end{tabular} \end{table} -\subsubsection*{Non-identification: the elasticities are not behavioural} - -The bunching-implied elasticities in Table~\ref{tab:boot}---the notch-width -elasticity ($\approx 0.45$) and the marginal-buncher elasticity -($\approx 0.66$)---together with the CES substitution elasticity -$\sigma = 4.85$ are \emph{not} behaviourally identified on these data. The -synthetic firm population is calibrated to coarse aggregate HMRC turnover-band -counts, and the generator contains no firm location-choice: firms do not respond -to the threshold, so the excess mass below it is mechanical, inherited from the -density step in the calibration targets rather than from any behavioural -response (the placebo test below makes this precise). The elasticities are -therefore reported only as a record of what the estimator returns when applied -to these data; the paper draws no behavioural conclusion from them. A reader -should note that the iso-elastic turnover elasticities $e\in\{0.05,0.17,0.32\}$ -swept in the body (Section~\ref{sec:behavioural}) are a \emph{different} object -from the notch-width elasticity ($\approx 0.45$) and marginal-buncher elasticity -($\approx 0.66$) reported here: the former are the median and mean of a per-firm -marginal-buncher mapping under the iso-elastic firm specification, while the -latter are aggregate estimator outputs computed under different normalisations. -All of these numbers are mechanical artefacts of the calibration and are -non-identified on these synthetic data---they admit no precise numerical mapping -between the two sets---so none is used anywhere as a behavioural estimate. This is an -instance of the general non-identification of bunching elasticities absent -exogenous variation or strong functional-form assumptions -\citep{blomquistetal2021, bertanhaetal2023}. - \subsubsection*{Sensitivity to polynomial degree and exclusion window} -Table~\ref{tab:degwin} maps the point estimates across a grid of polynomial -degree $\in\{5,6,7,8\}$ and symmetric exclusion window -$\in\{\pounds10\text{k},\pounds15\text{k},\pounds20\text{k},\pounds25\text{k}\}$. -The estimates are stable across the central cells (degree $6$--$7$, window -\pounds10--\pounds20k): the substitution elasticity stays in roughly -$4.4$--$5.7$ and the excess mass in $4{,}000$--$9{,}000$. The corner cells are -less reliable: at very wide windows ($\pounds25$k) the excluded region begins to -swallow genuine curvature in the density, the fitted counterfactual crosses the -observed density, and $b$ can turn slightly negative (so $\sigma$ is undefined); -at the lowest degree ($5$) the inflexible trend over-fits the bunching mass into -the counterfactual and inflates $b$. I therefore report the degree-$7$, -\pounds15k-window specification as the baseline, with the bootstrap CIs above -spanning the variation across the stable interior of the grid. - -\begin{table}[t] -\centering -\caption{Degree $\times$ window sensitivity (point estimates), \pounds85{,}000 -data. Cells with $b<0$ leave $\sigma$ undefined.} -\label{tab:degwin} -\begin{tabular}{llrrrr} -\hline -Degree & Window & $b$ & $E$ & $\sigma$ & Notch-width (median) \\ -\hline -5 & \pounds10k & $0.150$ & $13{,}339$ & $5.62$ & $0.47$ \\ -5 & \pounds15k & $0.139$ & $18{,}823$ & $5.16$ & $0.71$ \\ -5 & \pounds20k & $0.141$ & $25{,}596$ & $4.95$ & $0.87$ \\ -5 & \pounds25k & $0.152$ & $34{,}172$ & $5.11$ & $1.04$ \\ -6 & \pounds10k & $0.077$ & $7{,}262$ & $5.42$ & $0.41$ \\ -6 & \pounds15k & $0.045$ & $6{,}575$ & $4.99$ & $0.44$ \\ -6 & \pounds20k & $0.015$ & $3{,}822$ & $4.21$ & $0.35$ \\ -6 & \pounds25k & $-0.028$ & $471$ & --- & $0.15$ \\ -7 & \pounds10k & $0.091$ & $8{,}539$ & $5.07$ & $0.47$ \\ -\textbf{7} & \textbf{\pounds15k} & $\mathbf{0.060}$ & $\mathbf{8{,}712}$ & $\mathbf{4.85}$ & $\mathbf{0.45}$ \\ -7 & \pounds20k & $0.034$ & $7{,}313$ & $4.62$ & $0.43$ \\ -7 & \pounds25k & $-0.004$ & $3{,}089$ & --- & $0.25$ \\ -8 & \pounds10k & $0.118$ & $10{,}806$ & $4.92$ & $0.42$ \\ -8 & \pounds15k & $0.118$ & $16{,}329$ & $4.53$ & $0.59$ \\ -8 & \pounds20k & $0.166$ & $29{,}364$ & $4.96$ & $0.77$ \\ -8 & \pounds25k & $0.301$ & $59{,}931$ & $7.57$ & $0.95$ \\ -\hline -\end{tabular} -\end{table} - -\subsubsection*{Sensitivity to the effective wedge} - -The CES substitution elasticity is recovered as $\sigma = -\ln(\mathrm{RR})/\ln(1+\tau_{e})$, where $\mathrm{RR}$ is the ratio of -counterfactual-to-observed above/below mass ratios. Because the wedge enters only -through $\ln(1+\tau_{e})$, $\sigma$ scales roughly as $1/\ln(1+\tau_{e})$ while -the displaced share $\Pi = 1-(1+\tau_{e})^{-\sigma}$ is essentially invariant -(it is pinned by $\mathrm{RR}$). On my data, $\tau_{e}=0.025$ gives -$\sigma=9.59$, $\tau_{e}=0.05$ gives $\sigma=4.85$, $\tau_{e}=0.075$ gives -$\sigma=3.28$, and $\tau_{e}=0.10$ gives $\sigma=2.49$, while $\Pi=0.211$ -throughout. The magnitude of $\sigma$ is therefore conditional on $\tau_{e}$: I -adopt $\tau_{e}=0.05$ as a baseline effective registration wedge and report -$\Pi$, which is robust to it, as the policy-relevant displacement object. - -\subsubsection*{Placebo test} - -The non-identification of the bunching elasticities can be made precise with a -placebo test. The HMRC turnover-band targets to which the synthetic population -is calibrated are coarse: a single count for firms at or below \pounds85{,}000 -and a single count for firms in \pounds85{,}000--\pounds150{,}000. The implied -average per-\pounds1{,}000 densities differ sharply across the threshold -($\approx 7{,}981$ firms/\pounds1{,}000 below versus $\approx 4{,}697$ above), so -the calibration target \emph{itself} contains a density step at exactly -\pounds85{,}000. Because the generator has no firm location-choice, any density -discontinuity in the synthetic population must be inherited from this stepped -target rather than produced by behaviour. The placebo removes the step and -re-runs the estimator. Table~\ref{tab:placebo} reports two variants: Placebo~A -reweights the existing synthetic firms so the per-\pounds1{,}000 density follows -a single smooth log-quadratic trend across the threshold (preserving total mass -over $[\pounds20\text{k},\pounds140\text{k}]$, no regeneration); Placebo~B -replaces the two HMRC band counts straddling \pounds85{,}000 with a split -implied by a single common per-\pounds1{,}000 density (no step in the target), -then re-runs the full generator and multi-objective calibration before -estimating. +Table entries for a grid of polynomial degree $\in\{5,6,7,8\}$ and symmetric +exclusion window $\in\{\pounds10\text{k},\ldots,\pounds25\text{k}\}$ are in +\texttt{results/bunching\_inference.txt}; the pattern matters more than the +cells. On the 2023--24 population the target-inherited excess ranges over +roughly $6{,}700$--$9{,}800$ in the interior cells (degrees 6--7, windows +\pounds10--15k), inflating in the corner cells where the polynomial confuses +the profile's shoulders with its counterfactual. On the 2024--25 population +the band-edge artifact swings four-fold across the grid ($E$ between roughly +$8{,}600$ and $36{,}700$; $b_{\mathrm{LLAT}}$ between $0.94$ and $4.46$) +while its headline cell lands within 10\% of the administrative estimate: +neither specification stability nor literature-proximity certifies a +synthetic bunching statistic---a caution for any bunching exercise on +calibrated synthetic data. + +\subsubsection*{Placebo tests} + +The placebo makes the target-inheritance mechanism precise by manipulating the +calibration targets and re-running the estimator +(Table~\ref{tab:placebo}; Section~\ref{ssec:bunch-placebo} describes the +constructions). The estimates track the targets exactly: the control, +calibrated to the OBR fine-band profile, returns $E=7{,}933$; Placebo~A +(smooth reweighting) returns $E=0$; and Placebo~B (no fine targets, +un-stepped coarse bands, full regeneration and recalibration) returns $E=0$. +Removing structure from the targets removes structure from the estimates +because the targets are the only place sub-band structure can come from: the +generator has no firm location-choice. \begin{table}[t] \centering -\caption{Placebo test: removing the calibration density step collapses the -excess mass. \pounds85{,}000 data.} +\caption{Placebo tests, 2023--24 population (\pounds85{,}000 threshold).} \label{tab:placebo} -\begin{tabular}{lrrr} -\hline -Population & $b$ & $E$ & $b_{\mathrm{LLAT}}$ \\ -\hline -Actual (control) & $+0.060$ & $8{,}712$ & $0.941$ \\ -Placebo A (reweight density smooth) & $-0.063$ & $0$ & $0.000$ \\ -Placebo B (un-stepped HMRC band targets) & $-0.016$ & $99$ & $0.010$ \\ -\hline +\begin{tabular}{lrr} +\toprule +Population & $b_{\mathrm{LLAT}}$ & $E$ \\ +\midrule +Actual (control, OBR fine-band targets) & $1.911$ & $7{,}933$ \\ +Placebo A (reweight density smooth) & $0.000$ & $0$ \\ +Placebo B (no fine targets, un-stepped) & $0.395$ & $0$ \\ +\bottomrule \end{tabular} \end{table} -When the density step is removed from the calibration target, the estimated -excess mass collapses from $8{,}712$ firms in the control to at most $\approx 99$ -firms ($\approx 1\%$ of the control value) in Placebo~B, and to zero in -Placebo~A; the bunching ratio even turns slightly negative. This proves that the -synthetic bunching is inherited from the coarse HMRC turnover-band targets, not -from any firm behaviour, and confirms that the elasticities in -Table~\ref{tab:boot} are mechanical artefacts of the calibration rather than -behavioural parameters. The placebo is part of the released code and is fully -reproducible. - -\subsubsection*{Recovery: the estimator has power} - -The placebo establishes \emph{specificity}: the estimator returns no bunching -when none is present. The complementary property is \emph{sensitivity}---whether -the estimator can detect a genuine behavioural response when one \emph{is} -present. To check this I run a recovery exercise. Starting from the step-free -Placebo~A population---the null world with no bunching---I inject a behavioural -bunching signal of \emph{known} magnitude by relocating $E_{\mathrm{true}}$ firms, -mass-conservingly, from a donor window just above the threshold to a window just -below it (the firm location-choice the generator lacks), with a triangular -profile peaking at \pounds85{,}000. I then re-run the \emph{same} estimator -(degree~$7$, $\pm\pounds15$k window) and record the recovered excess mass, -measured as the change in signed below-threshold excess relative to the step-free -baseline. Table~\ref{tab:recovery} reports three magnitudes. +\subsubsection*{Power (recovery) test} + +The placebo establishes \emph{specificity}: no false positive on step-free +data. The complementary property is \emph{power}. Starting from the step-free +Placebo~A population, I inject a Kleven--Waseem-consistent behavioural signal +of known magnitude: firms in the donor region $(T^{*}, \pounds112\text{k}]$ +relocate to $[\pounds80\text{k}, T^{*})$ with probability declining linearly +from the threshold to zero at the true marginal buncher +$y_R^{\mathrm{true}}=\pounds112$k, so the missing-mass region extends +\pounds12k \emph{beyond} the exclusion window---as with genuine bunching---and +the counterfactual fit confronts genuinely depressed above-window bins. +Recovery is scored with the headline estimator alone +(Table~\ref{tab:recovery}).\footnote{An earlier version of this exercise +relocated mass entirely \emph{within} the exclusion window. The fitted +counterfactual is identical across such injections by construction (it is fit +outside the window and rescaled by total mass, which relocation preserves), so +that version measured deposit bookkeeping, not power, and its stated +attenuation mechanism was wrong. The redesigned test supersedes it.} \begin{table}[t] \centering -\caption{Recovery test: the estimator recovers $\approx 90\%$ of an injected -behavioural response of known magnitude. \pounds85{,}000 data; -$E_{\mathrm{recovered}}$ is the change in signed below-threshold excess relative -to the step-free baseline.} +\caption{Power (recovery) test on the step-free population: +Kleven--Waseem-consistent injections with true marginal buncher at +\pounds112{,}000. Baseline (no injection): $E=0$.} \label{tab:recovery} -\begin{tabular}{rrr} -\hline -$E_{\mathrm{true}}$ (injected) & $E_{\mathrm{recovered}}$ & Recovery \\ -\hline -$2{,}000$ & $1{,}792$ & $89.6\%$ \\ -$5{,}000$ & $4{,}479$ & $89.6\%$ \\ -$8{,}000$ & $7{,}167$ & $89.6\%$ \\ -\hline +\begin{tabular}{rrrr} +\toprule +$E_{\mathrm{true}}$ (injected) & $E_{\mathrm{hat}}$ & Recovery & $\hat y_R$ (true 112) \\ +\midrule +$2{,}000$ & $298$ & $14.9\%$ & $85.8$ \\ +$5{,}000$ & $2{,}445$ & $48.9\%$ & $91.9$ \\ +$8{,}000$ & $4{,}918$ & $61.5\%$ & $100.0$ \\ +\bottomrule \end{tabular} \end{table} -The estimator recovers about $90\%$ of the injected mass at every magnitude (a -stable $89.6\%$, monotone in $E_{\mathrm{true}}$ and never over-stating). The -$\approx 10\%$ attenuation is benign: the degree-7 polynomial counterfactual -re-absorbs part of the injected spike and the fixed exclusion window clips its -tails, so the estimator slightly \emph{under}-states a true response rather than -inflating one. The estimator is therefore both \emph{specific} (no false -positive---the placebo) and \emph{sensitive} (has power---this recovery). The -implication is the one this section turns on: the absence of identified bunching -on the actual synthetic data is a property of the aggregate-calibrated -\emph{data}, which contain no firm location-choice, not a failure of the -\emph{method}. The recovery test is part of the released code and is fully -reproducible. +Recovery rises with signal size---half to two-thirds of moderate +(5{,}000--8{,}000-firm) injections, while a small 2{,}000-firm injection sits +near the detection floor---and the estimator \emph{under}-states the truth +rather than inflating it. The +attenuation has a measured mechanical source: the depressed bins between the +window top (\pounds100k) and the true marginal buncher (\pounds112k) enter the +counterfactual fit and pull it down, truncating measured missing mass and +drawing $\hat y_R$ toward the threshold. The implication is the one +Section~\ref{sec:bunching} turns on: the target-inherited excess on the +2023--24 data is read with the same attenuation a genuine signal would face, +so the estimator, if anything, under-states the targeted profile; and no +attenuation argument can turn the 2024--25 band-edge artifact into +behaviour. Both tests are part of the released code and are +fully reproducible. diff --git a/paper/Appendix/appendix.tex b/paper/Appendix/appendix.tex index 6db633f..52230d0 100644 --- a/paper/Appendix/appendix.tex +++ b/paper/Appendix/appendix.tex @@ -3,10 +3,10 @@ \section{Appendix} This appendix collects supporting material in two parts: data construction and calibration robustness (Appendix~\ref{app:data}); -and statistical inference for the reduced-form bunching estimates -(Appendix~\ref{app:inference}), which also reports a placebo test -demonstrating that the synthetic bunching is mechanical---inherited -from the coarse HMRC turnover-band targets---rather than behavioural. +and statistical inference for the reduced-form bunching results +(Appendix~\ref{app:inference}), including the placebo and power tests +establishing that band-calibrated synthetic data cannot support +bunching inference in either direction. \input{Appendix/a_data} \input{Appendix/a_inference} diff --git a/paper/Sections/background.tex b/paper/Sections/background.tex index ec0f4a4..144d0be 100644 --- a/paper/Sections/background.tex +++ b/paper/Sections/background.tex @@ -14,14 +14,19 @@ \section{Institutional background} \paragraph{Value added, input reclaim, and voluntary registration.} Real VAT is a tax on \emph{value added}, not on turnover: a registered firm charges output VAT -on its sales but reclaims input VAT on its purchases. A large share of -below-threshold firms therefore register \emph{voluntarily}---roughly $43\%$ of -eligible below-threshold firms \citep{liuetal2021}, driven by input-VAT reclaim and -business-to-business sales---and for them the incentive to bunch is weak. My -one-input model taxes \emph{turnover} rather than value added, so it is a -\emph{turnover-tax-notch approximation} for the consumer-facing, limited-reclaim -firms for whom the bunching incentive is sharpest; it abstracts from input reclaim -and voluntary registration. I treat this as a first-order scope restriction. +on its sales but reclaims input VAT on its purchases. The model reflects this: +each synthetic firm's net liability is the standard rate applied to its value +added (Section~\ref{sec:data}), and under the value-added formulation the +notch's dominated region is invariant to the firm's input share +(Section~\ref{sec:model}). Two features of the real system remain outside the +model's scope. A large share of below-threshold firms register +\emph{voluntarily}---roughly $43\%$ of eligible below-threshold firms +\citep{liuetal2021}, driven by input-VAT reclaim and business-to-business +sales---and for them the threshold carries no bunching incentive; voluntary +registration enters the model only as a registration-rate parameter and a +retention sensitivity, not as a choice. And net-repayment traders (zero-rated +exporters and similar, HMRC's negative-liability column) are not represented, +because the public aggregates do not resolve rated structure by turnover band. \paragraph{Threshold history.} The registration threshold was held at \pounds85{,}000 from 1~April 2017 to 31~March 2024---a seven-year nominal freeze, @@ -48,7 +53,8 @@ \section{Institutional background} \label{fig:obr_bunching} \end{figure} -\paragraph{The reform debate.} The UK threshold is among the highest in the OECD, +\paragraph{The reform debate.} The UK threshold is the highest in the OECD +alongside Switzerland \citep{hmrc_threshold}, and there is debate over whether to raise it---to reduce the compliance burden on small firms---or lower it, to broaden the base and reduce the growth distortion at the margin. Three families of reform feature, and I evaluate all three: a change in @@ -58,7 +64,13 @@ \section{Institutional background} notch with a continuous profile); and a change in its \emph{rate} (a \emph{reduced rate} for small firms in a band above the threshold, with the standard 20\% rate retained above). The taper and reduced-rate designs follow proposals in the UK -policy debate, notably \citet{ots2017vat}, which canvassed a financial incentive or -reduced effective rate to smooth the cliff-edge at the threshold. A banded reduced rate introduces a smaller \emph{secondary} notch -at the band top, which the continuous taper avoids. I cost all three by the same -machinery in Section~\ref{sec:static}. +policy debate: \citet{ots2017vat} canvassed a financial incentive or reduced +effective rate to smooth the cliff-edge at the threshold, and HM Treasury's +call for evidence on the registration threshold examined smoothing mechanisms +in the same family \citep{hmt2018cfe}. The European Union ran a closely +related ``graduated relief'' scheme for small enterprises and abolished it +from January~2025 on complexity grounds, in favour of a simple exemption with +a transition tolerance \citep{eudirective2020285}---relevant precedent for the +administrability of taper-style designs. A banded reduced rate introduces a +smaller \emph{secondary} notch at the band top, which the continuous taper +avoids. I cost all three by the same machinery in Section~\ref{sec:static}. diff --git a/paper/Sections/behavioural.tex b/paper/Sections/behavioural.tex index 45d50ee..f08b705 100644 --- a/paper/Sections/behavioural.tex +++ b/paper/Sections/behavioural.tex @@ -4,29 +4,29 @@ \section{Behavioural reform costs} The reforms of Section~\ref{sec:static} are costed \emph{statically}: each schedule is re-applied to a fixed turnover distribution, and the revenue change is the mechanical reclassification of firms with no response in turnover. -Section~\ref{sec:bunching} then shows that the bunching in my synthetic data is -mechanical, so a behavioural elasticity is not identified from it---the reduced-form -response is a placebo. Section~\ref{sec:model} supplies the one object that needs -no behavioural calibration at all: the exact, elasticity-free dominated region. What is -missing from this sequence is the behavioural layer itself---a costing that lets -firms re-optimise turnover when a reform changes the effective rate they face. This -section supplies that layer. I build an iso-elastic structural simulator that, for -an \emph{assumed} turnover elasticity $e$, re-solves each firm's optimum under a -counterfactual schedule and prices the resulting revenue effect. Because $e$ is not -identified from these data, I do not report a point estimate; I report an -$e$-sensitivity range. The simulator nests the static costing of -Section~\ref{sec:static} as its $e\to0$ limit, which I use below as a correctness -check rather than treat as a coincidence. This is honest infrastructure, and every -number in it is explicitly conditional on $e$. - -\subsection{An iso-elastic structural simulator} +Section~\ref{sec:bunching} shows that the synthetic data contain no behavioural +signal from which a response could be estimated, and Section~\ref{sec:model} +supplies the one object that needs no behavioural calibration at all: the exact +dominated region. What is missing from this sequence is the behavioural layer +itself---a costing that lets firms re-optimise turnover when a reform changes the +effective rate they face. This section supplies that layer for an \emph{assumed} +turnover elasticity $e$, reported as an $e$-sensitivity range rather than a point +estimate, and nesting the static costing exactly in its $e\to0$ limit. Its +headline is deflationary, and usefully so: on the intensive margin the static +costings are robust. A pure threshold rise has \emph{exactly} zero +intensive-margin revenue offset at every $e$, and the reduced-rate bands' offsets +stay under $4\%$ of the static cost across the sweep. + +\subsection{An iso-elastic simulator on the intensive margin} \label{ssec:simulator} -I adopt the iso-elastic firm problem of \citet{klevenwaseem2013}, in the -sufficient-statistics tradition of \citet{saez2010} and as applied to UK VAT by -\citet{liuetal2021}, but write it so that the tax falls on \emph{value added} -rather than on turnover. In this value-added statement---which I label -formulation~A---a firm of ability $n_i$ chooses turnover $y$ to maximise +I adapt the iso-elastic model of \citet{klevenwaseem2013}, in the +sufficient-statistics tradition of \citet{saez2010}, writing the tax on +\emph{value added} rather than on turnover. (\citet{liuetal2021} caution that +turnover-tax bunching formulae do not carry to VAT unmodified, because input +costs intervene; the value-added statement below is the adaptation this +requires.) In this statement---formulation~A---a firm of ability $n_i$ chooses +turnover $y$ to maximise \begin{equation} \pi_i(y) \;=\; (1-\delta_i)\,\bigl(1-\tau\,f(y)\bigr)\,y \;-\; C(y;n_i,e), \qquad @@ -53,241 +53,187 @@ \subsection{An iso-elastic structural simulator} \label{eq:flat-optimum} \end{equation} so the retained wedge facing the firm is the product $(1-\delta)(1-\tau)$ of the -value-added share and the statutory net-of-tax rate, and one verifies directly -from~\eqref{eq:flat-optimum} that -$\mathrm{d}\ln y^{*}/\mathrm{d}\ln\!\bigl[(1-\delta)(1-\tau)\bigr]=e$, so $e$ is +value-added share and the statutory net-of-tax rate, and +$\mathrm{d}\ln y^{*}/\mathrm{d}\ln\!\bigl[(1-\delta)(1-\tau)\bigr]=e$: $e$ is exactly the knob that governs the intensive response. Figure~\ref{fig:formulation_a_optima} traces the formulation-A profit and its -optima across the notch and taper schedules for three deductible shares, showing -how both the value-added optimum and the notch geometry shift with $\delta$: the -$(1-\delta)$ factor scales the whole curve down, and a higher $\delta$ pulls the -registered optimum back toward the threshold, eventually tipping the global -choice from the registered interior optimum to bunching at the notch. +optima across the notch and taper schedules for three deductible shares. \begin{figure}[htbp] \centering \includegraphics[width=0.85\textwidth]{figures/formulation_a_optima.png} -\caption{Optima of the value-added (formulation~A) profit -function~\eqref{eq:isoelastic}, $\pi_A(y)=(1-\delta)(1-\tau f(y))\,y-C(y;n,e)$, -at statutory rate $\tau=0.20$, ability $n=\pounds130$k and elasticity $e=0.17$, -under the hard registration notch (left) and the graduated -taper (right). Each panel overlays three deductible-input shares -$\delta\in\{0.0,0.4,0.8\}$; dots mark each curve's local maxima and the star its -global optimum, and the dashed vertical line is the \pounds85{,}000 threshold. -The value-added factor $(1-\delta)$ scales the whole curve down without moving -the frictionless optimum, while a higher $\delta$ shrinks the retained wedge -$(1-\delta)(1-\tau)$ and so pulls the registered optimum -$y^{*}=n[(1-\delta)(1-\tau)]^{e}$ back toward the threshold---eventually tipping -the global optimum from the registered interior peak to bunching at the notch, -consistent with the formulation-A discussion above.} +\caption{Optima of the formulation-A profit function~\eqref{eq:isoelastic} at +$\tau=0.20$, $n=\pounds130$k, $e=0.17$, under the registration notch (left) and +the graduated taper (right), for deductible-input shares +$\delta\in\{0.0,0.4,0.8\}$. Dots mark local maxima, the star the global +optimum, and the dashed line the \pounds85{,}000 threshold. A higher $\delta$ +scales the profit curve down and pulls the registered optimum +$y^{*}=n[(1-\delta)(1-\tau)]^{e}$ toward the threshold, eventually tipping the +global optimum to bunching at the notch.} \label{fig:formulation_a_optima} \end{figure} -\paragraph{Ability recovery.} To populate the simulator I recover an ability $n$ -for each firm from its observed turnover under the baseline \pounds85{,}000 notch. -Given $e$, I set $n=y_{\mathrm{obs}}$ for an unregistered firm -($y_{\mathrm{obs}}\; y_{\mathrm{obs},i}, + \left(\frac{1-\tau f_1}{1-\tau f_0}\right)^{e}. \label{eq:rescale} \end{equation} -so the taxed base broadens and partly offsets the static loss. - -\paragraph{Conditional on $e$.} I am explicit about what this exercise is and is -not. Treating each firm's observed (mechanically calibrated) turnover as optimal -and inverting it for $n$ is an \emph{accounting anchor}, not structural -identification: it reproduces the baseline by construction but borrows no -information about the response. The elasticity $e$ is not identified from these data -(the placebo of Section~\ref{sec:bunching}), so every behavioural magnitude below is -conditional on the assumed $e$. The robust, $e$-free headline objects remain the -static cost of Section~\ref{sec:static} and the exact dominated region of -Section~\ref{sec:model}; this section's numbers are a disciplined sensitivity range, -not point estimates. The margin priced here is purely \emph{intensive}---firms scale -turnover as the effective rate moves. The extensive notch distortion, the discrete -incentive to suppress turnover and bunch below the threshold, is the separate -analytic object of Section~\ref{sec:model}; a reader should not expect re-bunching -dynamics here. +The intensive response depends only on $e$, the statutory rate, and the +schedule fractions---not on $\delta_i$, not on the firm's net remittance rate, +and not on the recovered ability level. Ability recovery +($n_i=y_{\mathrm{obs},i}$ below the threshold, +$n_i=y_{\mathrm{obs},i}/[(1-\delta_i)(1-\tau)]^{e}$ above) is an +\emph{accounting anchor}---it rationalises the observed allocation given +$e$ and reproduces the baseline by construction---but no reform number below +depends on it. + +\paragraph{Region-confined scope.} The margin priced here is purely +\emph{intensive}: each firm re-optimises within the region of the reform +schedule that contains its observed turnover, per~\eqref{eq:rescale}, clipped +at its region's edges. Relocation across a notch---bunching below a threshold +from above, or de-registering past a band edge---is the \emph{extensive} +margin, which is the separate analytic object of Section~\ref{sec:model} +(the dominated region and the marginal buncher) and is deliberately out of +scope: the synthetic data contain no information about it +(Section~\ref{sec:bunching}), and pricing it would require assumptions about +re-bunching dynamics the paper has declined to make. Confining the response to +the firm's own region also makes the $e\to0$ limit collapse onto the static +costing \emph{exactly}, with no solver tolerance.\footnote{An earlier version +of this simulator computed the registered optimum by damped fixed-point +iteration on the discontinuous schedule. For any firm whose ability straddles +a reform notch that iteration has no fixed point---the iterate oscillates +across the notch and the reported turnover is an artifact of the iteration +count. The reported behavioural offsets in the earlier draft (for example +$-\pounds292$m against a static $-\pounds508$m for the raise at $e=0.17$) were +dominated by this artifact. The corrected, region-confined solve is closed +form; the replication repository documents the change.} + +\paragraph{Conditional on $e$.} The elasticity $e$ is not identified from +these data, so every behavioural magnitude below is conditional on the assumed +$e$, and the sweep is a sensitivity analysis rather than a set of forecasts. +The sweep values $e\in\{0.05,\,0.17,\,0.32\}$ are assumptions: $0.05$ is the +external anchor---\citet{klevenwaseem2013} report lower-bound structural +elasticities mostly in $[0.05, 0.15]$---and $0.17$ and $0.32$ are chosen to +span the range used in the threshold literature; the published UK VAT-base +elasticities of \citet{liuetal2021} (roughly $0.09$--$0.14$) fall between the +anchor and the midpoint. A reader may substitute any preferred value directly. +The robust, $e$-free headline objects remain the static costs of +Section~\ref{sec:static} and the dominated region of Section~\ref{sec:model}. \subsection{Results} \label{ssec:behavioural-results} -I sweep $e\in\{0.05,\,0.17,\,0.32\}$ and report the full sweep, treating -$e=0.17$ as an illustrative midpoint rather than a headline estimate. The low -value $0.05$ is of the order reported by \citet{klevenwaseem2013}; $0.32$ is the -mean implied by mapping the marginal-buncher condition through my notch; $0.17$ is -the median of that mapping. (These per-firm-mapping summaries are a different object -from the single aggregate marginal-buncher elasticity $\approx0.66$ tabulated in -Appendix~\ref{app:inference}, and differ from it numerically; both are mechanical, -non-identified artefacts of the calibration.) I flag the provenance plainly: the $0.17$ and $0.32$ -values are read off the marginal-buncher condition applied to my notch geometry, -which inherits the mechanical bunching that Section~\ref{sec:bunching} shows to be -non-behavioural, so they are model-implied, not data-identified; the range's only -externally-anchored point is its lower end (the \citet{klevenwaseem2013} value of -$\approx 0.05$). I use them only to delimit a plausible sweep, and a reader -preferring a fully external range---for instance \citet{liuetal2021}'s UK VAT-base -elasticity---may substitute literature values for $e$ directly without changing the -conditional structure of the costing. The same mapping pins the marginal buncher -$n_H(e)$---the highest ability that still finds it optimal to bunch at the -threshold---at \pounds112{,}795 for $e=0.05$ (a frictionless excess -$\Delta y_{H}\equiv n_H-T^{*}\approx\pounds27.8$k, distinct from the empirical -bunching span $\Delta y^{*}=\pounds5.6$k of Appendix~\ref{app:inference}), -\pounds127{,}382 for $e=0.17$ -($\approx\pounds42.4$k), and \pounds143{,}527 for $e=0.32$ ($\approx\pounds58.5$k), -consistent with the analytic dominated-region width $a=\pounds21{,}250$ of -Section~\ref{sec:model}. - -Table~\ref{tab:behavioural_costs} reports the behavioural cost of each of the three -flat-rate reforms---the raised threshold and the two reduced-rate bands---measured -as the change in revenue relative to the \pounds85{,}000-notch baseline, alongside -the static figure of Table~\ref{tab:schedule_costs}, for each $e$. The direction is -uniform across these three: a larger $e$ makes each of them \emph{cheaper} in -revenue terms. The mechanism is~\eqref{eq:rescale}: each reform lowers the effective -rate on the band by a \emph{constant} amount, so firms scale turnover up toward -their frictionless optimum, broadening the taxed base and partly offsetting the -static loss. The offset is substantial: at $e=0.17$ the raised threshold costs -\(-\)\pounds292m against a static \(-\)\pounds508m, and the $10\%$ and $15\%$ bands -cost \(-\)\pounds273m and \(-\)\pounds135m against static \(-\)\pounds343m and -\(-\)\pounds171m. At the illustrative midpoint $e=0.17$, the number of firms re-optimising is -$50{,}155$ under the raised threshold, $61{,}187$ under the $10\%$ reduced rate, and -$51{,}226$ under the $15\%$ reduced rate. Figure~\ref{fig:reform_dist} traces these -costs across the full range of $e$, with each curve nesting onto its static value as -$e\to0$. - -\paragraph{Why the graduated taper is excluded.} I do not report a behavioural cost -for the graduated taper, and I want to be candid about why. The taper carries two -behavioural channels that pull in opposite directions. The first is the -base-broadening channel shared with the flat reforms: as the \emph{average} rate a -firm faces falls, the firm scales its turnover up, which is cheaper for revenue in -exactly the way~\eqref{eq:rescale} captures. The second is a marginal-rate -distortion that is the taper's signature: because the taper's rate \emph{rises} with -turnover, raising output lifts the rate on \emph{all} of a firm's turnover, so the -firm faces an incentive to hold turnover down---a force that is costlier for -revenue, not cheaper. The iso-elastic cost used here can price the first, upward -channel but not the second, downward one. Imposing the full marginal-rate wedge in a -correct first-order-condition solve makes firms collapse to the band floor and yields -economically pathological revenue losses of the order of several billion pounds---an -artefact of a cost function that cannot represent the downward, marginal-rate-driven -response a taper induces, not a credible policy estimate. The net behavioural sign of -the taper is therefore ambiguous and not identified in this framework. I take this as -an honest scope limit, consistent with the paper's careful identification stance, and -report only the taper's robust, $e$-free objects---its static cost -(Section~\ref{sec:static}) and its exact, analytic removal of the dominated region -(Section~\ref{sec:model}). +Table~\ref{tab:behavioural_costs} reports the behavioural cost of each of the +three flat-rate reforms---the raised threshold and the two reduced-rate +bands---measured as the change in revenue relative to the +\pounds85{,}000-notch baseline, alongside the static figure of +Table~\ref{tab:schedule_costs}, for each $e$. For context, the marginal +buncher $n_H(e)$---the highest ability that still finds bunching at the +threshold optimal, the extensive-margin object held fixed here---sits at +\pounds112{,}795, \pounds127{,}382 and \pounds143{,}527 for +$e=0.05, 0.17, 0.32$. \begin{table}[htbp] \centering -\caption{Behavioural revenue effect of the three flat-rate reforms relative to the -\pounds85{,}000-notch baseline, by assumed turnover elasticity $e$, with the static -($e\to0$ limit) figure for comparison. Each behavioural figure re-solves every -firm's iso-elastic optimum~\eqref{eq:isoelastic} under the reform schedule, holding -recovered abilities and $e$ fixed. The final column reports the number of firms that -re-optimise at the illustrative midpoint $e=0.17$. Every behavioural figure is conditional on the -assumed, non-identified $e$. The graduated taper is excluded from the behavioural -costing; see the note below the table and the discussion that follows.} +\caption{Behavioural revenue effect of the three flat-rate reforms relative to +the \pounds85{,}000-notch baseline, by assumed turnover elasticity $e$, with +the static ($e\to0$ limit) figure for comparison. Each behavioural figure +re-solves every firm's optimum within its schedule region +per~\eqref{eq:rescale}, holding $e$ fixed. The final column reports the number +of firms whose effective rate changes at $e=0.17$. Estimates are conditional +on the assumed $e$ (Section~\ref{ssec:simulator}). The graduated taper is +excluded; see the paragraph below.} \label{tab:behavioural_costs} \begin{tabular}{lrrrrr} -\hline +\toprule Reform & Static & $e=0.05$ & $e=0.17$ & $e=0.32$ & Firms ($e{=}0.17$) \\ -\hline +\midrule Raise threshold to \pounds100{,}000 - & $-\pounds508$m & $-\pounds444$m & $-\pounds292$m & $-\pounds111$m & $50{,}155$ \\ + & $-\pounds753$m & $-\pounds753$m & $-\pounds753$m & $-\pounds753$m & $108{,}973$ \\ Reduced rate $10\%$ $[\pounds85\text{k},\pounds105\text{k}]$ - & $-\pounds343$m & $-\pounds322$m & $-\pounds273$m & $-\pounds210$m & $61{,}187$ \\ + & $-\pounds484$m & $-\pounds481$m & $-\pounds475$m & $-\pounds467$m & $137{,}944$ \\ Reduced rate $15\%$ $[\pounds85\text{k},\pounds105\text{k}]$ - & $-\pounds171$m & $-\pounds160$m & $-\pounds135$m & $-\pounds107$m & $51{,}226$ \\ -\hline + & $-\pounds242$m & $-\pounds240$m & $-\pounds235$m & $-\pounds228$m & $137{,}944$ \\ +\bottomrule \end{tabular} \smallskip -{\footnotesize \emph{Note.} The graduated taper is deliberately omitted from this -table. Its behavioural response cannot be credibly priced in the iso-elastic -framework, for the reason set out in the paragraph below; its robust, $e$-free -figures---the static cost of \(-\)\pounds336m and the exact removal of the dominated -region---are reported in Sections~\ref{sec:static} and~\ref{sec:model} instead.} +{\footnotesize \emph{Note.} The graduated taper is omitted: its rate varies +continuously with turnover, so its intensive response is outside the +region-confined solve, and its marginal-rate channel is not represented by the +flat-rate first-order condition. Its $e$-free figures---the static cost of +\(-\)\pounds520m and the exact removal of the dominated region---are in +Sections~\ref{sec:static} and~\ref{sec:model}.} \end{table} -\paragraph{Validation: the $e\to0$ limit.} For the three flat-rate reforms the -simulator should reproduce the static costing as the response vanishes, and it does. -Taking $e\to0$ in the forward solve returns \(-\)\pounds507m for the raised -threshold, \(-\)\pounds343m for the $10\%$ reduced rate, and \(-\)\pounds171m for the -$15\%$ reduced rate---matching the static \(-\)\pounds508m, \(-\)\pounds343m, and -\(-\)\pounds171m of Table~\ref{tab:schedule_costs} to within about \pounds1m. -This is the intended nesting: when no firm responds, the behavioural cost collapses -to the mechanical reclassification effect, so the static costing is the $e=0$ corner -of the same machine, not a separate calculation. The nesting notably does \emph{not} -hold for the graduated taper---a further symptom that the iso-elastic cost cannot -represent the taper's marginal-rate channel, and an additional reason its behavioural -cost is not reported. I separately confirm numerically that -$\mathrm{d}\ln y^{*}/\mathrm{d}\ln(1-\tau)=e$ holds exactly in the solved population -for the flat reforms, so $e$ is indeed the governing knob. +\paragraph{A level rise has no intensive-margin offset.} The raise-to- +\pounds100{,}000 row is identical to its static cost at every $e$, and this is +a result, not a failure to respond. Partition the firms. Those with observed +turnover below \pounds85{,}000 face $f=0$ before and after; nothing changes. +Those released by the raise ($y_{\mathrm{obs}}\in[\pounds85\text{k}, +\pounds100\text{k})$) see their rate fall to zero and expand +per~\eqref{eq:rescale} by the factor $(1-\tau)^{-e}$ (about $+3.9\%$ at +$e=0.17$)---but their expansion is \emph{untaxed}: they have left the VAT +base, so the revenue loss is their full baseline remittance, exactly the +static figure. Those above \pounds100{,}000 face $f=1$ before and after; +nothing changes. The only candidates for a taxed response are released firms +whose expansion would carry them across the new threshold, and for every such +firm the new notch's bunching condition binds (its ability lies strictly below +the new marginal buncher), so it optimally stops at the threshold and remits +nothing. Base broadening from a threshold rise is therefore real economic +activity but generates no VAT: conditional on this model, the static costing +of a level move is not an upper bound that behaviour erodes---it \emph{is} the +behavioural costing on the intensive margin. The simulator asserts this +invariance programmatically (to \pounds0.1m at each swept $e$). + +\paragraph{Reduced-rate offsets are second order.} A reduced-rate band lowers +the rate on band firms from $\tau$ to $r$, so each scales up +by~\eqref{eq:rescale} with $f_1 = r/\tau$: about $+2.0\%$ at the $10\%$ rate +and $e=0.17$, and about $+1.0\%$ at $15\%$. Remittance scales with turnover, +so the offset is roughly the scale gain times the band's (rate-reduced) +remittance---\pounds9m against a static \pounds484m at $e=0.17$ for the $10\%$ +band, reaching \pounds17m ($3.5\%$) only at $e=0.32$. The direction is +uniform---a larger $e$ makes the bands slightly cheaper---but the magnitude +never approaches the static term. Figure~\ref{fig:reform_dist} traces the +costs across the full range of $e$: the raise is exactly flat, the bands +nearly so. + +\paragraph{Validation.} Three properties are asserted programmatically in the +released code on every run: the baseline solve reproduces each firm's observed +turnover exactly (the accounting anchor is internally consistent); the $e\to0$ +behavioural cost equals the static cost to \pounds0.1m for every priced +reform; and the solved response satisfies +$\mathrm{d}\ln y^{*}/\mathrm{d}\ln(1-\tau f)=e$ to machine precision. The +static costing is thus the $e=0$ corner of the same machine, not a separate +calculation. \begin{figure}[htbp] \centering \includegraphics[width=0.78\textwidth]{figures/dynamic_cost_vs_elasticity.png} -\caption{Behavioural reform cost against the assumed turnover elasticity $e$, for -the three flat-rate reforms. Each curve is the change in revenue relative to the -\pounds85{,}000-notch baseline as $e$ varies; the intercept at $e=0$ is the static -cost of Table~\ref{tab:schedule_costs}, onto which the behavioural cost nests as the -response vanishes. As $e$ rises, firms scale turnover up toward their frictionless -optimum~\eqref{eq:rescale}, broadening the taxed base and making each reform cheaper. -The dotted lines mark the swept values $e\in\{0.05,0.17,0.32\}$ of -Table~\ref{tab:behavioural_costs}. The graduated taper is omitted: its behavioural -response is not credibly identified in this framework (see above). All magnitudes are -conditional on the assumed, non-identified $e$.} +\caption{Behavioural reform cost against the assumed turnover elasticity $e$, +for the three flat-rate reforms. Each curve is the change in revenue relative +to the \pounds85{,}000-notch baseline; the intercept at $e=0$ is the static +cost of Table~\ref{tab:schedule_costs}. The raise-to-\pounds100{,}000 line is +exactly flat (no intensive-margin offset); the reduced-rate lines decline by +under 4\% of their static values across the plotted range. Dotted lines mark +the swept values $e\in\{0.05,0.17,0.32\}$. Estimates are conditional on the +assumed $e$ (Section~\ref{ssec:simulator}).} \label{fig:reform_dist} \end{figure} -This section completes the costing framework. Where Section~\ref{sec:static} prices -each reform mechanically and Section~\ref{sec:model} measures the distortion it -removes, the simulator here prices the \emph{level and rate} reforms -\emph{behaviourally}: it lets firms re-optimise turnover as the effective rate -changes and implies that, for any assumed $e$, the base-broadening response would -offset a fraction of the static revenue loss. The layer is bounded by what it can -and cannot identify. The behavioural magnitudes are conditional on an assumed, -non-identified $e$, and so are a sensitivity range rather than forecasts; and the -priced margin is purely \emph{intensive}, since the model re-scales turnover while -holding the extensive bunching response fixed. Crucially, the graduated taper's -behavioural response is \emph{not} credibly identified in this framework: its -base-broadening and marginal-rate channels pull in opposite directions and the -iso-elastic cost cannot net them, so I price it only statically and through its exact -dominated-region removal. The robust anchors of the paper therefore remain the -$e$-free static cost of Section~\ref{sec:static} and the exact dominated region of -Section~\ref{sec:model}; the contribution here is a disciplined, transparent layer -that prices the intensive behavioural response to the level and rate reforms once one -is willing to name an elasticity. +This section completes the costing framework, and its contribution is a +robustness statement. Where Section~\ref{sec:static} prices each reform +mechanically and Section~\ref{sec:model} measures the distortion each removes, +the intensive-margin layer shows that naming an elasticity barely moves the +static numbers: not at all for a level move, and by under $4\%$ for the +reduced-rate bands. The behavioural uncertainty that could move these costings +materially sits on the \emph{extensive} margin---registration, de-registration, +and location choice at the notch---which the synthetic data cannot identify +and which this paper prices only through its exact analytic geometry. diff --git a/paper/Sections/bunching.tex b/paper/Sections/bunching.tex index 1c321ef..a71e444 100644 --- a/paper/Sections/bunching.tex +++ b/paper/Sections/bunching.tex @@ -1,21 +1,50 @@ -\section{Bunching at the VAT threshold} +\section{Bunching and the limits of band-calibrated synthetic data} \label{sec:bunching} This section applies the polynomial counterfactual-density estimator of -\citet{saez2010} and \citet{klevenwaseem2013}---as used on UK VAT data by -\citet{liuetal2021}---to my synthetic firm population at the \pounds85{,}000 -registration threshold prevailing in my 2023--24 data. The estimator is purely -reduced-form: it fits a smooth counterfactual to the empirical turnover density -and reads excess mass off the gap, without imposing any structural model of the -firm. My headline finding is one about my data rather than about firm behaviour. -The estimator returns a sizeable excess-mass spike at the threshold, but a -placebo test shows that this spike is \emph{mechanical}: it is inherited from the -coarse turnover-band targets I calibrate to, not generated by any -location-choice in the synthetic firms. I therefore report the estimate as a -reproduction of a published density step, stress-test it, and make no -behavioural bunching claim and convert no excess mass into an elasticity. I read -this as a transparency result: the open synthetic file faithfully transmits the -administrative pattern, and its limit is reported openly. +\citet{chettyetal2011} and \citet{klevenwaseem2013}---as applied to UK VAT +data by \citet{liuetal2021}---to the synthetic firm population. Its finding is +about the data, not about firm behaviour: every sub-band feature of a +band-calibrated synthetic population is exactly what its targets put there, +and this section demonstrates the point in three directions. The 2023--24 +population's near-threshold density is calibrated to the OBR's published +\pounds1{,}000-band profile (Section~\ref{sec:data}), and the estimator reads +that profile back as excess mass---target inheritance, not behaviour. A +placebo that regenerates the population \emph{without} those targets returns +zero. And the 2024--25 vintage, for which no fine bands are published, +produces a very large \emph{spurious} excess-mass signal sitting exactly on an +HMRC calibration-band edge. Together with a power (recovery) test, these +results establish the section's transparency claim: band-calibrated synthetic +data support no bunching inference in either direction, and any sub-band +feature of such data should be traced to its calibration targets before it is +read as economics. The behavioural evidence on UK VAT bunching remains the +administrative estimate of \citet{liuetal2021}. + +The section also documents a correction. An earlier draft of this paper +reported an excess mass of $8{,}712$ firms at +\pounds85{,}000 that appeared to ``reproduce'' the density step documented in +administrative data. That excess mass was an artifact of a liability +mis-scaling in the generator (net liability set to value added itself rather +than the standard rate applied to value added, inflating per-firm liabilities +roughly fivefold; Section~\ref{sec:data}, footnote), which distorted how the +weight optimiser distributed mass near the threshold. Correcting the scaling +removed the step entirely; the near-threshold profile is now supplied by the +OBR targets instead, as published data rather than an optimiser +side-effect.\footnote{The defect and its diagnosis are recorded +in the replication repository (issue \#15); the near-threshold targets are +issue \#23. A second correction followed: the below-threshold HMRC liability +total, which belongs to voluntary registrants the liability model does not +represent, was initially calibrated against the whole below-threshold +population, draining weights around the fine-target window; on an +intermediate build it also manufactured a spectacular ($E\approx196{,}000$), +specification-robust artifact at the \pounds90{,}000 band edge. It is now an +informational diagnostic (Section~\ref{sec:data}). Aggregate calibration +scores barely moved under any of these changes---the optimiser hit the band +totals every time---which is itself part of the lesson: aggregate fit does +not discipline sub-band shape.} A plausible-looking, literature-adjacent bunching statistic +was manufactured by an accounting bug in the data layer and survived until the +liability accounting was audited. I report this openly because it is the +sharpest available demonstration of the section's thesis. \subsection{Methodology} @@ -31,9 +60,12 @@ \subsection{Methodology} where $c_j$ is the number of firms in bin $j$, $y_j$ is the distance of bin $j$ from the threshold, $q$ is the polynomial order, and $[y^{*}_{-},\,y^{*}_{+}]$ is the excluded window. The fitted polynomial is then projected into the -excluded region to recover the counterfactual density $g(y)$. Excess bunching is -the integrated difference between the observed and counterfactual densities just -below the threshold, +excluded region to recover the counterfactual density $g(y)$, with a +mass-conservation restriction that locates the upper edge of the manipulation +window endogenously (excess mass below the threshold must equal missing mass +above it; Appendix~\ref{app:inference}). Excess bunching is the integrated +difference between the observed and counterfactual densities just below the +threshold, \[ B(y^{*}) \;=\; \int_{y^{*}-\Delta y^{*}}^{y^{*}} g(y)\,\mathrm{d}y \;\approx\; g(y^{*})\,\Delta y^{*}, @@ -43,124 +75,156 @@ \subsection{Methodology} bunching region expressed as a fraction of the threshold---a normalised \emph{ratio}, not an elasticity. The estimator delivers the raw geometry of any density step at the threshold; whether that step reflects firm behaviour is a -separate question, addressed by the placebo test below. - -\subsection{Results} - -Applied to the 2023--24 synthetic data at the \pounds85{,}000 threshold, the -estimator returns a bunching ratio $b = 0.060$ (SE $0.005$) and excess mass of -$8{,}712$ firms (SE $662$), with full inference---bootstrap standard errors and -the mass-conservation restriction that excess mass below the threshold equal -missing mass above it---reported in Appendix~\ref{app:inference} and reproducible -from the released code on the regenerated synthetic data. The observed -density displays a clear step at the threshold: more mass in the \pounds1{,}000 bins -immediately below the cutoff than just above it. - -I want to be precise about what this number is. It is the magnitude of a density -step in my synthetic file, and that step reproduces the discontinuity documented -in UK administrative micro-data by \citet{liuetal2021}: the open synthetic -population transmits the published pattern. It is \emph{not} a measured -behavioural response. The synthetic generator contains no firm location-choice, -so the firms in my file do not---and cannot---adjust their turnover to avoid -registration. Whether the reproduced step nonetheless carries any behavioural -information is exactly what the placebo test settles, and the answer is that it -does not. - -\subsection{Placebo test} -\label{ssec:bunch-placebo} - -The central result of this section is a placebo test that diagnoses where the -excess mass comes from. The test exploits a feature of my calibration targets. -HMRC publishes turnover counts only in coarse bands across the threshold: -$678{,}350$ firms at or below \pounds85{,}000 (an average of about $7{,}981$ -firms per \pounds1{,}000) and $305{,}320$ between \pounds85{,}000 and -\pounds150{,}000 (about $4{,}697$ per \pounds1{,}000). The two band densities -differ, so a step at \pounds85{,}000 is already present in the calibration -target before any firm is generated. Because the generator has no -location-choice, any density discontinuity it produces must be inherited from -this target rather than chosen by firms. - -I therefore remove the step from the target in two ways and re-run the -estimator. In Placebo~A I reweight the existing synthetic firms so that the -per-\pounds1{,}000 density follows a single smooth trend across the threshold, -holding total mass fixed. In Placebo~B I replace the two HMRC band counts with a -split implied by one common density, then regenerate the entire population and -re-calibrate from scratch. The full table is in Appendix~\ref{app:inference}. -The result is decisive: excess mass collapses from $8{,}712$ firms to $0$ under -Placebo~A and to $99$ under Placebo~B---about one per cent of the original -spike---and the bunching ratio turns slightly negative in both. Removing the -step from the calibration target removes essentially all of the bunching. - -The conclusion I draw is plain. The synthetic bunching is inherited from the -coarse HMRC band targets, not generated by firm behaviour, because the generator -has no location-choice. I therefore make no behavioural bunching claim on these -data, and I do not convert the excess mass into a turnover elasticity. The -apparent agreement between my normalised statistic and LLAT's (see below) is a -mechanical coincidence fixed by the band-density ratio, not an independent -behavioural match. This is a credibility result more than a negative one: the -open synthetic file is stress-tested and its limit is reported transparently. -The exercise also sits comfortably with the broader identification critique of -bunching designs, which warns that excess mass need not point-identify a -structural elasticity even in genuine administrative data -\citep{blomquistetal2021, bertanhaetal2023}; here the warning is sharper still, -since the mass is not behavioural to begin with. A recovery test in -Appendix~\ref{app:inference} confirms the null is a property of the data rather -than the estimator: when a behavioural signal of known magnitude is injected into -the step-free population, the same estimator recovers about $90\%$ of it, so it is -both specific (the placebo) and sensitive (the recovery). +separate question. The estimator reports geometry only ($b$, excess mass $E$, +and the mass-conservation objects): no elasticity is computed from it, both +because the identification critique of bunching designs applies +\citep{blomquistetal2021,bertanhaetal2023} and because on these data there is +no behavioural mass to convert. + +\subsection{Results: a target-inherited signal at \pounds85{,}000, a spurious one at \pounds90{,}000} + +Applied to the 2023--24 population at the \pounds85{,}000 threshold, the +estimator returns an excess mass of $E = 7{,}933$ weighted firms: it reads +back the bunching profile that the OBR \pounds1{,}000-band targets place in +the file (Section~\ref{sec:data}). This is target inheritance, not +behaviour---the generator contains no firm location-choice---and the placebo +below proves it by deletion. On the \citet{liuetal2021} normalisation the +target-inherited excess is $b_{\mathrm{LLAT}} = 1.91$, about 1.4 times +their administrative $1.361$; the two are not comparable estimates of the same +object, since LLAT's sample ends in 2014--15 while the OBR profile embeds the +far deeper bunching of the frozen-threshold era (their bunching counts nearly +double between 2017--18 and 2025--26). Mass conservation locates the +manipulation-window edge at the search bound ($y_R = \pounds100$k), +consistent with the OBR profile's missing mass extending past +$+\pounds15$k---as LLAT's own $+\pounds24$k window did. + +Applied to the 2024--25 population at the \pounds90{,}000 threshold---which +has \emph{no} fine targets---the same estimator returns $E = 11{,}072$ and +$b_{\mathrm{LLAT}} = 1.23$: within ten per cent of \citet{liuetal2021}'s +administrative $1.361$. Nothing behavioural produced it. It is the coarse +\pounds90{,}000 band edge, where the \pounds1--\pounds90{,}000 and +\pounds90{,}000--\pounds150{,}000 targets meet, read through the estimator; +its magnitude swings four-fold across estimator specifications +($E$ between roughly $8{,}600$ and $36{,}700$ over the degree--window grid, +Appendix~\ref{app:inference}) and the manipulation-window edge sits at the +search bound. The pair of results is the section's central exhibit +(Figure~\ref{fig:bunch85}): where fine targets exist, the estimator recovers +exactly the shape they encode; where they do not, band geometry alone can +manufacture a bunching statistic in the publishable range of the +literature---a researcher looking to ``validate'' synthetic data against +\citet{liuetal2021} would have found agreement here, and it would have meant +nothing. \begin{figure}[htbp] \centering -\includegraphics[width=0.78\textwidth]{figures/bunching_analysis_85k.png} -\caption{Reproduced density step at the \pounds85{,}000 threshold (2023--24 data -year). The figure shows the observed firm density in the synthetic population and -the polynomial no-bunching counterfactual fitted outside the manipulation -window. The synthetic data reproduce the density step documented in UK -administrative micro-data by \citet{liuetal2021}; the gap below the threshold has -magnitude $b = 0.060$ (a width ratio) and $E = 8{,}712$ firms. These describe the -size of the reproduced step, not a behavioural estimate: the placebo test in -Appendix~\ref{app:inference} shows the step is inherited from the coarse -calibration targets rather than from firm behaviour.} +\subfigure[2023--24 population, \pounds85{,}000: target-inherited profile]{ + \includegraphics[width=0.48\textwidth]{figures/bunching_analysis_85k.png} +} +\hfill +\subfigure[2024--25 population, \pounds90{,}000: band-edge artifact]{ + \includegraphics[width=0.48\textwidth]{figures/bunching_analysis_90k.png} +} +\caption{Observed synthetic firm density and polynomial no-bunching +counterfactual at each vintage's registration threshold. Panel (a): the +2023--24 population reproduces the administratively observed bunching profile +because it is calibrated to the OBR \pounds1{,}000-band targets; the +estimator reads the target-inherited excess back as $E = 7{,}933$ +($b_{\mathrm{LLAT}} = 1.91$). Panel (b): the 2024--25 population has no fine +targets, and its coarse \pounds90{,}000 band edge alone yields +$E = 11{,}072$ with $b_{\mathrm{LLAT}} = 1.23$---within 10\% of the +administrative estimate, coincidentally and unstably. Neither is behavioural: +the generator has no firm location-choice, so all sub-band structure is +inherited from the targets and the weight optimiser.} \label{fig:bunch85} \end{figure} +\subsection{Placebo test} +\label{ssec:bunch-placebo} + +The placebo diagnoses where any threshold-adjacent structure comes from by +manipulating the calibration targets directly. HMRC publishes turnover counts +only in coarse bands across the threshold: in 2023--24, $678{,}350$ firms at +or below \pounds85{,}000 (about $7{,}981$ per \pounds1{,}000) against +$305{,}320$ between \pounds85{,}000 and \pounds150{,}000 (about $4{,}697$ per +\pounds1{,}000), so a band-average step is present in the target before any +firm is generated. In Placebo~A I reweight the synthetic firms so the +per-\pounds1{,}000 density follows a single smooth trend across the threshold, +holding total mass fixed. In Placebo~B I regenerate the entire population and +re-calibrate from scratch with \emph{no} fine structure in the targets at +all: the OBR near-threshold bins are removed and the two HMRC band counts +straddling the threshold are replaced by a split implied by one common +density. The results track the targets exactly. The control---calibrated to +the OBR profile---returns $E = 7{,}933$; Placebo~A returns $E = 0$ +($b = -0.059$); Placebo~B returns $E = 0$ ($b = -0.073$). Deleting the fine +targets deletes the ``bunching''; and where a coarse step is present in the +targets---as at the 2024--25 vintage's \pounds90{,}000 band edge---the +estimator reads it as (artifactual) mass. Inserting or removing structure in +the targets inserts or removes ``bunching'' in the estimates. + +\subsection{Power (recovery) test} +\label{ssec:bunch-recovery} + +A null result is only informative if the estimator could have detected a +signal. I therefore inject a Kleven--Waseem-consistent behavioural response of +known magnitude into the step-free (Placebo~A) population: firms relocate to +just below the threshold from a donor region extending to a true marginal +buncher at \pounds112{,}000---beyond the estimator's exclusion window, as with +genuine bunching---with relocation probability declining linearly in distance +from the threshold. Scored by the headline estimator with no reference to the +known null, injected excess masses of $5{,}000$ and $8{,}000$ weighted firms +are recovered at $49\%$ and $62\%$ respectively, while a small $2{,}000$-firm +injection sits near the detection floor ($15\%$); the estimated +marginal-buncher location is attenuated toward the threshold throughout. The +attenuation has a measured mechanical source: part of the missing-mass region +lies outside the exclusion window, where it pulls the fitted counterfactual +down. The estimator therefore \emph{under}-states a true response, more +severely for small ones, and does not over-state one---so the target-inherited +$E=7{,}933$ at \pounds85{,}000 is, if anything, an attenuated reading of the +targeted profile.\footnote{An earlier +version of this exercise relocated mass entirely within the exclusion window, +which the counterfactual fit cannot see by construction; its reported +``$\sim$90\% recovery'' measured deposit bookkeeping, not estimator power. The +redesigned test is in \texttt{analysis/recovery\_bunching.py}.} + \subsection{Comparison with the literature} \label{ssec:bunch-lit} The behavioural fact in the literature is administrative. \citet{liuetal2021} -(hereafter LLAT) document genuine bunching at the same \pounds85{,}000 UK VAT -notch in HMRC micro-data, over a manipulation window of $-\pounds14$k to -$+\pounds24$k, with an excess-bunching ratio of $b = 1.361$ (SE $0.202$). If I -normalise my synthetic excess mass to the same statistic I obtain -$b_{\mathrm{LLAT}} = 0.94$, of similar order of magnitude. I stress that this -proximity is not an independent behavioural confirmation. As the placebo test -above shows, my number is a mechanical reflection of the band-density ratio in -the HMRC targets; its closeness to LLAT's behavioural estimate is a coincidence -of that ratio rather than a second measurement of the same response. - -What does carry across is a piece of institutional context that both settings -share. Like LLAT, the UK market features substantial voluntary registration -below the threshold---LLAT report that almost half (roughly $43\%$) of eligible -below-threshold firms register voluntarily---which dampens observed bunching -relative to a pure turnover-tax notch and which my turnover-tax-notch model -abstracts from. For wider order-of-magnitude context, \citet{obr2023vat} count -firms holding turnover below the frozen threshold over a \emph{wide} band (rising -from $23{,}000$ in 2017--18 to $\sim 44{,}000$ in 2025--26, with foregone -turnover of \pounds110m rising to \pounds350m); this is a different object from a -near-threshold spike and is cited only as corroborating context, not as a -like-for-like match. +(hereafter LLAT) document genuine bunching at the UK VAT registration notch in +HMRC micro-data over 2004--05 to 2014--15, during which the threshold rose +from \pounds58{,}000 to \pounds81{,}000, with an excess-bunching ratio of +$b = 1.361$ (SE $0.202$) around the year-specific threshold and a manipulation +window of $-\pounds14{,}000$ to $+\pounds24{,}000$. My data's +$b_{\mathrm{LLAT}} = 1.91$ is not a second estimate of their parameter: it is +the OBR target profile read back through their normalisation, on a +deeper-bunching era; and the uncalibrated 2024--25 vintage's +$b_{\mathrm{LLAT}} = 1.23$, despite sitting within 10\% of their estimate, +is not one either---it is band geometry.\footnote{The earlier draft's +$b_{\mathrm{LLAT}} = 0.94$, read against LLAT's $1.361$, illustrated how a +band-inherited artifact can land in the publishable range of the literature; +that artifact's disappearance under the liability correction, and its +replacement by an explicit published-data target, are reported above.} What does +carry across is institutional context: LLAT report that almost half (roughly +$43\%$) of eligible below-threshold firms register voluntarily, which dampens +observed bunching relative to a pure notch and which motivates the +voluntary-retention sensitivity of Section~\ref{sec:static}. For wider +order-of-magnitude context, \citet{obr2023vat} count firms holding turnover +below the frozen threshold over a \emph{wide} band (rising from $23{,}000$ in +2017--18 to about $44{,}000$ in 2025--26, with foregone turnover of +\pounds110m rising to \pounds350m); this is a different object from a +near-threshold spike and is cited only as context. \subsection{Reduced-form evidence and the dominated region} -The placebo sharpens, rather than weakens, the case for grounding the policy -analysis in structure. The reduced-form density step cannot price reforms---it -has no single point of excess mass to forward-map onto a change in the -\emph{shape} of the schedule---and on these data it cannot even be read -behaviourally at all. What the structure of Section~\ref{sec:model} -\emph{does} deliver exactly, for every reform considered, is the notch's -dominated region and how each schedule change alters it. It is precisely because -the reduced-form bunching is non-identifying here that the exact dominated region -carries the distortion characterisation. A fully behavioural forward solve that -re-prices each firm's turnover under counterfactual schedules requires -further parameter-sensitive assumptions---an assumed turnover elasticity in -particular---and is developed in Section~\ref{sec:behavioural}. +These results sharpen, rather than weaken, the case for grounding the policy +analysis in structure. The reduced-form density around the threshold cannot +price reforms---it has no single point of excess mass to forward-map onto a +change in the \emph{shape} of the schedule---and on band-calibrated synthetic +data it cannot be read behaviourally at all, in either direction. What the +structure of Section~\ref{sec:model} \emph{does} deliver exactly, for every +reform considered, is the notch's dominated region and how each schedule +change alters it. It is precisely because the reduced-form bunching is +non-identifying here that the exact dominated region carries the distortion +characterisation. The behavioural layer that re-prices each firm's turnover +under counterfactual schedules---conditional on an assumed turnover +elasticity---is developed in Section~\ref{sec:behavioural}. diff --git a/paper/Sections/conclusion.tex b/paper/Sections/conclusion.tex index 32ac1a2..5a63a94 100644 --- a/paper/Sections/conclusion.tex +++ b/paper/Sections/conclusion.tex @@ -7,105 +7,129 @@ \section{Conclusion} infrastructure rather than a structural identification result: I make no claim to recover policy-invariant firm primitives, unlike \citet{garicano2016} and \citet{gourioroys2014}. The analysis is anchored to the 2023--24 data year, in -which the statutory threshold was \pounds85{,}000. Table~\ref{tab:summary} -collects the headline objects. +which the statutory threshold was \pounds85{,}000, with a second 2024--25 +population (threshold \pounds90{,}000) for the forward sweep. +Table~\ref{tab:summary} collects the headline objects. \begin{table}[t] \centering -\caption{Summary of headline estimates. This table consolidates results reported -and defined in the body sections cross-referenced below; it is a reference summary, -not a new analysis. All quantities refer to the \pounds85{,}000 data-year baseline. -Static revenue figures are 2025--26.} +\caption{Summary of headline estimates, consolidating results defined in the +body sections cross-referenced below. Rows 1--2 are 2025--26 figures (the +anchor on the 2023--24 population, the sweep on the 2024--25 population at its +\pounds90{,}000 baseline); the remaining rows refer to the \pounds85{,}000 +data-year baseline.} \label{tab:summary} \small \begin{tabular}{@{}llll@{}} \toprule Object & Symbol / definition & Value & Source \\ \midrule -Static cost, \pounds85k to \pounds90k anchor & --- & $\approx-\pounds175$m & \S\ref{sec:static} \\ -Static sweep, \pounds90k baseline & per \pounds5k step & $\sim\pounds150$--$220$m & Table~\ref{tab:static_revenue} \\ -Dominated region (misallocation zone) & $a=T^{*}\tau/(1-\tau)$ & \pounds21{,}250 & \S\ref{ssec:dominated} \\ -Firms in the dominated band (weighted) & --- & $\approx137{,}000$ & \S\ref{ssec:dominated} \\ -Behavioural raise-to-\pounds100k ($e=0.05$--$0.32$) & $e$-sensitivity range & $-\pounds444$m to $-\pounds111$m & \S\ref{sec:behavioural} \\ +Static cost, \pounds85k to \pounds90k anchor & dereg.\ / retention conventions & $-\pounds323$m / $-\pounds184$m & Section~\ref{sec:static} \\ +Static sweep, \pounds90k baseline & per \pounds5k step & \pounds230m--\pounds265m & Table~\ref{tab:static_revenue} \\ +Dominated region & $a=T^{*}\tau/(1-\tau)$ & \pounds21{,}250 & Section~\ref{ssec:dominated} \\ +Firms in the dominated band (weighted) & --- & $\approx156{,}000$ & Section~\ref{ssec:dominated} \\ +Raise to \pounds100k, static and behavioural & invariant in $e$ & $-\pounds753$m & Sections~\ref{sec:static}, \ref{sec:behavioural} \\ +Graduated taper, static & --- & $-\pounds520$m & Section~\ref{ssec:schedule_costs} \\ \bottomrule \end{tabular} \end{table} -\paragraph{Findings.} Four results stand out. First, the static pipeline -reproduces HMRC's costing of the \pounds85{,}000 to \pounds90{,}000 move to within -about \pounds10m (\pounds175m against \pounds185m)---a consistency check, since the -microdata are calibrated to HMRC aggregates---and prices a menu of level and -schedule reforms on a common \pounds85{,}000/\pounds183.6bn base: \(-\)\pounds508m -to raise the threshold to \pounds100{,}000, \(-\)\pounds336m for a graduated taper, -and \(-\)\pounds343m and \(-\)\pounds171m for $10\%$ and $15\%$ banded reduced -rates. Second, the notch's distortion is captured exactly by its dominated region, -the \citet{klevenwaseem2013} width $a=T^{*}\tau/(1-\tau)=\pounds21{,}250$---an -accounting identity rather than a new structural result, but one spanning a -populous range of roughly $137{,}000$ firms---a range that fiscal drag widens -further: with the \pounds90{,}000 threshold now frozen in nominal terms, ageing -the turnover distribution forward draws about $14\%$ more firms into the dominated -region by 2028--29 (roughly $130{,}000$ to $148{,}000$), with the just-below, -bunching-exposed band growing about $9.5\%$ (roughly $41{,}000$ to $45{,}000$). -Setting cost against distortion is -instructive: raising the threshold is the most expensive option yet merely -relocates the zone, and a banded reduced rate does not shrink the distortion -either---it lowers the largest single notch (from \pounds17{,}000 to \pounds12{,}750 -at a $15\%$ band) but, because the band reverts to the standard rate at its -\pounds105{,}000 top, adds a secondary notch, leaving the total dominated-turnover -width essentially unchanged (\pounds21{,}562 at $15\%$, \pounds22{,}569 at $10\%$, -both marginally above the \pounds21{,}250 baseline). Only the graduated taper, -being continuous, removes the distortion entirely, and for less. Third, the open -data reproduce the published density step at the threshold, but a placebo test -shows the apparent excess mass is inherited from the coarse HMRC band targets -rather than firm behaviour---it collapses from $8{,}712$ to roughly $99$ weighted -firms when the target step is removed---so behavioural bunching is not identified -on these data; the bunching ratio and implied elasticities are relegated to the -appendix and labelled non-identified, and the behavioural evidence on threshold -bunching remains the administrative estimate of \citet{liuetal2021}. Fourth, the -framework also prices each reform \emph{behaviourally}, with a structural simulator -that re-optimises firms under the reformed schedule conditional on an assumed -turnover elasticity $e$ (Section~\ref{sec:behavioural}). Because $e$ is not -identified on these synthetic data---the placebo shows the bunching is -mechanical---I report the behavioural cost as an $e$-sensitivity range that nests -the static cost as $e\to0$. Conditional on an assumed $e$, modelled responses partly -offset the static costs: at an illustrative midpoint $e=0.17$ the raise to -\pounds100{,}000 falls from \pounds508m static to about \pounds292m, the $10\%$ -band from \pounds343m to \pounds273m, and the $15\%$ band from \pounds171m to -\pounds135m, as firms broaden the base when the effective rate falls. The -$e$-range $\{0.05,0.17,0.32\}$ is a sensitivity range whose only externally -anchored point is the lower end $e=0.05$; the $0.17$ and $0.32$ values are implied -by the notch geometry, not identified from the data. I report no behavioural cost for the -graduated taper: its behavioural response is not credibly identified, because its -base-broadening and marginal-rate channels pull in opposite directions and the -iso-elastic cost cannot net them, so only its static cost and dominated-region -removal are reported. The static costs and the dominated region remain the robust, -$e$-free anchors; the behavioural magnitudes are conditional on the assumed $e$. +\paragraph{Findings.} Four results stand out. First, the static pipeline prices +level and schedule reforms on a common \pounds85{,}000 / \pounds184.8bn base +(\(-\)\pounds753m to raise the threshold to \pounds100{,}000, \(-\)\pounds520m +for a graduated taper, \(-\)\pounds484m and \(-\)\pounds242m for $10\%$ and +$15\%$ banded reduced rates), and its anchor costing of the \pounds85{,}000 to +\pounds90{,}000 move tracks HMRC's published figure once the deregistration +convention is stated: the full-deregistration convention overshoots +($-$\pounds323m against the published $-$\pounds185m in 2025--26, consistent +with the official costing's phased registration response), the retention +convention matches the published 2025--26 figure to \pounds1m +($-$\pounds184.1m against $-$\pounds185m), and both conventions reproduce the +official profile's +narrowing and its 2028--29 sign change under the uprated counterfactual +threshold path. -\paragraph{Limitations and future work.} The model is a turnover-tax-notch -approximation: it treats VAT as a cost on turnover, whereas real VAT is levied on -value added with input reclaim, and roughly 43\% of below-threshold firms register -voluntarily \citep{liuetal2021}, so the effective notch is smaller than a flat -treatment implies. The dominated-region width indexes the misallocation distortion -only and omits the compliance and administrative-cost saving that a \emph{higher} -threshold delivers by removing small firms from VAT---the classic rationale for a -high registration threshold \citep{keenmintz2004}---so the efficiency comparison is -partial; a full welfare/MVPF accounting would net these compliance costs against -the misallocation distortion. The menu reforms are also costed only in aggregate: +Second, the notch's distortion is captured exactly by its dominated region, the +\citet{klevenwaseem2013} width $a=T^{*}\tau/(1-\tau)=\pounds21{,}250$---an +accounting identity rather than a new structural result, but one that is +invariant to the firm's input share under the value-added formulation and +spans a populous range of roughly $156{,}000$ weighted firms. Setting cost +against distortion on this metric: raising the threshold carries the largest +static cost and relocates the region without changing its width; a banded +reduced rate lowers the largest single notch (from \pounds17{,}000 to +\pounds12{,}750 at $15\%$) but adds a secondary notch at the band top, leaving +the total dominated width essentially unchanged (\pounds21{,}562 at $15\%$, +\pounds22{,}569 at $10\%$); only the graduated taper removes the dominated +region, at a static cost of \(-\)\pounds520m against the $10\%$ band's +\(-\)\pounds484m, which removes none of it. The metric indexes misallocation +only; the limitations paragraph below states what it omits. + +Third, the synthetic data carry a transparency lesson: sub-band structure in +band-calibrated microdata is exactly what its targets put there, so it +supports no bunching inference in either direction. The 2023--24 population's +near-threshold profile is calibrated to the OBR's published +\pounds1{,}000-band data, and the estimator reads it back as target-inherited +excess mass ($E=7{,}933$); a placebo that regenerates without the fine +targets returns zero; and the 2024--25 vintage, which has no fine targets, +shows the coarse \pounds90{,}000 band edge alone yielding an excess-bunching +statistic within 10\% of the administrative estimate---coincidental, +specification-unstable, and behaviour-free. A redesigned power test confirms +the estimator detects moderate genuine signals (recovering half to two-thirds +of 5{,}000--8{,}000-firm injections, attenuated, never inflated). An earlier draft +of this paper reported ``reproducing'' the administrative density step at +\pounds85{,}000 when a liability mis-scaling manufactured it; the paper now +documents the artifact, its correction, and the replacement of optimiser +side-effects with published fine-band targets as the sharpest demonstration of +the lesson. The behavioural evidence on threshold bunching remains the +administrative estimate of \citet{liuetal2021}. + +Fourth, the behavioural layer's contribution is a robustness statement: on the +intensive margin, naming an elasticity barely moves the static costings. A +pure level rise has exactly zero intensive-margin offset at every $e$---released +firms leave the VAT base, so their expansion is untaxed, and boundary-crossers +optimally bunch below the new threshold---and the reduced-rate bands' offsets +stay under $6\%$ of the static cost across $e\in\{0.05,0.17,0.32\}$ (the +$10\%$ band falls from \pounds484m to \pounds475m at $e=0.17$). The +graduated taper is priced only statically: its continuously varying rate is +outside the flat-rate machinery. The behavioural uncertainty that could move +these costings materially sits on the extensive margin---registration and +location choice at the notch---which these data cannot identify and the paper +prices only through its exact analytic geometry. + +\paragraph{Limitations and future work.} The model abstracts from several +margins, each stated where it binds. It has no firm location choice and no +extensive-margin response; voluntary registration enters only as a +registration-rate parameter and a retention sensitivity, not a choice model; +net-repayment traders are outside the liability model +(Section~\ref{sec:data}); the statutory rolling registration test is +approximated by a data-year turnover test on total rather than taxable +turnover; the near-threshold profile rests on two stated assumptions (the +2023--24 interpolation between the OBR's 2019--20 outturn and 2025--26 +frozen-threshold projection, and the shape-only, side-consistent treatment +of the OBR bins, whose chart universe differs from the ONS frame); +and the calibrated revenue bases sit about $5.8\%$ above the HMRC +liability-by-band target sums, with band-level calibration between $79\%$ and +$94\%$ (Section~\ref{sec:static}, footnote). The dominated-region width +indexes the misallocation distortion only and omits the compliance and +administrative-cost saving that a \emph{higher} threshold delivers by removing +small firms from VAT---the classic rationale for a high registration threshold +\citep{keenmintz2004}---so the efficiency comparison is partial; it likewise +books no compliance saving to the taper or reduced rate, which keep every band +firm inside the VAT system, and a taper's administrability (an effective rate +that depends on annual turnover cannot be charged on invoices, so a real +design would operate as remittance-side relief) is a design question the +costing does not address. The menu reforms are costed only in aggregate: because VAT liability by sector is excluded from the calibration optimiser -(Section~\ref{sec:data}), the framework does not yet report the sectoral incidence -of a taper or reduced rate---which sectors gain and by how much---a cut of obvious -policy interest that I leave to future work. The microdata are synthetic and calibrated to coarse aggregate -bands---which is why the behavioural magnitudes are reported only conditional on an -assumed elasticity rather than as estimates---and the analysis is -partial-equilibrium, abstracting from pass-through into prices \citep{benedek2015, -belloncopestake2022}. The conditional behavioural costing is now done -(Section~\ref{sec:behavioural}), but on synthetic data the turnover elasticity $e$ -it requires is assumed, not identified; the chief outstanding task is therefore to -\emph{identify} $e$ from administrative micro-data, which would turn the present -$e$-sensitivity range into a point estimate. A welfare/MVPF analysis modelling -value added and input reclaim would in turn convert the dominated-region distortion -into cost--benefit terms and support revenue-neutral schedule designs that -neutralise the notch at no net fiscal cost. Above all, validation against -administrative firm-level data with -genuine location choice would replace the present internal-consistency checks with -out-of-sample tests and let the framework identify firm bunching directly. +(Section~\ref{sec:data}), the framework does not yet report the sectoral +incidence of a taper or reduced rate, a cut of obvious policy interest, and +the split of band-total liability across sub-band turnover---which the anchor +and relocation costings use---rests on the generator's common input-share +distribution rather than on sector-composition data. The +analysis is partial-equilibrium, abstracting from pass-through into prices +\citep{benedek2015,belloncopestake2022}. The chief outstanding empirical task +is to \emph{identify} the turnover elasticity from administrative micro-data, +which would turn the $e$-sensitivity range into a point estimate; a +welfare/MVPF accounting would net compliance costs against the misallocation +distortion and support revenue-neutral schedule designs. Above all, validation +against administrative firm-level data with genuine location choice would +replace the present internal-consistency checks with out-of-sample tests. diff --git a/paper/Sections/data.tex b/paper/Sections/data.tex index 8350d78..6796f32 100644 --- a/paper/Sections/data.tex +++ b/paper/Sections/data.tex @@ -9,30 +9,53 @@ \section{Data} calibrate-to-published-aggregates approach underlies open household-level tax-benefit microsimulation \citep{policyengine}; here I apply it at the firm level. The generator takes the registration threshold as a parameter and is -documented in Appendix~\ref{app:data}. +documented in Appendix~\ref{app:data}; I build one population for 2023--24 +(threshold \pounds85{,}000), the paper's primary data year, and one for +2024--25 (threshold \pounds90{,}000), used for the forward sweep of +Section~\ref{sec:static}. The archived CSV inputs in this repository remain the reproduction source for the paper's reported numbers; a pinned migration snapshot also represents the -same 2024--25 numeric target surface through PolicyEngine Ledger and the +same numeric target surface through PolicyEngine Ledger and the experimental Populace firm generator, and Appendix~\ref{app:data} reports the parity check between that shared source-of-truth path and the paper inputs. \paragraph{Construction.} Index firms by $i$. For each sector $s$ and ONS turnover band $b=[\underline{b},\overline{b}]$, the \emph{UK Business: Activity, -Size and Location} table gives a firm count $N_{s,b}$, and I draw $N_{s,b}$ firms -with within-band turnover +Size and Location} table gives a business count $N_{s,b}$, and I draw $N_{s,b}$ +firms with within-band turnover \[ y_i \;=\; \underline{b} + (\overline{b}-\underline{b})\,u_i + \varepsilon_i, \qquad u_i \sim \mathcal{U}(0,1), \;\; \varepsilon_i \sim \mathcal{N}(0,\sigma_b^2), \] truncated below at zero, where $\varepsilon_i$ smooths the within-band -distribution. Each firm is given input expenditure $x_i = \rho_i\,y_i$, with the -input--output ratio $\rho_i$ drawn from a rescaled Beta distribution with -sector-specific shifts and bounded to $\rho_i \in [0.6,1.5]$; its value added, the -net VAT base, is $v_i = y_i - x_i$ (the upper bound $\rho_i=1.5$ permits $x_i>y_i$, -and hence negative value added, for a non-trivial share of firms in the calibrated -population). Employment is assigned from the ONS -employment-band shares. +distribution. The ONS register covers businesses registered for VAT and/or +PAYE---about 2.7 million---so the synthetic population represents that +registered-business frame, not the full business population of roughly +5.6 million in the DBT business population estimates; the difference is +concentrated below the threshold and matters for threshold \emph{cuts}, which I +flag where relevant. Each firm is given input expenditure $x_i = \rho_i\,y_i$, +with the input--output ratio $\rho_i$ drawn from a rescaled Beta distribution +with sector-specific shifts, clamped to $\rho_i \in [0.1, 0.95]$ (mean about +0.6, so value added averages about 40\% of turnover, in line with the UK +non-financial business economy). Its net VAT liability is the standard rate +applied to its value added, +\[ + v_i \;=\; \tau\,(y_i - x_i), \qquad \tau = 0.20, +\] +so every firm's net rate $v_i/y_i = \tau(1-\rho_i)$ lies in $[1\%, 18\%]$, +strictly positive and below the statutory cap of 20\%. The model therefore +abstracts from net-repayment traders (firms with zero-rated outputs whose input +reclaim exceeds output VAT---HMRC's negative-liability column); representing +them requires rated-structure detail (zero, reduced, and exempt output shares) +that the public aggregates do not resolve by band. Employment is assigned from +the ONS employment-band shares.\footnote{An earlier draft of this generator set +$v_i = y_i - x_i$ with $\rho_i \in [0.6, 1.5]$---omitting the factor $\tau$, so +per-firm liabilities were about five times too large and a large minority of +firms carried negative value added. The weight optimiser compensated on the +band totals, leaving aggregate calibration scores similar but distorting the +near-threshold density; Section~\ref{sec:bunching} documents the consequence +and the correction.} The base population reproduces the ONS structure but not the HMRC VAT-registered totals, so I re-weight it. Each firm receives a strictly @@ -42,7 +65,7 @@ \section{Data} \widehat{T}_k(\theta) \;=\; \sum_i a_{ki}\, w_i , \] where $a_{ki}$ is firm $i$'s contribution to target $k$: an indicator of band or -sector membership for a count target, and the firm's liability $v_i$ for a +sector membership for a count target, and the firm's net liability $v_i$ for a VAT-liability target. I choose $\theta$ to minimise a symmetric relative-error loss with per-target importance weights $\lambda_k$, \[ @@ -52,53 +75,114 @@ \section{Data} \] the final term a mean absolute penalty on the log-weights. The targets are the HMRC VAT-registered counts by turnover band and by sector, the HMRC net VAT -liability by turnover band, and the ONS employment-band totals; turnover-band -targets carry the largest $\lambda_k$, followed by VAT liability by band. VAT -liability by sector is reported as an informational diagnostic but excluded from -the optimizer, because the current generator fixes firm inputs rather than -calibrating the input/output tax structure by sector. The problem is -solved by gradient descent, and the symmetric loss keeps targets of very different -magnitudes on a common scale. +liability by turnover band, the ONS employment-band totals, and---for the +2023--24 vintage---the OBR's published near-threshold profile: the March 2023 +\emph{Economic and Fiscal Outlook} Chart~C data give HMRC counts of businesses +by \pounds1{,}000 turnover band over \pounds65{,}000--\pounds90{,}000 +\citep{obr2023vat}, which I interpolate to the 2023--24 data year between the +2019--20 outturn and the OBR's 2025--26 frozen-threshold projection. All twenty-five bins enter as \emph{shape} targets, applied +side-consistently: each side of the threshold takes the OBR profile's +within-side shape, normalised over its own window +(\pounds65{,}000--\pounds85{,}000 below; \pounds85{,}000--\pounds90{,}000 +above) and scaled to the synthetic population's own mass there. The chart +counts HMRC traders---a different unit and, below the threshold, a +substantially narrower universe than the ONS business frame---so its levels +are not imported on either side. An earlier build that mixed conventions +(direct counts above the threshold, frame-scaled shape below) placed more +mass just above the threshold than just below it, inverting the +administrative profile's cross-threshold ordering; under side-consistent +scaling the cross-threshold step comes from the frame's own band structure +and the OBR data supply only the within-side geometry---the rise into the +threshold and the decline beyond it. These fine targets +pin the near-threshold density to the administratively observed bunching +profile---the region that coarse bands alone leave to the weight optimiser +(Section~\ref{sec:bunching}). No fine bands are published for the +\pounds90{,}000 threshold era, so the 2024--25 vintage keeps coarse bands +only. Turnover-band and near-threshold targets carry the largest $\lambda_k$, +followed by VAT liability by band. Two liability dimensions are reported as +informational diagnostics but excluded from the optimizer. VAT liability by +sector is excluded because the generator draws a common input-share +distribution with sector shifts rather than calibrating the input/output tax +structure by sector. The below-threshold liability band +(\pounds1--threshold, \pounds1.46bn in 2023--24) is excluded because that +total is remitted by voluntary registrants---input-reclaim traders averaging +about \pounds2{,}150 of net remittance---whom the model's +standard-rate-on-value-added liability does not represent +(Section~\ref{sec:background}); imposing it on the whole below-threshold +population would force the optimiser to suppress weights in the +\pounds50{,}000--\pounds85{,}000 region, distorting the near-threshold +shape the fine targets exist to pin. The problem is +solved by gradient descent, and the symmetric loss keeps targets of very +different magnitudes on a common scale. -A firm is registered with certainty -when its turnover exceeds the threshold $T^{*}$. Below the threshold it registers -voluntarily with probability $r = M / n_{<}$, where $M$ is the HMRC count of -registered firms in the \pounds1--threshold band and $n_{<}$ is the unweighted -number of synthetic below-threshold firm rows. This sets the expected row-level -voluntary-registration rate; I do not treat below-threshold voluntary -registration as a separate weighted calibration target. The resulting dataset -comprises approximately -$2.94$~million firm records, weighted to represent roughly $2.5$~million UK firms; -checked for consistency against the official sources along every calibrated -dimension, it attains an overall calibration accuracy of about $90\%$. This -headline is the mean of five calibrated-dimension scores, each clipped at zero -as $\max\{0,1-\lvert \widehat{T}-T\rvert/\lvert T\rvert\}$; it excludes the -VAT-liability-by-sector diagnostic described above. +A firm is registered with certainty when its data-year turnover exceeds the +threshold $T^{*}$. This is an approximation to the statutory test, which is a +rolling 12-month test on \emph{taxable} turnover with a roughly two-month +registration lag, a forward-looking 30-day test, and an exception for temporary +breaches (Section~\ref{sec:background}); the model also registers firms whose +turnover is largely exempt, whom the law would not require to register. For a +single-year cross-section calibrated to registered-population totals these +timing and composition wedges are second order for the aggregates, but they are +worth naming: the HMRC band tables classify traders by total declared outputs +(VAT-return Box 6), and the ONS turnover measure is likewise total turnover, so +the running variable throughout is total rather than taxable turnover. Below +the threshold a firm registers voluntarily with probability $r = M / n_{<}$, +where $M$ is the HMRC count of registered firms in the \pounds1--threshold band +and $n_{<}$ is the unweighted number of synthetic below-threshold firm rows. +This sets the expected row-level voluntary-registration rate; I do not treat +below-threshold voluntary registration as a separate weighted calibration +target. The resulting dataset comprises approximately $2.94$~million firm +records per vintage, weighted to represent roughly $2.5$~million registered +businesses. Checked against the official sources along every calibrated +dimension, the vintages attain overall calibration accuracies of 89.2\% +(2023--24) and 92.8\% (2024--25), with dimension scores ranging from 77.9\% +(2023--24 employment bands) to 94.2\%; Appendix~\ref{app:data} reports +the full table. The headline is the mean of five calibrated-dimension scores, +each clipped at zero as $\max\{0,1-\lvert \widehat{T}-T\rvert/\lvert T\rvert\}$; +it excludes the VAT-liability-by-sector diagnostic described above. -\paragraph{The registration threshold in the data.} My data are for the 2023--24 -year, in which the statutory threshold was \pounds85{,}000. The firm density steps -down at the threshold---from roughly $10{,}200$ to $6{,}600$ firms per -\pounds1{,}000 turnover band---reflecting the incentive to remain below the -registration cutoff, with a second, smaller step at \pounds150{,}000, the ceiling -of the VAT Flat Rate Scheme (Figure~\ref{fig:turnover_dist}). I note, however, -that HMRC publishes firm counts only in coarse turnover bands across the -threshold, so the density step at \pounds85{,}000 in the synthetic data is -inherited from these aggregate targets rather than from any modelled firm -behaviour; Section~\ref{sec:bunching} quantifies this with a placebo test. -Counterfactual -policies---including the \pounds85{,}000 to \pounds90{,}000 reform and the forward -threshold sweep of Section~\ref{sec:static}---are evaluated on these firms by -re-applying the registration rule to the microdata for the static costings. I -hold the empirical turnover distribution fixed for these static costings. A -fully behavioural forward solve that re-prices firms under counterfactual -schedules---conditional on an assumed turnover elasticity---is developed in +\paragraph{The registration threshold in the data.} My primary data year is +2023--24, when the statutory threshold was \pounds85{,}000. The HMRC band +targets step down across the threshold---678{,}350 firms in the +\pounds1--\pounds85{,}000 band against 305{,}320 in +\pounds85{,}000--\pounds150{,}000, or roughly $8{,}000$ against $4{,}700$ firms +per \pounds1{,}000 of band width---and the calibrated population necessarily +inherits that band-average step. The \emph{local} shape within a few thousand +pounds of the threshold is pinned by the OBR near-threshold targets described +above: the calibrated density rises into the threshold (about $13{,}800$ firms +per \pounds1{,}000 in the \pounds84{,}000--\pounds85{,}000 bin), steps down +across it (about $10{,}300$ just above), and declines through the band---the +administratively observed bunching profile \citep{obr2023vat,liuetal2021}, +present in the file because it is targeted, not because any synthetic firm +chooses it. In an earlier build without these targets the local shape was an +unpinned optimiser equilibrium (and, under the pre-correction liability scale, +a spurious bunching look-alike); the central data caveat of the paper stands +in all three configurations: no sub-band feature of band-calibrated synthetic +data carries behavioural information beyond what its targets put there +(Section~\ref{sec:bunching} quantifies this with placebo and recovery tests). +Counterfactual policies---including the \pounds85{,}000 to \pounds90{,}000 +reform and the forward threshold sweep of Section~\ref{sec:static}---are +evaluated on these firms by re-applying the registration rule to the microdata +for the static costings, holding the empirical turnover distribution fixed. A +behavioural layer that re-prices firms under counterfactual schedules, +conditional on an assumed turnover elasticity, is developed in Section~\ref{sec:behavioural}. \begin{figure}[htbp] \centering \includegraphics[width=0.74\textwidth]{figures/turnover_distribution_85k.png} \caption{Synthetic firm turnover distribution (weighted firm counts, -\pounds1{,}000 bins), 2023--24. The density steps down at the \pounds85{,}000 -registration threshold and again at the \pounds150{,}000 Flat Rate Scheme ceiling.} +\pounds1{,}000 bins), 2023--24. The near-threshold profile---rising into the +\pounds85{,}000 threshold and stepping down across it---is calibrated to the +OBR's published \pounds1{,}000-band counts and is therefore target-inherited, +not behavioural (Section~\ref{sec:bunching}). Levels reflect the ONS +VAT/PAYE-registered frame: unregistered businesses---most of the +below-threshold mass, and most of the cross-threshold cliff, in all-business +administrative charts---are outside it, so level comparisons to such charts +are not like-for-like. The steps at \pounds90{,}000 (about $9{,}100$ firms +per \pounds1{,}000 in the last OBR-pinned bin against about $6{,}800$ in the +first unpinned bin) and \pounds150{,}000 are calibration-target +boundaries---the top of the OBR fine-band window and an HMRC band edge +respectively---not features of the underlying firm distribution.} \label{fig:turnover_dist} \end{figure} diff --git a/paper/Sections/intro.tex b/paper/Sections/intro.tex index 055bdfe..596b871 100644 --- a/paper/Sections/intro.tex +++ b/paper/Sections/intro.tex @@ -1,10 +1,10 @@ \section{Introduction}\label{sec:intro} -The United Kingdom's Value Added Tax (VAT) applies above a registration threshold that is among the highest in the OECD \citep{hoc_vat,hmrc_threshold}. The threshold is a \emph{notch} rather than a kink: once a firm's annual taxable turnover crosses it, the standard 20\% rate falls due on all of the firm's turnover, not only on the part above the threshold, so registration produces a discrete jump in liability rather than a marginal one. The threshold falls in a dense part of the firm distribution. Figure~\ref{fig:dist}(a) shows that UK firms are concentrated at the lower end of the turnover distribution, and Figure~\ref{fig:dist}(b) shows that VAT-registered firms are concentrated in the turnover bands at and below the threshold, so the notch applies to a large number of firms. +The United Kingdom's Value Added Tax (VAT) applies above a registration threshold that is the highest in the OECD alongside Switzerland \citep{hoc_vat,hmrc_threshold}. The threshold is a \emph{notch} rather than a kink: once a firm's annual taxable turnover crosses it, VAT falls due on the firm's whole base, not only on the part above the threshold, so registration produces a discrete jump in liability rather than a marginal one. The threshold falls in a dense part of the firm distribution. Figure~\ref{fig:dist}(a) shows that VAT- and PAYE-registered UK businesses are concentrated at the lower end of the turnover distribution, and Figure~\ref{fig:dist}(b) shows that the VAT-registered population per \pounds1{,}000 of turnover is densest at and below the threshold, so the notch applies to a large number of firms. \begin{figure}[htbp] \centering -\subfigure[All firms (ONS, 2023--24)]{ +\subfigure[VAT- and/or PAYE-registered businesses (ONS, 2023--24)]{ \includegraphics[width=0.48\textwidth]{figures/firms_by_turnover_band_85k.png} } \hfill @@ -12,10 +12,15 @@ \section{Introduction}\label{sec:intro} \includegraphics[width=0.48\textwidth]{figures/vat_firms_by_turnover_band_85k.png} } \caption{The UK firm-size distribution and VAT registration, 2023--24 (threshold -\pounds 85{,}000). Panel (a): number of firms by turnover band. Panel (b): number -of VAT-registered firms by turnover band. Source: panel (a), ONS, +\pounds 85{,}000). Panel (a): number of businesses by turnover band in the ONS +business register, which covers businesses registered for VAT and/or PAYE +(about 2.7 million); the full business population including unregistered +businesses is roughly twice as large (DBT business population estimates). +Panel (b): number of VAT-registered firms by turnover band. Band widths are +unequal, so cross-band count comparisons should be read per \pounds1{,}000 of +turnover. Source: panel (a), ONS, \href{https://www.ons.gov.uk/businessindustryandtrade/business/activitysizeandlocation/bulletins/ukbusinessactivitysizeandlocation/2023}{\emph{UK Business: Activity, Size and Location}} -(firm counts by turnover band); panel (b), HMRC, +(business counts by turnover band); panel (b), HMRC, \href{https://www.gov.uk/government/statistics/value-added-tax-vat-annual-statistics}{\emph{Value Added Tax (VAT) Annual Statistics}} (VAT-registered population by turnover band).} \label{fig:dist} @@ -24,24 +29,35 @@ \section{Introduction}\label{sec:intro} Firms respond to the notch by locating below the threshold. Tabulations of HMRC turnover data show the number of firms rising towards \pounds 84{,}000 and then dropping sharply at the \pounds 85{,}000 threshold, leaving excess mass just below it \citep{obr2023vat}. -\citet{liuetal2021} document this bunching in UK firm data, and \citet{liulockwoodtam2024} +\citet{liuetal2021} document this bunching in UK administrative firm data over +2004--05 to 2014--15, when the threshold rose from \pounds58{,}000 to +\pounds81{,}000, and \citet{liulockwoodtam2024} find that firms slow their turnover growth as they approach the threshold. The notch therefore distorts the size distribution and the growth decisions of firms near the margin, which places the threshold under recurrent pressure for reform. Reform proposals change the threshold in one of three ways: its \emph{level} (raising or lowering it), its \emph{shape} (replacing the notch with a schedule that phases the rate in over a band), or its \emph{rate} (a reduced rate for firms in a band above the threshold). The three are not equivalent. Changing the level moves the notch along the turnover axis; changing the shape or the rate alters the size of the discrete jump itself. Costing the three on a common basis is the practical difficulty this paper addresses. A change in the level can be costed by mechanical accounting, but a change in the shape of the schedule cannot be evaluated with the reduced-form bunching methods used to study the threshold, because a continuous schedule leaves no single point of excess mass to exploit. The firm-level data needed to study turnover near the threshold is, in addition, not available in open form. -In this paper I build an open, reproducible firm-level microsimulation for costing UK VAT threshold reforms on a common static basis. I construct synthetic firm microdata calibrated to published HMRC aggregates---band-level firm counts and sector turnover totals---for the 2023--24 tax year, when the threshold was \pounds 85{,}000 (raised to \pounds 90{,}000 in April 2024); the synthetic data can be released openly and regenerated under any counterfactual schedule. On these data I do four things. I cost both level reforms and schedule reforms---a graduated taper and a reduced-rate band---statically, by applying each counterfactual schedule mechanically to the firm distribution. I show that the synthetic data reproduce the density step at the \pounds 85{,}000 notch documented in administrative data by \citet{liuetal2021}, and I use a placebo test to demonstrate that this step is mechanical---inherited from the coarse band-level counts that serve as calibration targets rather than generated by firm location choice---so I draw no behavioural elasticity from the synthetic bunching. And I characterise the notch's distortion through its \emph{dominated region}---the exact, elasticity-free range of turnover above the threshold in which no firm locates---and how each reform changes it. I then additionally price the reforms behaviourally: a structural simulator re-optimises each firm under each counterfactual schedule---a forward solve that re-prices firms rather than applying the schedule to the observed distribution---conditional on an assumed turnover elasticity $e$ that I do not identify from the data, and I report the result as an $e$-sensitivity range that nests the static costing in its $e\to0$ limit. The static cost and the exact dominated region remain the elasticity-free robust anchors. +In this paper I build an open, reproducible firm-level microsimulation for costing UK VAT threshold reforms on a common static basis. I construct synthetic firm microdata calibrated to published official aggregates---HMRC registered-firm counts by turnover band and by sector, net VAT liability by turnover band, and ONS business counts and employment bands---for the 2023--24 tax year, when the threshold was \pounds 85{,}000, and separately for 2024--25, when it rose to \pounds 90{,}000. Each firm's net VAT liability is the standard rate applied to its value added. The synthetic data can be released openly and regenerated under any counterfactual schedule. -Three findings follow. First, the static pipeline prices level and shape reforms on a common basis and reproduces HMRC's published anchor costing: my static costing of the April 2024 increase from \pounds 85{,}000 to \pounds 90{,}000 gives \pounds 175m in 2025--26 against the Government's published \pounds 185m, agreeing within about \pounds 10m---an internal-consistency check on the costing rather than an external validation. Forward moves from the \pounds 90{,}000 base range from a gain of \pounds 665m at \pounds 70{,}000 to a cost of \pounds 1{,}205m at \pounds 120{,}000, against a base of about \pounds 203.8bn. +On these data I do four things. First, I cost level reforms and schedule reforms---a graduated taper and a reduced-rate band---statically, by applying each counterfactual schedule mechanically to the firm distribution. Second, I characterise the notch's distortion through its \emph{dominated region}---the exact, elasticity-free range of turnover above the threshold in which no firm profits from locating---and how each reform changes it. Third, I price the level and rate reforms behaviourally: each firm re-optimises its turnover within its schedule region, conditional on an assumed turnover elasticity $e$ that the data do not identify, reported as an $e$-sensitivity range that nests the static costing exactly in its $e\to0$ limit. Fourth, I show that the synthetic data's near-threshold structure is target-inherited and cannot support bunching inference: the \pounds85{,}000 profile is calibrated to the OBR's published \pounds1{,}000-band data and the estimator reads exactly that back, a placebo without the fine targets returns zero, and the uncalibrated \pounds90{,}000 vintage shows a spurious band-edge signal. -Second, the shape and rate reforms act on the notch's distortion in a way that a change in level does not. The notch creates a \emph{dominated region} of width $a = T^{*}\tau/(1-\tau) = \pounds 21{,}250$ above the threshold (\pounds 85{,}000--\pounds 106{,}250), a range of turnover in which no firm can locate without being strictly worse off than at the threshold. This region is an exact, elasticity-free property of the schedule (conditional on the turnover-tax notch): it follows from the arithmetic of the notch alone and requires no behavioural calibration. It also spans a populous part of the firm distribution---about 137{,}000 weighted firms---so its width is an economically meaningful distortion index, not a theoretical curiosity. Raising the threshold relocates this region without removing it. A reduced rate does \emph{not} remove the distortion: it lowers the largest single notch (the jump at the threshold falls from \pounds 17{,}000 to \pounds 12{,}750 at a 15\% band) but, because the band reverts to the standard rate at its \pounds 105{,}000 top, it introduces a second notch and hence a second dominated region, so the \emph{total} dominated-turnover width is essentially unchanged---\pounds 21{,}562 at 15\% and \pounds 22{,}569 at 10\%, both marginally above the \pounds 21{,}250 baseline. Only a graduated taper, being continuous, removes the distortion entirely. Set against their static revenue costs, the reforms are not interchangeable: raising the threshold to \pounds 100{,}000 costs \pounds 508m on this common \pounds 85{,}000 data-year base (the \pounds 90{,}000-base sweep of the first finding puts the same move at \pounds 374m), the most expensive option, yet removes none of the distortion; the taper removes the dominated region entirely for \pounds 336m; and the 10\% and 15\% reduced rates cost \pounds 343m and \pounds 171m while merely splitting the dominated band in two rather than shrinking it. The level move is therefore the dearest and least efficient of the menu. I report, for each reform, its static cost together with the portion of the dominated region it removes. +Four findings follow. First, the static pipeline prices all the reforms on a common basis, and its anchor costing tracks the Government's published number once the deregistration convention is stated. My static costing of the April 2024 increase from \pounds 85{,}000 to \pounds 90{,}000 depends on what released firms are assumed to do: if every firm in the band deregisters, the 2025--26 cost is \pounds 323m, overshooting HMRC's published \pounds 185m \citep{hmt_spring_budget_2024} in line with the official costing's phased registration response; if the roughly 43\% voluntary-registration share that \citet{liuetal2021} document is retained, it is \pounds 184m---matching the published figure to \pounds 1m. Both conventions reproduce the official profile's narrowing and its 2028--29 sign change. Forward moves from the \pounds 90{,}000 base range from a gain of about \pounds 1{,}040m at \pounds 70{,}000 to a cost of about \pounds 1{,}450m at \pounds 120{,}000, against a base of about \pounds 200.9bn in 2025--26. -Pricing the same reforms behaviourally---conditional on an assumed turnover elasticity $e$, which the synthetic data do not identify---implies that firm responses, if firms respond at all, would partly offset these static costs. As the effective rate falls, firms in the model scale their turnover up and broaden the base, so a larger assumed $e$ makes each reform cheaper. At an illustrative midpoint $e = 0.17$ the raise to \pounds 100{,}000 falls from \pounds 508m to about \pounds 292m, the 10\% rate from \pounds 343m to \pounds 273m, and the 15\% rate from \pounds 171m to \pounds 135m. I do not report a behavioural cost for the graduated taper: its two channels---base-broadening as the average rate falls, and a marginal-rate distortion as the taper's rate rises with turnover---cannot be credibly netted in this iso-elastic framework, so only its static cost and dominated-region removal are reported. These behavioural figures are conditional on the assumed $e$ and span a range over $e \in \{0.05, 0.17, 0.32\}$, of which only the lower end $e = 0.05$ has an external anchor \citep{klevenwaseem2013}; the $0.17$ and $0.32$ values are read off the notch geometry, not identified from the data. Because $e$ is not identified on the synthetic data, I treat the range as a disciplined sensitivity analysis rather than a point estimate, with the static cost and the exact dominated region as the elasticity-free anchors. +Second, the shape and rate reforms act on the notch's distortion in a way that a change in level does not. The notch creates a \emph{dominated region} of width $a = T^{*}\tau/(1-\tau) = \pounds 21{,}250$ above the threshold (\pounds 85{,}000--\pounds 106{,}250), a range of turnover in which no firm can locate without being strictly worse off than at the threshold. This region is an exact property of the schedule: under the value-added formulation of Section~\ref{sec:behavioural} its width is the same for every firm with positive value added, whatever its input share, and it requires no behavioural calibration. It also spans a populous part of the firm distribution---about 156{,}000 weighted firms in the calibrated data---so its width is an economically meaningful distortion index. Raising the threshold relocates this region without removing it. A reduced rate does \emph{not} remove it: the jump at the threshold falls (from \pounds 17{,}000 to \pounds 12{,}750 at a 15\% band), but the band reverts to the standard rate at its \pounds 105{,}000 top, introducing a second notch and a second dominated region, so the total dominated width is essentially unchanged---\pounds 21{,}562 at 15\% and \pounds 22{,}569 at 10\%, both marginally above the \pounds 21{,}250 baseline. Only the graduated taper, being continuous, removes the dominated region. On the common \pounds 85{,}000 data-year base, raising the threshold to \pounds 100{,}000 costs \pounds 753m and removes none of the dominated region; the taper removes all of it for \pounds 520m; and the 10\% and 15\% reduced rates cost \pounds 484m and \pounds 242m while splitting the dominated band in two. On the dominated-region metric the level move is the most expensive option per unit of distortion removed---a comparison that indexes the misallocation distortion only and omits the compliance-cost saving a higher threshold delivers (Section~\ref{sec:conclusion}). -Third, the open data carry a transparency lesson about bunching. The synthetic records reproduce the density step at \pounds 85{,}000 that \citet{liuetal2021} document in administrative data, which might tempt one to read a behavioural response off the synthetic distribution. A placebo test shows this would be a mistake: when the density step is removed from the calibration target, the apparent excess mass collapses from about 8{,}712 firms to roughly 99, revealing that the step is mechanical---a reflection of the two coarse turnover bands HMRC publishes across the threshold, baked into the calibration target---rather than a product of firm location choice, which the generator does not model. Behavioural bunching is thus not identified on the synthetic data, and I make no such claim from them; the behavioural evidence remains \citeauthor{liuetal2021}'s administrative estimate. I treat the reproduction of the published step as a credibility check on the data and the placebo as the appropriate caveat against over-reading it. +Third, conditional on the assumed elasticity, intensive-margin responses barely move these costings. A pure level rise has \emph{exactly} zero intensive-margin revenue offset at every $e$: released firms leave the VAT base, so their expansion is untaxed, and no other firm's effective rate changes---a result the simulator verifies to \pounds0.1m. For the reduced-rate bands the offset is second order: at $e=0.17$ the 10\% band's cost falls from \pounds 484m to \pounds 475m and the 15\% band's from \pounds 242m to \pounds 235m, under 6\% even at $e=0.32$. I do not report a behavioural cost for the graduated taper: its rate varies continuously with turnover, so its marginal-rate channel is outside the flat-rate machinery, and only its static cost and dominated-region removal are reported. The sweep values $e \in \{0.05, 0.17, 0.32\}$ are assumptions: the lower end has an external anchor \citep{klevenwaseem2013}, and the published UK VAT-base estimates of \citet{liuetal2021} fall between it and the midpoint. The consequence of these results runs opposite to the usual worry: the static costings are robust to the intensive margin, and the behavioural uncertainty that matters---registration and location choice at the notch---is exactly the margin the synthetic data cannot identify. -\medskip -\textbf{Related literature.} The paper draws on and contributes to four strands of work. The first is the methodology of bunching and notches \citep{saez2010,klevenwaseem2013,chettyetal2011,kleven2016,best2015}, which provides the analytic notion of a dominated region; I use the dominated region to characterise a distortion that leaves no single point of excess mass to exploit. The second is the empirical literature on the VAT registration threshold \citep{liuetal2021,liulockwoodtam2024,onji2009,harju2019,asatryanpeichl2017,nandiwarwick2020,waseem2024}, which estimates the behavioural response and studies changes in the threshold's level. \citet{liuetal2021} is closest: it estimates bunching at the UK notch on administrative data and documents voluntary registration; I take its administrative estimate as the established behavioural fact, show that my open synthetic data reproduce the density step it documents, and cost shape and rate reforms statically on a common basis. The international evidence \citep{harju2019,onji2009,asatryanpeichl2017,nandiwarwick2020} notes that bunching at a VAT threshold can reflect compliance costs, firm-splitting, or reporting rather than real turnover responses. The third strand questions whether bunching identifies a structural elasticity at all: \citet{blomquistetal2021} show that the elasticity is not non-parametrically identified from bunching at a kink without strong functional-form assumptions, and \citet{bertanhaetal2023} make the analogous point for notches. This literature motivates my refusal to read a behavioural elasticity off the synthetic bunching: even setting aside the placebo evidence that the synthetic step is mechanical, the mapping from excess mass to an elasticity is not identified without assumptions I am unwilling to impose. The fourth strand is the structural literature on size-based thresholds \citep{garicano2016,gourioroys2014}, which identifies policy-invariant primitives at the French 50-employee threshold and computes welfare from them; the present paper makes no such structural claim, pricing reforms statically and, conditional on an assumed elasticity, behaviourally. This paper makes three contributions. First, it provides an open, reproducible firm-level microsimulation for costing UK VAT threshold reforms, where the existing firm-level evidence on the threshold rests on restricted administrative data; as part of this, I show transparently that the open data reproduce the published density step and use a placebo to establish that the step is mechanical, so no behavioural bunching is claimed from the synthetic data. Second, it characterises the notch's distortion through its exact, elasticity-free dominated region and costs two schedule reforms---a graduated taper and a reduced-rate band---on the same static basis as level reforms, where prior work has neither costed these reforms nor measured this distortion. Third, it prices these reforms behaviourally with a structural simulator that re-optimises each firm under each schedule, conditional on an assumed turnover elasticity, reported as a sensitivity range that nests the static costing in its zero-elasticity limit. Because the synthetic data do not identify the turnover elasticity, identifying it from administrative micro-data is what remains for future work; a welfare and marginal-value-of-public-funds accounting---together with revenue-neutral designs and the treatment of voluntary registration---are also left for later. +Fourth, the open data carry a transparency lesson about bunching: every sub-band feature of band-calibrated synthetic data is exactly what its targets put there, and this paper demonstrates the point in three directions. The 2023--24 population's near-threshold density is calibrated to the OBR's published \pounds1{,}000-band profile \citep{obr2023vat}, so it reproduces the administratively observed bunching shape---and the estimator reads that shape back as excess mass ($E=7{,}933$), which is target inheritance, not behaviour. A placebo that regenerates the population \emph{without} the fine targets returns $E=0$: remove the targets and the ``bunching'' vanishes. And the 2024--25 vintage, for which no fine bands are published, shows what the trap looks like from the other side: the coarse \pounds90{,}000 band edge alone produces an excess-bunching statistic within 10\% of the administrative estimate of \citet{liuetal2021}---a coincidence of band geometry, four-fold unstable across estimator specifications, with no behaviour behind it. An earlier draft of this paper reported ``reproducing'' the administrative step when a liability mis-scaling in the generator manufactured it; the correction removed it, and the OBR targets now supply the shape from published data instead. The lesson is symmetric and general: synthetic bunching is not evidence of behaviour, its absence is not evidence of no behaviour, and any sub-band feature of calibrated data should be traced to its targets before it is read as economics. The behavioural evidence on UK VAT bunching remains \citeauthor{liuetal2021}'s administrative estimate. -The remainder of the paper proceeds as follows. Section~\ref{sec:background} describes the institutional background of the UK VAT threshold. Section~\ref{sec:data} sets out the synthetic firm microdata and its calibration to HMRC aggregates. Section~\ref{sec:static} sets out the static costing of threshold changes and the schedule reforms. Section~\ref{sec:bunching} reports the reduced-form bunching evidence. Section~\ref{sec:model} develops the notch and its exact dominated region, and shows how each reform changes it. Section~\ref{sec:behavioural} prices the reforms behaviourally with a structural simulator conditional on an assumed elasticity, reported as a sensitivity range that nests the static costing. Section~\ref{sec:conclusion} concludes. +\subsection*{Related literature} + +The paper draws on four strands of work. The first is the methodology of bunching and notches \citep{chettyetal2011,saez2010,klevenwaseem2013,kleven2016,best2015}, which provides the analytic notion of a dominated region; I use the dominated region to characterise a distortion that leaves no single point of excess mass to exploit. + +The second is the empirical literature on VAT registration thresholds \citep{liuetal2021,liulockwoodtam2024,onji2009,harju2019,asatryanpeichl2017,nandiwarwick2020,waseem2024}. \citet{liuetal2021} is closest: it estimates bunching at the UK notch on administrative data over 2004--2014 and documents voluntary registration; I take its estimates as the established behavioural facts and cost shape and rate reforms statically on a common basis, which that literature does not do. The international evidence \citep{harju2019,onji2009,asatryanpeichl2017,nandiwarwick2020} notes that bunching at a VAT threshold can reflect compliance costs, firm-splitting, or reporting rather than real turnover responses. + +The third strand questions whether bunching identifies a structural elasticity at all: \citet{blomquistetal2021} show that the elasticity is not non-parametrically identified from bunching at a kink or a notch without strong functional-form assumptions, and \citet{bertanhaetal2023} develop the notch case. This literature motivates my refusal to read an elasticity off the synthetic data: even setting aside the placebo evidence that any synthetic step is mechanical, the mapping from excess mass to an elasticity requires assumptions I am unwilling to impose. The fourth strand is the structural literature on size-based thresholds \citep{garicano2016,gourioroys2014}, which identifies policy-invariant primitives at the French 50-employee threshold and computes welfare from them; the present paper makes no such structural claim. + +This paper makes three contributions. First, it provides an open, reproducible firm-level microsimulation for costing UK VAT threshold reforms, where the existing firm-level evidence rests on restricted administrative data; the released pipeline regenerates every number in the paper from public inputs. Second, it characterises the notch's distortion through its exact dominated region and costs two schedule reforms---a graduated taper and a reduced-rate band---on the same static basis as level reforms. Third, it demonstrates, by construction and by correction, that band-calibrated synthetic data carry no sub-band behavioural information beyond their targets: the paper documents how its own earlier build manufactured a plausible-looking density step, how the correction removed it, how calibrating to the OBR's published fine bands restores the administrative shape as an explicit target, and how the same band-edge mechanism manufactures a spurious signal where no fine targets exist. Identifying the turnover elasticity from administrative micro-data, a welfare accounting, revenue-neutral designs, and an explicit model of voluntary registration are left for future work. + +The remainder of the paper proceeds as follows. Section~\ref{sec:background} describes the institutional background of the UK VAT threshold. Section~\ref{sec:data} sets out the synthetic firm microdata and its calibration to official aggregates. Section~\ref{sec:static} sets out the static costing of threshold changes and the schedule reforms. Section~\ref{sec:bunching} shows that the synthetic data contain no usable bunching signal and validates the estimator's power on injected signals. Section~\ref{sec:model} develops the notch and its exact dominated region, and shows how each reform changes it. Section~\ref{sec:behavioural} prices the reforms behaviourally, conditional on an assumed elasticity, and derives the level-rise invariance. Section~\ref{sec:conclusion} concludes. diff --git a/paper/Sections/model.tex b/paper/Sections/model.tex index 554c84b..ac972dc 100644 --- a/paper/Sections/model.tex +++ b/paper/Sections/model.tex @@ -2,41 +2,38 @@ \section{The notch and its dominated region} \label{sec:model} The behavioural response to the registration notch is documented in -administrative data by \citet{liuetal2021}; on my synthetic data the reduced-form -bunching is not behaviourally identified (Section~\ref{sec:bunching}). To -characterise the notch precisely I therefore turn to its analytic structure, -which yields an exact distortion measure that needs no behavioural calibration. I -set out the firm-level structure following the framework of -\citet{klevenwaseem2013}, \citet{saez2010}, and \citet{kleven2016}, as applied -to UK VAT by \citet{liuetal2021}. The UK registration threshold is a -\emph{notch}, not a kink: once turnover crosses the threshold the firm becomes -liable for VAT on its \emph{entire} turnover, not merely on the increment above -it. I model this notch exactly. The section's central deliverable is the notch's -\emph{dominated region}---an exact, elasticity-free accounting identity that indexes the -distortion the threshold imposes (Section~\ref{ssec:dominated}), whose analytic -response to each schedule reform complements the static reform costs of -Section~\ref{ssec:schedule_costs}. The dominated region is a transparent, -parameter-free distortion index: it depends on the rate and threshold alone and is -therefore exact. Section~\ref{sec:behavioural} prices the behavioural response to -each reform conditional on an assumed turnover elasticity, re-solving firm choices -under each counterfactual schedule; here the dominated region remains the exact, -elasticity-free distortion measure, requiring no assumption about the firm's -technology or elasticity. +administrative data by \citet{liuetal2021}; the synthetic data contain no +bunching signal to exploit (Section~\ref{sec:bunching}). To characterise the +notch precisely I therefore turn to its analytic structure, which yields an +exact distortion measure that needs no behavioural calibration. I set out the +firm-level structure following \citet{klevenwaseem2013}, \citet{saez2010}, and +\citet{kleven2016}, whose bunching framework \citet{liuetal2021} adapt to UK +VAT. The UK registration threshold is a \emph{notch}, not a kink: once +turnover crosses the threshold the firm becomes liable for VAT on its +\emph{entire} base, not merely on the increment above it. The section's +central deliverable is the notch's \emph{dominated region}---an exact, +elasticity-free property of the schedule that indexes the distortion the +threshold imposes (Section~\ref{ssec:dominated})---and its analytic response +to each schedule reform, complementing the static reform costs of +Section~\ref{ssec:schedule_costs}. Section~\ref{sec:behavioural} prices the +intensive-margin response to each reform conditional on an assumed turnover +elasticity; nothing in this section depends on that assumption. -\paragraph{Scope: a turnover-tax notch.} The structure here taxes \emph{turnover}. -Real VAT is levied on \emph{value added} with input-tax reclaim, and a substantial -share of below-threshold firms register voluntarily to recover input VAT -\citep{liuetal2021}. My treatment abstracts from input reclaim and voluntary -registration: it is a turnover-tax-notch approximation. This is a scope limitation -I state up front; it bounds the welfare claims I make and is one I return to in the -concluding discussion. +\paragraph{Scope.} The model prices the registration margin for firms that +remit positive net VAT. Two populations are outside its scope and are treated +as such throughout: below-threshold \emph{voluntary} registrants (roughly 43\% +of eligible firms in \citealp{liuetal2021}), who have chosen registration and +so face no notch at the threshold, and net-repayment traders (zero-rated +exporters and similar), whose remittance is negative for rated-structure +reasons the generator does not represent (Section~\ref{sec:data}). \subsection{The firm's problem} Each firm $i$ chooses turnover $y_i$ to maximise after-tax profit. Let $c_i(y_i)$ denote the cost of producing turnover $y_i$, $T^{*}$ the registration threshold, -and $\tau$ the standard VAT rate. Because VAT applies to the firm's entire -turnover once it registers, after-tax revenue is discontinuous and profit is +and $\tau$ the standard VAT rate. In the simplest statement VAT applies to the +firm's entire turnover once it registers, so after-tax revenue is discontinuous +and profit is \begin{equation} \pi_i(y_i) \;=\; \begin{cases} @@ -49,12 +46,19 @@ \subsection{The firm's problem} that nudges its turnover from just below to just above the threshold loses $\tau\,T^{*}$ of net revenue on turnover it was already earning. With the standard rate $\tau=0.20$ and threshold $T^{*}=\pounds85{,}000$ this discrete -drop is $\tau\,T^{*}=\pounds17{,}000$. This drop---absent from a kink, where only -the \emph{marginal} rate changes at the threshold while average liability moves -continuously---is the defining feature of a notch and the source of the bunching -documented in Section~\ref{sec:bunching}. It is what makes locating just below -the cutoff strictly attractive and creates the empty band derived in -Section~\ref{ssec:dominated}. +drop is $\tau\,T^{*}=\pounds17{,}000$ on whole turnover. Real VAT taxes value +added, and the corrected data give each firm net liability +$v_i=\tau(y_i-x_i)$ with deductible inputs $x_i=\delta_i y_i$ +(Section~\ref{sec:data}); profit is then +$(1-\delta_i)y_i - \tilde c_i(y_i)$ unregistered and +$(1-\delta_i)(1-\tau)y_i - \tilde c_i(y_i)$ registered---the deductible share +multiplies \emph{both} branches, so the notch geometry +of~\eqref{eq:firm-problem} carries over firm by firm, with the cash size of +the jump scaled to $\tau(1-\delta_i)T^{*}$ (about \pounds6{,}800 at the mean +value-added share of 40\%). This drop---absent from a kink, where only the +\emph{marginal} rate changes at the threshold while average liability moves +continuously---is the defining feature of a notch: it makes locating just +below the cutoff strictly attractive and creates the empty band derived next. \subsection{The dominated region} \label{ssec:dominated} @@ -74,31 +78,34 @@ \subsection{The dominated region} my parameters it gives $a = \pounds85{,}000\times 0.20/0.80 = \pounds21{,}250$, so the dominated region is $(T^{*},\,T^{*}+a)=(\pounds85{,}000,\ \pounds106{,}250)$, shown in -Figure~\ref{fig:notch_fit}. Two properties make -this $\sim\pounds21$k band a transparent, parameter-free index of the distortion. -First, it is \emph{exact and elasticity-free}: it depends on $\tau$ and $T^{*}$ -alone and is independent of the cost specification, of any behavioural elasticity, -and of any smoothing parameter. It is, however, \emph{conditional on the -statutory-rate turnover notch}: the $\pounds21{,}250$ width is computed at the -statutory $\tau=0.20$ applied to whole turnover, and so applies to the -limited-reclaim, consumer-facing firms that are the scope of this model (the -``Scope: a turnover-tax notch'' paragraph above). For firms with substantial input -reclaim the effective notch---and hence its dominated region---is correspondingly -smaller. The width is thus independent of any behavioural elasticity but -conditional on the turnover-tax-notch scope. Second, it is an order of magnitude -wider than the $\sim\pounds1$k region implied by a smoothed \emph{kink} -approximation. The band also spans a populous part of the firm distribution: about -$137{,}000$ weighted firms in the synthetic population lie in the -$\pounds85{,}000$--$\pounds106{,}250$ dominated band. Because the synthetic -generator has no location choice, this counts the firms the data \emph{place} in -the band---indexing the size of the population exposed to the distortion---rather -than firms that \emph{optimally locate} there; the identity thus ranges over a -heavily populated stretch of turnover rather than an empty tail. The precise count -is, moreover, conditional on the uniform within-band fill used to resolve turnover -inside the coarse HMRC bands (Section~\ref{sec:data}) and would shift under a -different within-band shape; it is the width $a$, not this count, that is exact. The dominated -region stands alone as a theoretical property of the schedule, independent of any -reduced-form pattern in the data. +Figure~\ref{fig:notch_fit}. + +Two properties make this band a transparent index of the distortion. First, it +is \emph{exact and elasticity-free}, and---less obviously---\emph{invariant to +the firm's input share}. Under the value-added formulation above, the +indifference condition at the edge of the region is +$(1-\delta_i)(T^{*}) = (1-\delta_i)(1-\tau)(T^{*}+a)$: the deductible share +$(1-\delta_i)$ cancels, so every firm with positive value added faces the +\emph{same} dominated width $a=T^{*}\tau/(1-\tau)$, whatever its input +intensity. (A per-firm width built from the net remittance rate, such as +$T^{*}\tau_{0i}/(1-\tau_{0i})$, corresponds to a different technology in which +marginal turnover carries no input cost, and is not used here.) The width +depends on $\tau$ and $T^{*}$ alone---not on the cost specification, any +behavioural elasticity, or any smoothing parameter. Who escapes the notch is a +matter of scope, not of input shares: voluntary registrants escape by choice, +and net-repayment traders have no positive remittance to jump +(the Scope paragraph above). Second, the region is an order of magnitude wider +than the $\sim\pounds1$k region implied by a smoothed \emph{kink} +approximation, and it spans a populous part of the firm distribution: about +$156{,}000$ weighted firms in the calibrated synthetic population lie in the +$\pounds85{,}000$--$\pounds106{,}250$ band +(\texttt{results/dominated\_region\_mass.txt}). Because the generator has no +location choice, this counts the firms the data \emph{place} in the +band---indexing the size of the population exposed to the distortion---rather +than firms that optimally locate there; the count is conditional on the +uniform within-band fill inside the coarse HMRC bands (Section~\ref{sec:data}) +and would shift under a different within-band shape. It is the width $a$, not +the count, that is exact. \begin{figure}[htbp]\centering \includegraphics[width=0.78\textwidth]{figures/dynamic_notch_fit_e017.png} @@ -106,37 +113,14 @@ \subsection{The dominated region} \label{fig:notch_fit} \end{figure} -\paragraph{Value-added robustness of the dominated region.} The -$\pounds21{,}250$ width assumes VAT falls on the firm's whole turnover, whereas -real VAT taxes value added net of reclaimed input tax. A firm that remits a net -rate $\tau_0$ (its net VAT as a share of turnover) faces a value-added dominated -region $a_i=T^{*}\,\tau_0/(1-\tau_0)$ rather than the full-rate width. I gauge the -magnitude this implies from the firm-level net-rate distribution for -near-threshold firms (turnover $\pounds80$k--$\pounds90$k). About $42\%$ of these -firms have a net VAT rate below $1\%$---net input creditors or near-zero -remitters---so they face effectively \emph{no} notch; this share is close to the -roughly $43\%$ voluntary-registration rate \citet{liuetal2021} document. For the -remaining firms with positive net VAT, the value-added dominated region has a -weighted median of about $\pounds18{,}650$---the same order of magnitude as the -$\pounds21{,}250$ full-rate figure---rising to about $\pounds44{,}000$ for the -consumer-facing, high-net-rate firms in the top quartile, which are precisely the -firms the turnover-tax-notch model is meant to describe. The value-added -correction therefore does not collapse the dominated region: it identifies the -$\sim\!42\%$ of firms (the voluntary registrants) for whom there is no notch---the -subpopulation already scoped out above---while leaving a $\sim\pounds20$k dominated -region for the limited-reclaim, consumer-facing firms the model targets. The -$\pounds21{,}250$ width is thus a reasonable representative magnitude for that -target population, consistent with the conditional, scope-limited reading set out -above. - \paragraph{How each reform changes the dominated region.} Because the width $a=T^{*}\tau/(1-\tau)$ depends on the threshold and the rate alone, the effect of -each schedule reform of Section~\ref{ssec:schedule_costs} on this misallocation -zone is exact and follows directly from the notch arithmetic +each schedule reform of Section~\ref{ssec:schedule_costs} on the dominated +region is exact and follows directly from the notch arithmetic of~\eqref{eq:dominated} and~\eqref{eq:dominated-secondary}, with no dependence on the cost specification, any behavioural elasticity, or any simulated re-optimisation. Raising the threshold to \pounds100{,}000 leaves the rate -unchanged and therefore \emph{relocates} the zone without altering its width: it +unchanged and therefore \emph{relocates} the region without altering its width: it is the same \pounds21{,}250 band, transported to the new cutoff. A banded reduced rate does \emph{not} remove the distortion. It reduces the \emph{largest single} notch---the jump at $T^{*}$ falls from $\tau T^{*}=\pounds17{,}000$ to @@ -160,17 +144,19 @@ \subsection{The dominated region} baseline, not below it. The reduced rate splits one wide empty band into two narrower ones rather than shrinking the total: it lowers the largest single notch (to $\pounds12{,}750$ at $15\%$) at the price of adding a secondary notch of -$(\tau-r)\,T_{1}=\pounds5{,}250$. The firm counts confirm this. The roughly -$96{,}500$ and $66{,}100$ weighted firms previously reported for the $15\%$ and -$10\%$ bands are the mass of the \emph{primary} region alone; the secondary region -above $\pounds105{,}000$ restores comparable dominated mass, so the total dominated -mass is not materially reduced. A graduated taper, by contrast, has \emph{no} -notch and hence no dominated region: marginal net revenue declines smoothly through -the band rather than off a cliff, so the band of dominated turnover---and with it -the discrete incentive to suppress turnover---is removed entirely. On the -dominated-region metric, then, \emph{only} the taper removes the distortion; the -reduced rate and the level move both leave it essentially intact---split and -relocated, respectively---which sharpens the taper's advantage. The dominated -region is thus the paper's exact, elasticity-free measure of the distortion the -notch imposes, and the analytic statement above is exactly how much of that -distortion each reform of Section~\ref{ssec:schedule_costs} removes. +$(\tau-r)\,T_{1}=\pounds5{,}250$. The firm counts confirm this +(\texttt{results/dominated\_region\_mass.txt}): the primary regions hold about +$120{,}600$ ($15\%$) and $89{,}900$ ($10\%$) weighted firms, the secondary +regions add about $36{,}100$ and $68{,}900$, and the totals---$156{,}700$ and +$158{,}800$---sit within $2.1\%$ of the $160{,}100$-firm baseline band. A +graduated taper, by contrast, has \emph{no} notch and hence no dominated +region: marginal net revenue declines smoothly through the band rather than off +a cliff, so the band of dominated turnover---and with it the discrete incentive +to suppress turnover---is removed entirely. On the dominated-region metric, +then, only the taper removes the distortion; the reduced rate splits it and the +level move relocates it. The metric indexes the misallocation distortion +only---what it omits, and how the reforms compare on cost, is taken up in +Section~\ref{sec:conclusion}. The dominated region is the paper's exact, +elasticity-free measure of the distortion the notch imposes, and the analytic +statement above is exactly how much of that distortion each reform of +Section~\ref{ssec:schedule_costs} removes. diff --git a/paper/Sections/static.tex b/paper/Sections/static.tex index bdc79bb..fc0205e 100644 --- a/paper/Sections/static.tex +++ b/paper/Sections/static.tex @@ -3,106 +3,143 @@ \section{Static costing of threshold reforms} A static costing measures the first-order revenue effect of a reform by re-applying the tax rule to a fixed firm population, with no behavioural response. Let firm $i$ -have turnover $y_i$, calibrated net VAT liability $v_i$ (output less input VAT; -Section~\ref{sec:data}), and weight $w_i$. A firm remits VAT only once registered, -that is once its turnover exceeds the threshold $T$, so total VAT revenue at -threshold $T$ is the weighted sum of liabilities over registered firms, +have turnover $y_i$, calibrated net VAT liability $v_i = \tau(y_i - x_i)$ +(Section~\ref{sec:data}), and weight $w_i$. A firm remits VAT only once registered, +which the model equates with turnover above the threshold $T$, so total VAT revenue +at threshold $T$ is the weighted sum of liabilities over registered firms, \[ R(T) \;=\; \sum_i w_i\, v_i \,\mathbf{1}\{y_i \ge T\}. \] -Because turnover is held fixed, moving the threshold from $T_0$ to $T$ changes -revenue only through the firms whose registration status flips---those with turnover -in the band between the two thresholds: +Two scope conventions follow from this formula and are worth stating. First, +below-threshold \emph{voluntary} registrants' remittances (a \pounds1.46bn HMRC +target in 2023--24) are outside $R(T)$, so a threshold cut credits the full +liability of newly covered firms even though roughly 43\% of below-threshold +firms would already be registered voluntarily \citep{liuetal2021}. Second, and +symmetrically, the headline treats every firm released by a threshold rise as +deregistering; the anchor comparison below reports the voluntary-retention +sensitivity. Because turnover is held fixed, moving the threshold from $T_0$ to +$T$ changes revenue only through the firms whose registration status flips: \[ \Delta R \;=\; R(T) - R(T_0) \;=\; -\,\operatorname{sign}(T - T_0) \sum_i w_i\, v_i \,\mathbf{1}\{\,T_{\min} \le y_i < T_{\max}\,\}, \] where $T_{\min}=\min(T,T_0)$ and $T_{\max}=\max(T,T_0)$: lowering the threshold draws firms into the net and raises revenue, while raising it releases firms and loses -revenue. The estimate is therefore the mechanical reclassification effect and -excludes the behavioural response of Section~\ref{sec:behavioural}. The calibrated -weights reproduce HMRC's net VAT-liability totals (Section~\ref{sec:data}), and I -age the microdata to a given fiscal year by a cumulative nominal-growth factor. At -the \pounds90{,}000 threshold this puts total VAT revenue at \pounds203.8bn in -2025--26 and \pounds210.0bn in 2026--27.\footnote{This \pounds203.8bn aggregate is -the weighted sum of the synthetic registered population's net VAT liabilities -(output less input VAT) aged to 2025--26---a theoretical-liability (VTTL-style) -base, not the published cash-receipts line. It therefore sits above published net -cash VAT receipts (around \pounds169bn in 2023--24, and an OBR forecast near -\pounds180bn for 2025--26), which are reduced relative to the theoretical liability -by refunds and repayments, the VAT gap, and collection timing.} +revenue. The estimate is the mechanical reclassification effect and excludes the +behavioural response of Section~\ref{sec:behavioural}. I age the microdata to a +given fiscal year by a cumulative nominal-growth factor. At the \pounds90{,}000 +threshold this puts total VAT revenue at \pounds200.9bn in 2025--26 and +\pounds206.1bn in 2026--27.\footnote{These aggregates are weighted sums of the +synthetic registered population's net VAT liabilities aged forward---a +theoretical-liability (VTTL-style) base, not the published cash-receipts line +(around \pounds169bn in 2023--24; OBR forecast near \pounds180bn for 2025--26), +which is reduced by refunds, the VAT gap, and collection timing. The unaged +bases also sit about 5.8\% above the HMRC liability-by-band target sums they +are calibrated toward (\pounds184.8bn against \pounds174.6bn above-threshold in +2023--24; \pounds190.7bn against \pounds180.4bn in 2024--25): the multi-target +optimiser trades the liability totals off against the count targets, and the +liability-by-band calibration scores (91.3\% and 92.0\%) bound the shortfall. +Band-to-band \emph{differences}, which drive every costing in the paper, are +less exposed than the level. The growth factors are cumulative from 2023--24 +and are applied to both vintages; to the extent the 2024--25 vintage already +embodies 2024--25 nominal levels, the aged 2024--25 aggregates overstate +nominal growth by up to one year's factor ($\approx$3\%), within the +calibration error just described.} -\paragraph{Consistency check against HMRC.} I first check the static pipeline against -HMRC's own costing of the April~2024 increase from \pounds85{,}000 to -\pounds90{,}000, which was announced and costed at Spring Budget 2024 -\citep{hmt_spring_budget_2024}. Because my microdata are calibrated to HMRC VAT aggregates -(Section~\ref{sec:data}), a close match confirms internal consistency rather than -out-of-sample accuracy. Figure~\ref{fig:hmrc_validation} compares the two costings -year by year: they share sign and profile throughout---a loss that narrows as -fiscal drag lifts the frozen baseline towards the reformed threshold, turning to a -small gain by 2028--29---and agree to within \pounds7m--\pounds21m per year (for -2025--26, \(-\)\pounds175m against the published \(-\)\pounds185m). The model reproduces -both the magnitude and the turning point of the official costing. +\paragraph{Anchor comparison against HMRC's published costing.} I compare the +static pipeline against HMRC's costing of the April~2024 increase from +\pounds85{,}000 to \pounds90{,}000, announced and costed at Spring Budget 2024 +\citep{hmt_spring_budget_2024}. The comparison requires the costing baseline +convention: the official pre-measure baseline is not a frozen \pounds85{,}000 +threshold but a counterfactual path in which the freeze legislated to +March~2026 ends and the threshold resumes uprating (85, 85, 87, 89, 92 +thousand pounds over 2024--25 to 2028--29 in the model's implementation), so +the measure's impact shrinks over the forecast and changes sign in 2028--29, +when the counterfactual threshold overtakes \pounds90{,}000. The official +profile is $-$150, $-$185, $-$125, $-$50, $+$65 \pounds m. My mechanical +costing depends on the deregistration convention. If every released firm +deregisters, the model gives $-$317, $-$323, $-$195, $-$66, $+$103: it +reproduces the sign, the narrowing profile, and the 2028--29 turning point, +but overshoots the official magnitudes throughout ($-$317 against +$-$150 in 2024--25; $-$323 against $-$185 in 2025--26). +If instead the \citet{liuetal2021} voluntary-registration share (43\%) of +released-firm liability is retained, the model gives $-$180, $-$184, $-$111, +$-$38, $+$59: above the official number in the first year, matching it to +\pounds1m in 2025--26 ($-$184.1 against $-$185), and modestly below it +thereafter (Figure~\ref{fig:hmrc_validation}). That is the honest reading of the anchor: +the official costing embeds a phased registration response (HMRC expected +roughly 28{,}000 fewer registrants in the first year, against about 48{,}000 +firms in the released band here, now pinned by the OBR fine-band targets), so +mechanical conventions overshoot while the response phases in and converge to +the official profile as it completes. Because my +microdata are calibrated to HMRC VAT aggregates, even a close match would +confirm internal consistency rather than out-of-sample accuracy. \begin{figure}[htbp] \centering \includegraphics[width=0.78\textwidth]{figures/vat_threshold_revenue_impact.png} \caption{Anchor reform: revenue impact of raising the VAT registration threshold from \pounds85{,}000 to \pounds90{,}000 (the April~2024 change), my estimate versus -HMRC's published costing, 2024--25 to 2028--29. The two series share sign and -profile, both turning positive in 2028--29 as fiscal drag lifts the frozen baseline -above the reformed threshold. Because the microdata are calibrated to HMRC -aggregates, this is a consistency check, not an out-of-sample validation.} +HMRC's published costing, 2024--25 to 2028--29. Both series narrow over the +forecast and turn positive by 2028--29 because the costing baseline is a +counterfactual threshold path that resumes uprating after March~2026 and +overtakes \pounds90{,}000. The mechanical full-deregistration estimate +overshoots the official costing while its phased registration response builds; +the voluntary-retention convention matches the official 2025--26 figure to +\pounds1m and runs modestly below it thereafter. Because the microdata are calibrated +to HMRC and OBR aggregates, this is a consistency check, not an out-of-sample +validation.} \label{fig:hmrc_validation} \end{figure} -\paragraph{A menu of threshold locations.} Having checked the method, I use it to -cost a menu of further threshold locations, taking the post-reform \pounds90{,}000 -threshold as the baseline. Each row of Table~\ref{tab:static_revenue} costs a move -of the threshold to a new location for 2025--26, holding the turnover distribution -fixed, so the revenue change reflects only the reclassification of firms into or out -of the VAT net. Because the calibration places extra weight on high-liability firms -just below the threshold, I evaluate the reclassified band from a smooth -extrapolation of the clean above-threshold profile rather than the raw -below-threshold mass. Lowering the threshold draws firms in and raises revenue; -raising it loses revenue. The schedule is approximately linear, with a mild -convexity driven by the higher individual VAT liabilities of higher-turnover -firms---each \pounds5{,}000 step changes revenue by roughly -\pounds150m--\pounds220m, and the marginal revenue per step grows -(\pounds183.5m\,$\to$\,\pounds218.1m as the threshold rises) even though the number -of firms reclassified per step falls (from about $18{,}600$ to about $16{,}200$), -because each firm released at a higher threshold remits more VAT. Even a -\pounds30{,}000 -rise to \pounds120{,}000 costs about \pounds1.2bn, under $0.6\%$ of the -\pounds203.8bn base, because the threshold governs many small firms whose individual -liabilities are small. Figure~\ref{fig:static_sweep} shows the sweep graphically. -These are \emph{static} results: they bound the first-order fiscal effect of a -threshold change but abstract from the behavioural response of -Section~\ref{sec:behavioural}. +\paragraph{A menu of threshold locations.} I next cost a menu of further threshold +locations, taking the post-reform \pounds90{,}000 threshold as the baseline. This +sweep runs on the 2024--25 vintage population (Section~\ref{sec:data}), whose +liability-by-band calibration is the marginally weaker of the two (91.3\% against 92.0\%; both vintages score about 90\% overall). Each row of +Table~\ref{tab:static_revenue} costs a move of the threshold to a new location for +2025--26, holding the turnover distribution fixed, so the revenue change reflects +only the reclassification of firms into or out of the VAT net. Because the +optimiser determines the within-band shape near the threshold +(Section~\ref{sec:data}), I evaluate the reclassified band from a smooth +extrapolation of the above-threshold profile rather than the raw local mass. +Lowering the threshold draws firms in and raises revenue; raising it loses +revenue; the threshold-cut rows inherit the registered-business frame, so they +omit currently unregistered businesses that a lower threshold would newly cover. +The schedule is approximately linear with a mild concavity: each \pounds5{,}000 +step changes revenue by roughly \pounds230m--\pounds265m, slightly less per step +at higher thresholds because the number of firms reclassified per step falls +(from about $38{,}000$ to about $26{,}000$) faster than per-firm liability +rises. A \pounds30{,}000 rise to \pounds120{,}000 costs about \pounds1.4bn, +0.7\% of the \pounds200.9bn base, because the threshold governs many small +firms whose individual liabilities are small. Figure~\ref{fig:static_sweep} +shows the sweep graphically. These are \emph{static} results: they bound the +first-order fiscal effect of a threshold change but abstract from the +behavioural response of Section~\ref{sec:behavioural}. \begin{table}[htbp] \centering \caption{Static revenue and VAT-paying-firm effects of moving the VAT registration threshold, 2025--26, relative to the post-reform \pounds90{,}000 baseline (total VAT -revenue \pounds203.8bn). Figures are mechanical, holding firm turnover fixed (no -behavioural response). This sweep is distinct from the anchor reform of -Figure~\ref{fig:hmrc_validation}.} +revenue \pounds200.9bn; 2024--25 vintage population). Figures are mechanical, +holding firm turnover fixed (no behavioural response). This sweep is distinct from +the anchor reform of Figure~\ref{fig:hmrc_validation}. The machine-readable table +is \texttt{results/static\_sweep.txt} in the replication repository.} \label{tab:static_revenue} \begin{tabular}{lrrr} \toprule Threshold & Revenue change (\pounds m) & Change (\%) & VAT-paying firms (000s) \\ \midrule -\pounds70{,}000 & $+664.9$ & $+0.33$ & $+79.3$ \\ -\pounds75{,}000 & $+509.0$ & $+0.25$ & $+58.7$ \\ -\pounds80{,}000 & $+346.3$ & $+0.17$ & $+38.7$ \\ -\pounds85{,}000 & $+176.6$ & $+0.09$ & $+19.1$ \\ +\pounds70{,}000 & $+1{,}042.8$ & $+0.52$ & $+145.7$ \\ +\pounds75{,}000 & $+776.2$ & $+0.39$ & $+107.2$ \\ +\pounds80{,}000 & $+513.6$ & $+0.26$ & $+70.1$ \\ +\pounds85{,}000 & $+254.8$ & $+0.13$ & $+34.4$ \\ \pounds90{,}000 (baseline) & $0$ & $0$ & $0$ \\ -\pounds95{,}000 & $-183.5$ & $-0.09$ & $-18.6$ \\ -\pounds100{,}000 & $-374.0$ & $-0.18$ & $-36.8$ \\ -\pounds105{,}000 & $-571.4$ & $-0.28$ & $-54.5$ \\ -\pounds110{,}000 & $-775.7$ & $-0.38$ & $-71.7$ \\ -\pounds115{,}000 & $-987.0$ & $-0.48$ & $-88.5$ \\ -\pounds120{,}000 & $-1{,}205.1$ & $-0.59$ & $-104.7$ \\ +\pounds95{,}000 & $-250.9$ & $-0.12$ & $-33.0$ \\ +\pounds100{,}000 & $-498.0$ & $-0.25$ & $-64.6$ \\ +\pounds105{,}000 & $-741.1$ & $-0.37$ & $-94.8$ \\ +\pounds110{,}000 & $-980.4$ & $-0.49$ & $-123.7$ \\ +\pounds115{,}000 & $-1{,}215.7$ & $-0.61$ & $-151.2$ \\ +\pounds120{,}000 & $-1{,}447.1$ & $-0.72$ & $-177.3$ \\ \bottomrule \end{tabular} \end{table} @@ -118,13 +155,10 @@ \section{Static costing of threshold reforms} } \caption{Static effect of moving the VAT registration threshold, 2025--26, relative to the \pounds90{,}000 baseline (dashed line). Panel (a): revenue impact---lowering -the threshold raises revenue, raising it loses revenue, and the schedule is -approximately linear, with a mild convexity driven by the higher individual VAT -liabilities of higher-turnover firms---the marginal revenue per \pounds5{,}000 step -grows even as the number of firms reclassified per step falls---over the -\pounds70{,}000--\pounds120{,}000 range. Panel (b): the -change in the number of VAT-paying firms, tracking the local density of firms on each -side of the threshold.} +the threshold raises revenue, raising it loses revenue, approximately linearly +over the \pounds70{,}000--\pounds120{,}000 range. Panel (b): the change in the +number of VAT-paying firms, tracking the local density of firms on each side of +the threshold.} \label{fig:static_sweep} \end{figure} @@ -132,68 +166,74 @@ \subsection{Costing schedule reforms} \label{ssec:schedule_costs} The threshold sweep above moves the \emph{location} of a single cutoff. The same -static method---re-applying a tax rule to the fixed turnover distribution, with no -behavioural response---also costs reforms that change the \emph{shape} of the +static principle---re-applying a tax rule to the fixed turnover distribution, with +no behavioural response---also costs reforms that change the \emph{shape} of the schedule rather than merely its position. I consider four reforms and report their first-order revenue effects against a common baseline: the -\pounds85{,}000-notch / \pounds183.6bn 2023--24 base. (This 2023--24 data-year base -differs from the \pounds203.8bn figure in the sweep above, which ages the same -microdata to the 2025--26 fiscal year at the post-reform \pounds90{,}000 threshold; +\pounds85{,}000-notch / \pounds184.8bn 2023--24 base. (This 2023--24 data-year base +differs from the \pounds200.9bn figure in the sweep above, which runs on the +2024--25 vintage aged to 2025--26 at the post-reform \pounds90{,}000 threshold; the schedule reforms are costed in the data year to match the bunching and -dominated-region analysis. Both \pounds183.6bn and \pounds203.8bn are -theoretical-liability (VTTL-style) bases in the sense of the footnote above, not -cash-receipts lines.) For each reform I recompute -the weighted sum of liabilities $R = \sum_i w_i\, v_i$ under the new schedule, -holding each firm's turnover fixed, and difference it against the baseline. +dominated-region analysis. Both bases are theoretical-liability (VTTL-style) +aggregates in the sense of the footnote above, not cash-receipts lines.) For each +reform I recompute the weighted sum of liabilities $R = \sum_i w_i\, v_i$ under +the new schedule, holding each firm's turnover fixed, and difference it against +the baseline. \paragraph{Threshold relocation.} Raising the threshold from \pounds85{,}000 to -\pounds100{,}000 is a pure location move, costed exactly as in the sweep above: it -releases the firms with turnover in $[\pounds85{,}000, \pounds100{,}000)$---about -$94{,}300$ firms---from the VAT net, for a static revenue change of -\(-\)\pounds508m on the \pounds85{,}000-notch / \pounds183.6bn base, consistent -(same base) with the taper and reduced-rate reforms below. On this common base the -level move is the most expensive option yet removes no distortion---it merely -relocates the dominated region to a new cutoff---whereas the taper removes the -dominated region entirely at lower cost (\(-\)\pounds336m), foreshadowing -Section~\ref{sec:model}. +\pounds100{,}000 releases the firms with turnover in +$[\pounds85{,}000, \pounds100{,}000)$---about $111{,}900$ firms---from the VAT +net, for a static revenue change of \(-\)\pounds753m on the common base. Because +the released band lies \emph{above} the data-year threshold, its liabilities are +directly calibrated (and its lower reach pinned by the OBR fine-band targets), +so the band is summed directly; the sweep's smooth-counterfactual method, which +irons out the near-threshold concentration by construction, gives +\(-\)\pounds702m and $102{,}000$ firms, 10\% below the direct sum---a gap that +now measures the real, target-pinned concentration of firms just above the +threshold rather than an optimiser artifact. On this common base the level move carries the largest static +cost of the menu and leaves the dominated region in place, relocating it to the +new cutoff (Section~\ref{sec:model}); the taper removes the dominated region at +a static cost of \(-\)\pounds520m. Which matters more depends on what the +reader wants from the reform---the dominated-region metric indexes +misallocation only, and Section~\ref{sec:conclusion} discusses what it omits. \paragraph{Graduated taper.} A graduated taper replaces the discrete notch with an effective rate that phases linearly from $0\%$ at \pounds85{,}000 to the full $20\%$ at \pounds105{,}000. Firms in the band remit a tapered rather than a full rate on -their (fixed) turnover; mechanically this reduces revenue by \(-\)\pounds336m, with -about $123{,}100$ firms in the \pounds85{,}000--\pounds105{,}000 band facing a lower +their (fixed) turnover; mechanically this reduces revenue by \(-\)\pounds520m, with +about $144{,}800$ firms in the \pounds85{,}000--\pounds105{,}000 band facing a lower effective rate. \paragraph{Banded reduced rate.} A banded reduced rate charges firms in the \pounds85{,}000--\pounds105{,}000 band a reduced rate $\tau_{\text{low}}\in\{10\%,15\%\}$ in place of the standard $20\%$, with $20\%$ -retained above \pounds105{,}000. Statically this reduces revenue by \(-\)\pounds343m -at $\tau_{\text{low}}=10\%$ and by \(-\)\pounds171m at $\tau_{\text{low}}=15\%$, -again with about $123{,}100$ firms in the band facing the lower rate. +retained above \pounds105{,}000. Statically this reduces revenue by \(-\)\pounds484m +at $\tau_{\text{low}}=10\%$ and by \(-\)\pounds242m at $\tau_{\text{low}}=15\%$, +again with about $144{,}800$ firms in the band facing the lower rate. \begin{table}[htbp] \centering \caption{Static, behaviour-free revenue effect of the four reforms relative to the -common \pounds85{,}000-notch / \pounds183.6bn 2023--24 baseline. Each reform is +common \pounds85{,}000-notch / \pounds184.8bn 2023--24 baseline. Each reform is costed mechanically by re-applying its schedule to the fixed turnover distribution, with no behavioural response.} \label{tab:schedule_costs} \begin{tabular}{llr} -\hline +\toprule Reform & Lever & Static revenue (\pounds m) \\ -\hline -Raise threshold to \pounds100{,}000 & Location & $-508$ \\ -Graduated taper $[\pounds85\text{k},\pounds105\text{k}]$ & Shape (phase-in) & $-336$ \\ -Reduced rate $10\%$ $[\pounds85\text{k},\pounds105\text{k}]$ & Rate (step) & $-343$ \\ -Reduced rate $15\%$ $[\pounds85\text{k},\pounds105\text{k}]$ & Rate (step) & $-171$ \\ -\hline +\midrule +Raise threshold to \pounds100{,}000 & Location & $-753$ \\ +Graduated taper $[\pounds85\text{k},\pounds105\text{k}]$ & Shape (phase-in) & $-520$ \\ +Reduced rate $10\%$ $[\pounds85\text{k},\pounds105\text{k}]$ & Rate (step) & $-484$ \\ +Reduced rate $15\%$ $[\pounds85\text{k},\pounds105\text{k}]$ & Rate (step) & $-242$ \\ +\bottomrule \end{tabular} \end{table} These static figures bound the first-order fiscal effect of each reform but abstract from the behavioural response of Section~\ref{sec:behavioural}. One feature of the shape reforms is not visible in a static costing: unlike a threshold move, -which simply transports the notch to a new cutoff, the taper and the reduced rate +which transports the notch to a new cutoff, the taper and the reduced rate \emph{change the size of the notch itself}---the discrete drop in net revenue at the threshold and the empty band of turnover it induces. Quantifying that change requires the structural object I develop in Section~\ref{sec:model}, where I derive diff --git a/paper/figures/bunching_analysis_85k.png b/paper/figures/bunching_analysis_85k.png index 59df44f..150467d 100644 Binary files a/paper/figures/bunching_analysis_85k.png and b/paper/figures/bunching_analysis_85k.png differ diff --git a/paper/figures/bunching_analysis_90k.png b/paper/figures/bunching_analysis_90k.png new file mode 100644 index 0000000..e730a73 Binary files /dev/null and b/paper/figures/bunching_analysis_90k.png differ diff --git a/paper/figures/dynamic_cost_vs_elasticity.png b/paper/figures/dynamic_cost_vs_elasticity.png index 55337a1..1595445 100644 Binary files a/paper/figures/dynamic_cost_vs_elasticity.png and b/paper/figures/dynamic_cost_vs_elasticity.png differ diff --git a/paper/figures/dynamic_notch_fit_e005.png b/paper/figures/dynamic_notch_fit_e005.png new file mode 100644 index 0000000..fc238fc Binary files /dev/null and b/paper/figures/dynamic_notch_fit_e005.png differ diff --git a/paper/figures/dynamic_notch_fit_e017.png b/paper/figures/dynamic_notch_fit_e017.png index e0075af..d40773b 100644 Binary files a/paper/figures/dynamic_notch_fit_e017.png and b/paper/figures/dynamic_notch_fit_e017.png differ diff --git a/paper/figures/dynamic_notch_fit_e032.png b/paper/figures/dynamic_notch_fit_e032.png new file mode 100644 index 0000000..e3b3049 Binary files /dev/null and b/paper/figures/dynamic_notch_fit_e032.png differ diff --git a/paper/figures/dynamic_reform_distribution_raisethresholdto100k_e017.png b/paper/figures/dynamic_reform_distribution_raisethresholdto100k_e017.png new file mode 100644 index 0000000..ba8cab4 Binary files /dev/null and b/paper/figures/dynamic_reform_distribution_raisethresholdto100k_e017.png differ diff --git a/paper/figures/dynamic_reform_distribution_reducedrate1085k105k_e017.png b/paper/figures/dynamic_reform_distribution_reducedrate1085k105k_e017.png new file mode 100644 index 0000000..67936c3 Binary files /dev/null and b/paper/figures/dynamic_reform_distribution_reducedrate1085k105k_e017.png differ diff --git a/paper/figures/dynamic_reform_distribution_reducedrate1585k105k_e017.png b/paper/figures/dynamic_reform_distribution_reducedrate1585k105k_e017.png new file mode 100644 index 0000000..48038b1 Binary files /dev/null and b/paper/figures/dynamic_reform_distribution_reducedrate1585k105k_e017.png differ diff --git a/paper/figures/firms_by_turnover_band_85k.png b/paper/figures/firms_by_turnover_band_85k.png index 6f66321..daff466 100644 Binary files a/paper/figures/firms_by_turnover_band_85k.png and b/paper/figures/firms_by_turnover_band_85k.png differ diff --git a/paper/figures/firms_impact_2025_26.png b/paper/figures/firms_impact_2025_26.png index 25ceccf..d62d50c 100644 Binary files a/paper/figures/firms_impact_2025_26.png and b/paper/figures/firms_impact_2025_26.png differ diff --git a/paper/figures/formulation_a_optima.png b/paper/figures/formulation_a_optima.png index 6c6bbf2..a20f2ae 100644 Binary files a/paper/figures/formulation_a_optima.png and b/paper/figures/formulation_a_optima.png differ diff --git a/paper/figures/revenue_impact_2025_26.png b/paper/figures/revenue_impact_2025_26.png index 3c9c110..f50c5c0 100644 Binary files a/paper/figures/revenue_impact_2025_26.png and b/paper/figures/revenue_impact_2025_26.png differ diff --git a/paper/figures/turnover_distribution_85k.png b/paper/figures/turnover_distribution_85k.png index 9e9822a..5f54e69 100644 Binary files a/paper/figures/turnover_distribution_85k.png and b/paper/figures/turnover_distribution_85k.png differ diff --git a/paper/figures/vat_firms_by_turnover_band_85k.png b/paper/figures/vat_firms_by_turnover_band_85k.png index 384baff..52343be 100644 Binary files a/paper/figures/vat_firms_by_turnover_band_85k.png and b/paper/figures/vat_firms_by_turnover_band_85k.png differ diff --git a/paper/figures/vat_threshold_revenue_impact.png b/paper/figures/vat_threshold_revenue_impact.png index 2d33be3..35bd2a1 100644 Binary files a/paper/figures/vat_threshold_revenue_impact.png and b/paper/figures/vat_threshold_revenue_impact.png differ diff --git a/paper/frontmatter.tex b/paper/frontmatter.tex index fb1e818..981c74b 100644 --- a/paper/frontmatter.tex +++ b/paper/frontmatter.tex @@ -1,10 +1,10 @@ \maketitle \begin{abstract} -I present an open, reproducible firm-level microsimulation for costing UK VAT registration-threshold reforms, released with its synthetic-data generator. The threshold is a \emph{notch}: once turnover crosses \pounds85{,}000, 20\% VAT falls due on a firm's whole turnover, not the excess. I build synthetic firm records from ONS counts, calibrate them to 2023--24 HMRC statistics, and cost \emph{level}, \emph{shape} (a taper) and \emph{rate} (a reduced-rate band) reforms statically on a common basis, reproducing HMRC's \pounds85{,}000-to-\pounds90{,}000 costing within \pounds10m. I characterise the notch by its \emph{dominated region}---the exact \pounds21{,}250 band above the threshold in which no firm locates---and how each reform changes it: raising it (to \pounds100{,}000, $-$\pounds508m) relocates it, a reduced rate shrinks it, a taper removes it. I price level and rate reforms behaviourally, conditional on an assumed elasticity, as a sensitivity range nesting the static cost. A placebo shows the synthetic bunching is a calibration artefact, not behaviour. +I present an open, reproducible firm-level microsimulation for costing UK VAT registration-threshold reforms, released with its synthetic-data generator. The threshold is a \emph{notch}: once annual turnover crosses \pounds85{,}000, VAT falls due on a firm's whole base, not the excess. I build synthetic firm records from ONS registered-business counts, calibrate them to 2023--24 HMRC statistics---with the near-threshold density pinned to the OBR's published \pounds1{,}000-band bunching profile---and cost \emph{level}, \emph{shape} (a taper) and \emph{rate} (a reduced-rate band) reforms statically on a common \pounds184.8bn base: raising the threshold to \pounds100{,}000 costs \pounds753m, a graduated taper over \pounds85{,}000--\pounds105{,}000 costs \pounds520m, and 10\% and 15\% reduced-rate bands cost \pounds484m and \pounds242m. A static costing of the April 2024 rise to \pounds90{,}000 matches HMRC's published 2025--26 figure to \pounds1m under a voluntary-retention convention (\pounds184m against \pounds185m) and reproduces the official profile's narrowing and 2028--29 sign change. I characterise the notch by its \emph{dominated region}---the exact \pounds21{,}250 band above the threshold in which no firm profits from locating---and how each reform changes it: a level rise relocates it, a reduced rate splits it into two bands of essentially unchanged total width, a taper removes it. Conditional on an assumed turnover elasticity, intensive-margin responses barely move these costings: a pure level rise has exactly zero intensive-margin offset, and reduced-rate offsets stay under 4\%. The synthetic near-threshold shape is target-inherited, and provably so: the estimator reads back the excess mass the OBR targets put in at \pounds85{,}000, a placebo that regenerates without those targets returns zero, and the uncalibrated \pounds90{,}000 vintage shows a band-edge artifact that lands within 10\% of the administrative bunching estimate---a coincidence of band geometry, unstable across specifications---so band-calibrated synthetic data support no bunching inference in either direction. \end{abstract} \vspace{0.3cm} -\noindent\textbf{Keywords:} value-added tax, microsimulation, tax notch, policy +\noindent\textbf{Keywords:} value-added tax, microsimulation, tax notch, registration threshold \newpage diff --git a/paper/index.qmd b/paper/index.qmd index 4603bb4..0bf62c5 100644 --- a/paper/index.qmd +++ b/paper/index.qmd @@ -1,5 +1,5 @@ --- -title: "A Firm-Level Microsimulation for VAT Policy Analysis" +title: "An Open Firm-Level Microsimulation of the UK VAT Registration Threshold" author: - name: "Vahid Ahmadi" affiliation: "PolicyEngine" diff --git a/paper/main.pdf b/paper/main.pdf index c2e8f40..b554e78 100644 Binary files a/paper/main.pdf and b/paper/main.pdf differ diff --git a/paper/references.bib b/paper/references.bib index fa6f297..9abf610 100644 --- a/paper/references.bib +++ b/paper/references.bib @@ -5,7 +5,8 @@ @article{liuetal2021 volume = {103}, number = {1}, pages = {151--164}, - year = {2021} + year = {2021}, + url = {https://direct.mit.edu/rest/article/103/1/151/97767} } @techreport{liulockwoodtam2024, @@ -13,8 +14,9 @@ @techreport{liulockwoodtam2024 title = {Small Firm Growth and the {VAT} Threshold: Evidence for the {UK}}, institution = {International Monetary Fund}, type = {IMF Working Paper}, - number = {WP/24/033}, - year = {2024} + number = {WP/24/33}, + year = {2024}, + url = {https://www.imf.org/en/publications/wp/issues/2024/02/16/small-firm-growth-and-the-vat-threshold-evidence-for-the-uk-544462} } @article{saez2010, @@ -24,7 +26,8 @@ @article{saez2010 volume = {2}, number = {3}, pages = {180--212}, - year = {2010} + year = {2010}, + url = {https://doi.org/10.1257/pol.2.3.180} } @article{klevenwaseem2013, @@ -34,17 +37,19 @@ @article{klevenwaseem2013 volume = {128}, number = {2}, pages = {669--723}, - year = {2013} + year = {2013}, + url = {https://doi.org/10.1093/qje/qjt004} } @article{chettyetal2011, author = {Chetty, Raj and Friedman, John N. and Olsen, Tore and Pistaferri, Luigi}, - title = {Adjustment Costs, Firm Responses, and Micro vs. Macro Labor Supply Elasticities}, + title = {Adjustment Costs, Firm Responses, and Micro vs. Macro Labor Supply Elasticities: Evidence from {Danish} Tax Records}, journal = {Quarterly Journal of Economics}, volume = {126}, number = {2}, pages = {749--804}, - year = {2011} + year = {2011}, + url = {https://doi.org/10.1093/qje/qjr013} } @article{kleven2016, @@ -53,25 +58,17 @@ @article{kleven2016 journal = {Annual Review of Economics}, volume = {8}, pages = {435--464}, - year = {2016} + year = {2016}, + url = {https://doi.org/10.1146/annurev-economics-080315-015234} } @article{belloncopestake2022, - author = {Bellon, Matthieu and Copestake, Alexander and Zhang, Wenzhang}, + author = {Copestake, Alexander and Bellon, Matthieu and Zhang, Wenzhang}, title = {Supply and Demand Determinants of Heterogeneous {VAT} Pass-Through}, journal = {National Tax Journal}, note = {Forthcoming}, - year = {2022} -} - -@article{almunialopezrodriguez2018, - author = {Almunia, Miguel and Lopez-Rodriguez, David}, - title = {Under the Radar: The Effects of Monitoring Firms on Tax Compliance}, - journal = {American Economic Journal: Economic Policy}, - volume = {10}, - number = {1}, - pages = {1--38}, - year = {2018} + year = {2026}, + url = {https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4207882} } @misc{policyengine, @@ -88,35 +85,38 @@ @article{best2015 volume = {123}, number = {6}, pages = {1311--1355}, - year = {2015} + year = {2015}, + url = {https://doi.org/10.1086/683849} } @misc{nandiwarwick2020, author = {Nandi, Tushar and Warwick, Ross}, title = {How Businesses Respond to {VAT}: Evidence from {West Bengal}, {India}}, - howpublished = {TaxDev / Institute for Fiscal Studies}, + howpublished = {TaxDev / Institute for Fiscal Studies, \url{https://www.taxdev.org/research-projects/how-businesses-respond-vat}}, year = {2020} } -@article{benedek2015, - author = {Benedek, Dora and de Mooij, Ruud A. and Keen, Michael and Wingender, Philippe}, - title = {Estimating {VAT} Pass Through}, - journal = {IMF Working Paper}, - number = {WP/15/214}, - year = {2015} +@techreport{benedek2015, + author = {Benedek, Dora and de Mooij, Ruud A. and Keen, Michael and Wingender, Philippe}, + title = {Estimating {VAT} Pass Through}, + institution = {International Monetary Fund}, + type = {IMF Working Paper}, + number = {WP/15/214}, + year = {2015}, + url = {https://www.elibrary.imf.org/view/journals/001/2015/214/001.2015.issue-214-en.xml} } @misc{hmrc_threshold, author = {{HM Revenue and Customs}}, - title = {{VAT} Registration Thresholds}, - howpublished = {GOV.UK guidance, \url{https://www.gov.uk/vat-registration-thresholds}}, + title = {Increasing the {VAT} Registration Threshold}, + howpublished = {Tax information and impact note, GOV.UK, \url{https://www.gov.uk/government/publications/vat-increasing-the-registration-and-deregistration-thresholds/increasing-the-vat-registration-threshold}}, year = {2024} } @misc{hoc_vat, author = {Seely, Antony}, title = {{VAT}: The Registration Threshold}, - howpublished = {House of Commons Library Briefing Paper}, + howpublished = {House of Commons Library Briefing Paper SN00963, \url{https://commonslibrary.parliament.uk/research-briefings/sn00963/}}, year = {2024} } @@ -127,7 +127,8 @@ @article{garicano2016 volume = {106}, number = {11}, pages = {3439--3479}, - year = {2016} + year = {2016}, + url = {https://doi.org/10.1257/aer.20130232} } @article{gourioroys2014, @@ -137,7 +138,8 @@ @article{gourioroys2014 volume = {5}, number = {2}, pages = {377--416}, - year = {2014} + year = {2014}, + url = {https://doi.org/10.3982/QE338} } @article{harju2019, @@ -146,7 +148,8 @@ @article{harju2019 journal = {Journal of Public Economics}, volume = {173}, pages = {139--164}, - year = {2019} + year = {2019}, + url = {https://doi.org/10.1016/j.jpubeco.2019.02.003} } @article{onji2009, @@ -156,7 +159,8 @@ @article{onji2009 volume = {93}, number = {5--6}, pages = {766--775}, - year = {2009} + year = {2009}, + url = {https://doi.org/10.1016/j.jpubeco.2008.10.003} } @techreport{asatryanpeichl2017, @@ -165,15 +169,17 @@ @techreport{asatryanpeichl2017 institution = {CESifo}, type = {CESifo Working Paper}, number = {6754}, - year = {2017} + year = {2017}, + url = {https://ideas.repec.org/p/ces/ceswps/_6754.html} } @techreport{waseem2024, author = {Bashir, Muhammad and Farooq, Zehra and Jamal, Usama and Waseem, Mazhar}, title = {Size-Based Policies and Firm Growth: Evidence from {Pakistan}}, + institution = {University of Manchester}, type = {Working Paper}, - note = {\url{https://mazharwaseem.com/static/uploads/PAK_VAT_Threshold_October_2024.pdf}}, - year = {2024} + year = {2024}, + url = {https://mazharwaseem.com/static/uploads/PAK_VAT_Threshold_October_2024.pdf} } @misc{obr2023vat, @@ -184,13 +190,14 @@ @misc{obr2023vat } @article{blomquistetal2021, - author = {Blomquist, S{\o}ren and Newey, Whitney K. and Kumar, Anil and Liang, Che-Yuan}, + author = {Blomquist, S{\"o}ren and Newey, Whitney K. and Kumar, Anil and Liang, Che-Yuan}, title = {On Bunching and Identification of the Taxable Income Elasticity}, journal = {Journal of Political Economy}, volume = {129}, number = {8}, pages = {2320--2343}, - year = {2021} + year = {2021}, + url = {https://doi.org/10.1086/714446} } @article{bertanhaetal2023, @@ -200,16 +207,31 @@ @article{bertanhaetal2023 volume = {237}, number = {2}, pages = {105512}, - year = {2023} + year = {2023}, + url = {https://doi.org/10.1016/j.jeconom.2023.105512} } @misc{ots2017vat, author = {{Office of Tax Simplification}}, title = {Value Added Tax: Routes to Simplification}, - howpublished = {OTS report, November 2017, \url{https://www.gov.uk/government/publications/ots-vat-review-routes-to-simplification}}, + howpublished = {OTS report, November 2017, \url{https://assets.publishing.service.gov.uk/media/5a822577e5274a2e87dc1620/Value_added_tax_routes_to_simplification_web.pdf}}, year = {2017} } +@misc{hmt2018cfe, + author = {{HM Treasury}}, + title = {{VAT} Registration Threshold: Call for Evidence}, + howpublished = {HM Treasury, March 2018, \url{https://www.gov.uk/government/consultations/vat-registration-threshold-call-for-evidence}}, + year = {2018} +} + +@misc{eudirective2020285, + author = {{Council of the European Union}}, + title = {Council Directive ({EU}) 2020/285 on the Special Scheme for Small Enterprises}, + howpublished = {Official Journal of the European Union, \url{https://eur-lex.europa.eu/eli/dir/2020/285/oj}}, + year = {2020} +} + @article{keenmintz2004, author = {Keen, Michael and Mintz, Jack}, title = {The Optimal Threshold for a Value-Added Tax}, @@ -217,12 +239,13 @@ @article{keenmintz2004 volume = {88}, number = {3--4}, pages = {559--576}, - year = {2004} + year = {2004}, + url = {https://doi.org/10.1016/S0047-2727(02)00165-2} } @misc{hmt_spring_budget_2024, author = {{HM Treasury}}, title = {Spring Budget 2024: Policy Costings}, - howpublished = {HM Treasury, March 2024, \url{https://www.gov.uk/government/publications/spring-budget-2024-documents}}, + howpublished = {HM Treasury, March 2024, \url{https://assets.publishing.service.gov.uk/media/65e7920c08eef600155a5617/Published_Costing_Document_Spring_Budget_2024_Final.pdf}}, year = {2024} } diff --git a/paper/title_metadata.tex b/paper/title_metadata.tex index d0b7aac..8c6607f 100644 --- a/paper/title_metadata.tex +++ b/paper/title_metadata.tex @@ -1,3 +1,3 @@ -\title{A Firm-Level Microsimulation for VAT Policy Analysis\thanks{\parbox{\dimexpr\textwidth-5em\relax}{\textbf{Acknowledgements:} I thank Max Ghenis and Seyed Mahdi Hosseini for their great suggestions and helpful discussions.}}} +\title{An Open Firm-Level Microsimulation of the UK VAT Registration Threshold\thanks{\parbox{\dimexpr\textwidth-5em\relax}{\textbf{Acknowledgements:} I thank Max Ghenis and Seyed Mahdi Hosseini for their great suggestions and helpful discussions.}}} \author{Vahid Ahmadi\thanks{Research Associate at PolicyEngine. Email: \href{mailto:vahid@policyengine.org}{vahid@policyengine.org}} \\[0.4cm] \normalsize PolicyEngine} \date{{\small\textcolor{red}{Preliminary and Incomplete. Comments are welcome.}} \\ \vspace{0.3cm} \small \ifcase\month\or January\or February\or March\or April\or May\or June\or July\or August\or September\or October\or November\or December\fi\ \the\year} diff --git a/results/bunching_analysis_85k.png b/results/bunching_analysis_85k.png index 59df44f..150467d 100644 Binary files a/results/bunching_analysis_85k.png and b/results/bunching_analysis_85k.png differ diff --git a/results/bunching_analysis_90k.png b/results/bunching_analysis_90k.png index 66770fc..e730a73 100644 Binary files a/results/bunching_analysis_90k.png and b/results/bunching_analysis_90k.png differ diff --git a/results/bunching_cli.log b/results/bunching_cli.log new file mode 100644 index 0000000..efc4c49 --- /dev/null +++ b/results/bunching_cli.log @@ -0,0 +1,26 @@ +Generating bunching figures... +Generating bunching_analysis_85k.png... + saved /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/results/bunching_analysis_85k.png +Generating bunching_analysis_90k.png... + saved /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/results/bunching_analysis_90k.png + done. + +============================================================ + Bunching — vintage 2023-24 +============================================================ + point se ci_lo ci_hi n_boot +parameter +b 0.010598 0.004459 0.002972 0.021519 200 +b_llat 1.910717 0.061370 1.807769 2.032534 200 +E 7932.578238 290.458183 7380.758604 8564.120961 200 +dyR 15.000000 0.000000 15.000000 15.000000 200 + +============================================================ + Bunching — vintage 2024-25 +============================================================ + point se ci_lo ci_hi n_boot +parameter +b 0.073913 0.004782 0.064608 0.082811 200 +b_llat 1.229803 0.100604 1.049023 1.427485 200 +E 11072.367270 672.899527 9774.143049 12312.422664 200 +dyR 11.014494 1.864233 8.016325 15.000000 200 diff --git a/results/bunching_inference.txt b/results/bunching_inference.txt new file mode 100644 index 0000000..0222d18 --- /dev/null +++ b/results/bunching_inference.txt @@ -0,0 +1,49 @@ +BUNCHING INFERENCE — definitive build (OBR shape targets, side-consistent +frame scaling; no below-threshold liability calibration). Points + grids +only; see 'Why no standard errors are reported' in the paper appendix and +results/seed_sensitivity.txt for generator-seed dispersion. +========================================================================== + +--- Vintage 2023-24 (threshold GBP 85k) --- +E = 7,933 | b_llat = 1.911 | b = 0.0106 | y_R = 100.00 + +Degree x window sensitivity (point estimates): + degree window b b_llat E + 5 10.0 0.121455 2.540936 11083.763899 + 5 15.0 0.062952 2.409029 10496.139158 + 5 20.0 0.051871 2.531571 11481.096823 + 5 25.0 0.073787 3.426838 17978.098315 + 6 10.0 0.084931 2.071682 9047.128648 + 6 15.0 -0.002772 1.491790 6734.180107 + 6 20.0 -0.056319 0.904710 4707.063377 + 6 25.0 -0.085257 0.528752 3562.712992 + 7 10.0 0.095200 2.338710 9791.845330 + 7 15.0 0.010598 1.910717 7932.578238 + 7 20.0 -0.036794 1.379028 6094.394467 + 7 25.0 -0.058932 1.001457 4913.878747 + 8 10.0 0.168343 3.354124 14588.584354 + 8 15.0 0.096421 3.209501 13943.573789 + 8 20.0 0.075002 3.360832 14954.732208 + 8 25.0 0.186001 7.434261 40321.093337 + +--- Vintage 2024-25 (threshold GBP 90k) --- +E = 11,072 | b_llat = 1.230 | b = 0.0739 | y_R = 101.01 + +Degree x window sensitivity (point estimates): + degree window b b_llat E + 5 10.0 0.146068 1.615503 13556.548133 + 5 15.0 0.129243 2.197582 18412.307439 + 5 20.0 0.131270 3.037524 25109.035091 + 5 25.0 0.135558 3.976527 32395.051029 + 6 10.0 0.087845 0.936758 8589.238231 + 6 15.0 0.060779 0.964004 9217.642937 + 6 20.0 0.051607 1.093617 10634.357368 + 6 25.0 0.035325 0.983127 9868.215434 + 7 10.0 0.102238 1.142290 9865.988105 + 7 15.0 0.073913 1.229803 11072.367270 + 7 20.0 0.074531 1.779871 15008.964954 + 7 25.0 0.087805 2.729612 21941.019050 + 8 10.0 0.105654 1.178887 10164.141541 + 8 15.0 0.088577 1.489301 13090.387700 + 8 20.0 0.111132 2.574579 21642.323244 + 8 25.0 0.156187 4.460663 36658.967427 diff --git a/results/bunching_inference_regenerated.txt b/results/bunching_inference_regenerated.txt deleted file mode 100644 index 8fa3544..0000000 --- a/results/bunching_inference_regenerated.txt +++ /dev/null @@ -1,105 +0,0 @@ -============================================================================== -BUNCHING INFERENCE — REGENERATED FROM CURRENT ESTIMATOR (bunching/model.py) -Vintage 2023-24 (£85k), T* = 85.0, RNG_SEED = 20240617, B = 200 -Baseline: degree=7, window=±£15k, tau_e=0.05 -============================================================================== - -[1] BOOTSTRAP TABLE (tab:boot) — point / SE / 95% percentile CI ------------------------------------------------------------------------------- - point se ci_lo ci_hi n_boot -parameter -b 0.059885 0.004582 0.050097 0.068398 200 -b_llat 0.941023 0.074882 0.795223 1.085457 200 -E 8711.912433 661.555191 7920.404958 10515.575141 200 -sigma 4.854890 0.120713 4.575895 5.077208 200 -Pi 0.210907 0.004651 0.200092 0.219420 200 -eps_local_median 0.447983 0.027343 0.404949 0.496093 200 -eps_marginal 0.656829 0.081588 0.509753 0.821444 200 -dyR 5.583044 0.693497 4.332897 6.982270 200 - -(Pi point estimate = 0.2109; bootstrapped via summary row 'Pi') - - -[2] DEGREE x WINDOW SENSITIVITY (tab:degwin) — full grid, one code version ------------------------------------------------------------------------------- - degree window b b_llat E sigma eps_local_median - 5 10.0 0.150428 1.661197 13338.722356 5.615162 0.468555 - 5 15.0 0.139050 2.357746 18822.580978 5.161476 0.705882 - 5 20.0 0.141365 3.255463 25595.643506 4.947221 0.866789 - 5 25.0 0.152190 4.424472 34172.236574 5.109582 1.043650 - 6 10.0 0.076640 0.790229 7261.587858 5.421902 0.407559 - 6 15.0 0.044540 0.680790 6574.690639 4.985034 0.441282 - 6 20.0 0.015359 0.379377 3822.475982 4.210163 0.352928 - 6 25.0 -0.027983 0.044262 471.228923 NaN 0.146725 - 7 10.0 0.091354 0.974704 8538.992282 5.070560 0.470588 - 7 15.0 0.059885 0.941023 8711.912433 4.854890 0.447983 - 7 20.0 0.034128 0.750732 7312.596011 4.619318 0.429669 - 7 25.0 -0.003942 0.300294 3088.756051 3.645150 0.251975 - 8 10.0 0.118478 1.323128 10805.769773 4.921910 0.423842 - 8 15.0 0.118450 2.043347 16329.327339 4.534296 0.588235 - 8 20.0 0.165624 3.863177 29363.773200 4.959291 0.772223 - 8 25.0 0.301498 8.553605 59931.057978 7.569222 0.953864 - -Paper's tab:degwin cells (deg 6,7 x win 10,15,20): - degree window b b_llat E sigma eps_local_median - 6 10.0 0.076640 0.790229 7261.587858 5.421902 0.407559 - 6 15.0 0.044540 0.680790 6574.690639 4.985034 0.441282 - 6 20.0 0.015359 0.379377 3822.475982 4.210163 0.352928 - 7 10.0 0.091354 0.974704 8538.992282 5.070560 0.470588 - 7 15.0 0.059885 0.941023 8711.912433 4.854890 0.447983 - 7 20.0 0.034128 0.750732 7312.596011 4.619318 0.429669 - - -[3] CONSTRAINED vs UNCONSTRAINED MASS, and empirical excess span dy* ------------------------------------------------------------------------------- -UNCONSTRAINED (plain OLS, fixed ±£15k window, independent E and Delta_R): - E = 7,820.1 - Delta_R = 16,523.7 - -CONSTRAINED (mass-conserving, endogenous marginal buncher): - E = 8,711.9 - Delta_R = 9,214.5 - y_R = 90.583 (£k) - dy* = y_R - T* = 5.583 (£k) -> £5.6k - - Constrained b = 0.0599 - Constrained sigma = 4.8549 - - -[4] tau_e SENSITIVITY (sigma and Pi) ------------------------------------------------------------------------------- - tau_e sigma Pi - 0.025 9.592782 0.210907 - 0.050 4.854890 0.210907 - 0.075 3.275286 0.210907 - 0.100 2.485263 0.210907 - - -[4b] SIGMOID-STEEPNESS (k) SUBSECTION — orphan check ------------------------------------------------------------------------------- -No sigmoid schedule, no steepness parameter k, and no per-k dominated-region -width computation exist anywhere in the current code base (bunching/, notch/, -analysis/). notch/model.py uses the EXACT Kleven-Waseem dominated width -a = T* * tau/(1-tau). For T*=85, tau=0.20: - a = 85 * 0.20/0.80 = 21.250 (£k) -> £21.25k -The k=0.0001/0.001/0.002/0.005/0.01 -> width numbers (19.7k etc.) are NOT -reproducible: the smoothed-schedule structural model that produced them is -not in the consolidated code. Subsection is ORPHANED. - - -[5] CURRENTLY-PRINTED (WRONG) vs CORRECTED (current code) ------------------------------------------------------------------------------- -tab:boot: - b : printed 0.060/0.005/[0.050,0.068] -> 0.0599/0.0046/[0.0501,0.0684] - E : printed 8712/662/[7877,10483] -> 8,711.9/661.6/[7,920.4,10,515.6] - sigma : printed 4.85/0.12/[4.61,5.10] -> 4.8549/0.1207/[4.5759,5.0772] - Pi : printed 0.211/0.005/[0.202,0.221] -> 0.2109/0.0047/[0.2001,0.2194] - notchW : printed 0.448/0.027/[0.419,0.519] -> 0.4480/0.0273/[0.4049,0.4961] - margB : printed 0.657/0.082/[0.536,0.828] -> 0.6568/0.0816/[0.5098,0.8214] - -tab:degwin baseline (deg7, win15k): - printed b/E/sigma/notchW = 0.060/8712/4.85/0.45 - current b/E/sigma/notchW = 0.0599/8,711.9/4.8549/0.4480 - -Constrained Delta_R: printed 9,938 -> current 9214.5 -Empirical excess span dy*: printed 5.4k / 5.6k -> current £5.6k diff --git a/results/calibration_accuracy.txt b/results/calibration_accuracy.txt index 3e9d0bf..4b32999 100644 --- a/results/calibration_accuracy.txt +++ b/results/calibration_accuracy.txt @@ -8,40 +8,40 @@ dimensions and excludes the VAT-liability-by-sector diagnostic. Vintage 2023-24 | threshold £85k ================================================================ rows (firm types): 2,941,232 - weighted population: 2,481,542 firms + weighted population: 2,460,542 firms ---------------------------------------------------------------- Dimension accuracy error ---------------------------------------------------------------- - HMRC Turnover Bands 93.0% 7.0% - ONS Population 91.1% 8.9% - Employment Bands 78.2% 21.8% - Sector Distribution 92.5% 7.5% - VAT Liability by Band 94.6% 5.4% + HMRC Turnover Bands 93.8% 6.2% + ONS Population 90.3% 9.7% + Employment Bands 77.9% 22.1% + Sector Distribution 92.7% 7.3% + VAT Liability by Band 91.3% 8.7% ---------------------------------------------------------------- - Overall (5 calibrated dims) 89.9% 10.1% + Overall (5 calibrated dims) 89.2% 10.8% ---------------------------------------------------------------- Informational diagnostic (not a calibration target): - VAT Liability by Sector 47.1% 52.9% + VAT Liability by Sector 45.2% 54.8% ================================================================ ================================================================ Vintage 2024-25 | threshold £90k ================================================================ rows (firm types): 2,945,974 - weighted population: 2,577,078 firms + weighted population: 2,531,324 firms ---------------------------------------------------------------- Dimension accuracy error ---------------------------------------------------------------- - HMRC Turnover Bands 92.7% 7.3% - ONS Population 94.2% 5.8% - Employment Bands 89.7% 10.3% - Sector Distribution 94.5% 5.5% - VAT Liability by Band 81.4% 18.6% + HMRC Turnover Bands 93.1% 6.9% + ONS Population 92.6% 7.4% + Employment Bands 92.4% 7.6% + Sector Distribution 94.2% 5.8% + VAT Liability by Band 92.0% 8.0% ---------------------------------------------------------------- - Overall (5 calibrated dims) 90.5% 9.5% + Overall (5 calibrated dims) 92.8% 7.2% ---------------------------------------------------------------- Informational diagnostic (not a calibration target): - VAT Liability by Sector 44.5% 55.5% + VAT Liability by Sector 44.8% 55.2% ================================================================ Done: 2/2 vintage(s) reported. diff --git a/results/dominated_region_mass.txt b/results/dominated_region_mass.txt index d819bdc..4f09bce 100644 --- a/results/dominated_region_mass.txt +++ b/results/dominated_region_mass.txt @@ -14,16 +14,16 @@ Bands measured on the WEIGHTED synthetic firm population. rate / band width a (GBP) band (GBP k) OBS CF NET disp. ------------------------------------------------------------------------------------------ -20% (baseline notch) 21,250 [85, 106.250) 136,574 150,236 13,662 -15% band 15,000 [85, 100.000) 96,500 110,568 14,068 -10% band 9,444 [85, 94.444) 66,085 78,018 11,933 +20% (baseline notch) 21,250 [85, 106.250) 156,040 153,747 -2,293 +15% band 15,000 [85, 100.000) 115,929 112,830 -3,100 +10% band 9,444 [85, 94.444) 84,661 79,432 -5,230 ------------------------------------------------------------------------------------------ INTERPRETATION (baseline 20% notch, band [85,000, 106,250)): - Observed firms in dominated region ........ 136,574 - Counterfactual total density in band (CF).. 150,236 - NET displaced mass in band (CF - OBS) ..... 13,662 - CF mass as share of firms near threshold .. 0.517 + Observed firms in dominated region ........ 156,040 + Counterfactual total density in band (CF).. 153,747 + NET displaced mass in band (CF - OBS) ..... -2,293 + CF mass as share of firms near threshold .. 0.503 Note: the headline displaced-mass number is NET (CF - OBS), not the total CF density. The band is wide, so most CF firms in it would @@ -31,28 +31,31 @@ INTERPRETATION (baseline 20% notch, band [85,000, 106,250)): NET deficit is the mass the notch evacuates from the dominated region. REFORM-SHRUNK BANDS (net displaced mass): - 15% -> band width GBP 15,000: net displaced = 14,068 firms (CF total 110,568) - 10% -> band width GBP 9,444: net displaced = 11,933 firms (CF total 78,018) - -CONSISTENCY CHECK vs paper's reduced-form bunching: - excess mass below T* E = 8,712 firms - missing mass above T* Delta_R = 9,215 firms - displaced share Pi = 0.211 - marginal buncher y_R = GBP 90,583 - NET displaced mass in 20% dominated band = 13,662 firms - -> NET band mass / E = 1.57 - -> NET band mass / Delta_R = 1.48 - - By mass conservation the excess mass E (~8.7k) that bunches just below - T* is the mass that, absent the notch, would have spread into the region - above T*. The NET displaced mass in the dominated band (~13.7k) is the - same order of magnitude as E and Delta_R (~9.2k) -- it slightly exceeds - them because the wide 21.25k band also captures part of the smooth - density deficit beyond the marginal buncher y_R = GBP 90,583, not just - the bunching window. CONSISTENT: no order-of-magnitude discrepancy. - (The TOTAL CF density in the band, 150k, is NOT the displaced mass and + 15% -> band width GBP 15,000: net displaced = -3,100 firms (CF total 112,830) + 10% -> band width GBP 9,444: net displaced = -5,230 firms (CF total 79,432) + +SECONDARY NOTCH at the reduced-rate band top (T1 = GBP 105,000): + A banded reduced rate reverts to tau=20% at T1, adding a SECOND + dominated region a' = T1*(tau-r)/(1-tau). Total dominated turnover and + mass = primary [T*, T*+a] + secondary [T1, T1+a']. + 15% band secondary [105, 111.562) width GBP 6,563 OBS = 36,746 + primary OBS 115,929 + secondary OBS 36,746 = TOTAL 152,675 (baseline 156,040, -2.2%) + 10% band secondary [105, 118.125) width GBP 13,125 OBS = 70,179 + primary OBS 84,661 + secondary OBS 70,179 = TOTAL 154,840 (baseline 156,040, -0.8%) + +REDUCED-FORM BUNCHING on this population (context for the masses above): + excess mass below T* E = 7,933 firms + missing mass above T* Delta_R = 5,761 firms + marginal buncher y_R = GBP 100,000 + NET displaced mass in 20% dominated band = -2,293 firms + + By mass conservation the excess mass E that bunches just below T* + is the mass that, absent the notch, would have spread into the + region above T*. Compare magnitudes of E, Delta_R, and the NET band + mass; the wide band also captures smooth-density deficit beyond y_R. + (The TOTAL CF density in the band is NOT the displaced mass and should not be compared to E -- that would be a category error.) - total observed weighted mass on [20,140] est. range = 919,713 + total observed weighted mass on [20,140] est. range = 935,138 -script: analysis/dominated_region_mass.py +script: firm-microsim-dominated-region diff --git a/results/dynamic_cost_vs_elasticity.png b/results/dynamic_cost_vs_elasticity.png new file mode 100644 index 0000000..1595445 Binary files /dev/null and b/results/dynamic_cost_vs_elasticity.png differ diff --git a/results/dynamic_notch_fit_e005.png b/results/dynamic_notch_fit_e005.png new file mode 100644 index 0000000..fc238fc Binary files /dev/null and b/results/dynamic_notch_fit_e005.png differ diff --git a/results/dynamic_notch_fit_e017.png b/results/dynamic_notch_fit_e017.png new file mode 100644 index 0000000..d40773b Binary files /dev/null and b/results/dynamic_notch_fit_e017.png differ diff --git a/results/dynamic_notch_fit_e032.png b/results/dynamic_notch_fit_e032.png new file mode 100644 index 0000000..e3b3049 Binary files /dev/null and b/results/dynamic_notch_fit_e032.png differ diff --git a/results/dynamic_reform_distribution_raisethresholdto100k_e017.png b/results/dynamic_reform_distribution_raisethresholdto100k_e017.png new file mode 100644 index 0000000..ba8cab4 Binary files /dev/null and b/results/dynamic_reform_distribution_raisethresholdto100k_e017.png differ diff --git a/results/dynamic_reform_distribution_reducedrate1085k105k_e017.png b/results/dynamic_reform_distribution_reducedrate1085k105k_e017.png new file mode 100644 index 0000000..67936c3 Binary files /dev/null and b/results/dynamic_reform_distribution_reducedrate1085k105k_e017.png differ diff --git a/results/dynamic_reform_distribution_reducedrate1585k105k_e017.png b/results/dynamic_reform_distribution_reducedrate1585k105k_e017.png new file mode 100644 index 0000000..48038b1 Binary files /dev/null and b/results/dynamic_reform_distribution_reducedrate1585k105k_e017.png differ diff --git a/results/dynamic_reform_results.txt b/results/dynamic_reform_results.txt index b6772b5..939b045 100644 --- a/results/dynamic_reform_results.txt +++ b/results/dynamic_reform_results.txt @@ -1,6 +1,6 @@ Iso-elastic (Kleven-Waseem) dynamic VAT-notch simulator — reform results vintage=2023-24 T*=£85,000 tau_max=0.20 taper/band top=£105,000 -Repo-generated baseline registered VAT base = £183.589bn. +Repo-generated baseline registered VAT base = £184.765bn. A SINGLE turnover elasticity e governs the response. The behavioural cost is now a defensible e-SENSITIVITY RANGE over e in {0.05,0.17,0.32} (headline 0.17). Ability n is an accounting anchor recovered under the £85k notch given e; e is @@ -15,10 +15,10 @@ Marginal buncher n_H(e) [analytic; £]: Reform costs (change vs £85k-notch baseline): reform static e=0.05 e=0.17 e=0.32 #reopt(e=0.17) near-thr Δ - Raise threshold to £100k £ -508m £ -444m £ -292m £ -111m 50,155 +0 - Graduated taper (£85k→£105k) £ -336m £ -273m £ -156m £ -52m 54,440 +0 - Reduced rate 10% (£85k–£105k) £ -343m £ -322m £ -273m £ -210m 61,187 +0 - Reduced rate 15% (£85k–£105k) £ -171m £ -160m £ -135m £ -107m 51,226 +0 + Raise threshold to £100k £ -753m £ -753m £ -753m £ -753m 108,973 +0 + Graduated taper (£85k→£105k) £ -520m — — — + Reduced rate 10% (£85k–£105k) £ -484m £ -481m £ -475m £ -467m 137,944 +0 + Reduced rate 15% (£85k–£105k) £ -242m £ -240m £ -235m £ -228m 137,944 +0 Direction: a LARGER e makes every reform CHEAPER (smaller revenue loss). Each reform lowers the effective rate on the band, so the iso-elastic response scales diff --git a/results/figures_cli.log b/results/figures_cli.log new file mode 100644 index 0000000..942bc62 --- /dev/null +++ b/results/figures_cli.log @@ -0,0 +1,14 @@ +Generating figures (both vintages)... +Generating firms_by_turnover_band_85k.png... + saved /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/results/firms_by_turnover_band_85k.png +Generating vat_firms_by_turnover_band_85k.png... + saved /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/results/vat_firms_by_turnover_band_85k.png +Generating turnover_distribution_85k.png... + saved /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/results/turnover_distribution_85k.png +Generating firms_by_turnover_band_90k.png... + saved /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/results/firms_by_turnover_band_90k.png +Generating vat_firms_by_turnover_band_90k.png... + saved /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/results/vat_firms_by_turnover_band_90k.png +Generating turnover_distribution_90k.png... + saved /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/results/turnover_distribution_90k.png + done. diff --git a/results/firms_by_turnover_band_85k.png b/results/firms_by_turnover_band_85k.png index 6f66321..daff466 100644 Binary files a/results/firms_by_turnover_band_85k.png and b/results/firms_by_turnover_band_85k.png differ diff --git a/results/firms_by_turnover_band_90k.png b/results/firms_by_turnover_band_90k.png index eec0129..e8de99a 100644 Binary files a/results/firms_by_turnover_band_90k.png and b/results/firms_by_turnover_band_90k.png differ diff --git a/results/firms_impact_2025_26.png b/results/firms_impact_2025_26.png index 25ceccf..d62d50c 100644 Binary files a/results/firms_impact_2025_26.png and b/results/firms_impact_2025_26.png differ diff --git a/results/formulation_a_optima.png b/results/formulation_a_optima.png index 6c6bbf2..a20f2ae 100644 Binary files a/results/formulation_a_optima.png and b/results/formulation_a_optima.png differ diff --git a/results/iso_optimum_verification.png b/results/iso_optimum_verification.png index cccc58a..f749f0a 100644 Binary files a/results/iso_optimum_verification.png and b/results/iso_optimum_verification.png differ diff --git a/results/placebo_bunching.txt b/results/placebo_bunching.txt index 97cbd0a..73f49e3 100644 --- a/results/placebo_bunching.txt +++ b/results/placebo_bunching.txt @@ -26,11 +26,11 @@ Results ------- population b E b_llat y_R ------------------------------------------------------------------ -ACTUAL (control) +0.0599 8,712 0.941 90.58 -PLACEBO A (reweight) -0.0626 0 0.000 84.00 -PLACEBO B (regenerate) -0.0161 99 0.010 84.33 +ACTUAL (control) +0.0106 7,933 1.911 100.00 +PLACEBO A (reweight) -0.0591 0 0.000 84.00 +PLACEBO B (regenerate) -0.0729 0 0.395 85.00 Density step at £85k (80-85 vs 85-90 per £1k): - ACTUAL below=10,186 above=6,520 step=+56.2% - PLACEBO A below=8,792 above=8,042 step=+9.3% + ACTUAL below=11,208 above=9,583 step=+17.0% + PLACEBO A below=9,092 above=8,497 step=+7.0% diff --git a/results/placebo_cli.log b/results/placebo_cli.log new file mode 100644 index 0000000..c847d9d --- /dev/null +++ b/results/placebo_cli.log @@ -0,0 +1,12 @@ +============================================================================== + PLACEBO BUNCHING TEST (vintage 2023-24, threshold £85k) +============================================================================== + ACTUAL (control) b=+0.0106 E= 7,933 b_llat=1.911 y_R=100.00 + PLACEBO A (reweight) b=-0.0591 E= 0 b_llat=0.000 y_R=84.00 + + Density step at £85k (firms per £1k, 80-85 vs 85-90): + ACTUAL : below=11,208 above=9,583 step=+17.0% + PLACEBO A: below=9,092 above=8,497 step=+7.0% + + PLACEBO B (regenerate) b=-0.0729 E= 0 b_llat=0.395 y_R=85.00 +Wrote /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/results/placebo_bunching.txt diff --git a/results/recovery_bunching.txt b/results/recovery_bunching.txt index 347b74a..21d12ac 100644 --- a/results/recovery_bunching.txt +++ b/results/recovery_bunching.txt @@ -1,73 +1,39 @@ -RECOVERY / COVERAGE TEST — £85k UK VAT bunching estimator (vintage 2023-24) +RECOVERY / POWER TEST — £85k UK VAT bunching estimator (vintage 2023-24) ============================================================================== -Purpose -------- -The placebo (results/placebo_bunching.txt) shows the estimator returns no -bunching when none is present (no false positive). This test shows the -complementary property: the estimator has POWER to recover a real -behavioural response of KNOWN magnitude (coverage / recovery). - -Method +Design ------ -1. Baseline: take the actual £85k synthetic firms and apply the Placebo-A - reweighting (smooth log-quadratic density across £85k, no step), giving - a null world with b=-0.0626, headline E=0, signed - below-threshold excess = -8,927 (a small density DEFICIT). -2. Injection: relocate a KNOWN mass E_true from a donor window just above - the threshold [85, 100) to a bunching window just below it - [75, 85), with a triangular profile peaking at £85k. - This is mass-conserving and is the firm location-choice the generator - lacks. The relocated mass IS the injected excess mass E_true. -3. Run the SAME estimator (bunching.model._run_estimator, degree=7, - window=±15k) and record recovered excess and b_hat. - - -Measurement note. The headline E floors per-bin excess at zero -(max(f_obs-f_cf,0)). Because the smoothed baseline sits in a signed -deficit just below £85k, the floor hides the part of an injected spike -that merely refills that deficit. The PRIMARY recovery quantity is the -CHANGE in the SIGNED below-threshold excess relative to baseline -(E_recovered = signed_excess - baseline signed_excess), which is the -deficit-differenced coverage measure. The floored E_hat is also reported. +1. Baseline: the £85k synthetic firms under the Placebo-A reweighting + (smooth log-quadratic density across £85k), a step-free null world: + b=-0.0591, E=0, y_R=84.00. +2. Injection (Kleven–Waseem-consistent): firms in the donor region + (85, 112] relocate to [80, 85) with probability + declining linearly from the threshold to zero at the true marginal + buncher y_R = 112 — so the missing-mass region extends + 12k BEYOND the ±15k exclusion window, as with + genuine bunching. Mass is conserved. +3. Score with the HEADLINE estimator outputs only (floored excess mass + E, endogenous y_R): no side statistics that require knowing the null. Results ------- - E_true E_recovered recovery E_hat(fl) b_hat b_llat y_R ----------------------------------------------------------------------- - 2,000 1,792 89.6% 0 -0.0500 0.000 84.00 - 5,000 4,479 89.6% 932 -0.0312 0.103 86.48 - 8,000 7,167 89.6% 2,912 -0.0123 0.341 88.74 + E_true E_hat recovery y_R_hat b_hat b_llat +---------------------------------------------------------- + 2,000 298 14.9% 85.79 -0.0468 0.032 + 5,000 2,445 48.9% 91.89 -0.0281 0.309 + 8,000 4,918 61.5% 100.00 -0.0094 0.809 -Baseline (null, no injection): b=-0.0626 E=0 signed_excess=-8,927 -Mean recovery across magnitudes: 89.6% (monotone in E_true: True) +Baseline (null, no injection): b=-0.0591 E=0 y_R=84.00 +True marginal buncher: y_R = 112. Mean recovery: 41.8% (monotone in E_true: True). -Verdict +Reading ------- -The estimator HAS POWER: every injected behavioural signal is detected, -the recovered excess rises monotonically with E_true (monotone=True), -and the bunching ratio b_hat moves steadily up from the baseline as the -injection grows. Recovery is approximately unbiased (recovers ~90% of injected mass). The ~10% shortfall is a known, -benign attenuation: the degree-7 polynomial counterfactual partially -re-absorbs the injected spike and the fixed ±15k exclusion window clips -its tails, so the estimator slightly UNDER-states a true response — it -does not over-state one. Combined with the placebo (no false positive -when behaviour is absent), this completes the validation: the estimator -has BOTH no-false-positive AND power to detect a genuine location-choice -response. - -Caveat for the floored E. Read on its own, the headline E badly -understates small injections (E_hat=0 at E_true=2,000) ONLY because the -smoothed baseline starts in a below-threshold deficit that the spike must -first refill before any POSITIVE excess registers. This is a property of -the flooring, not a failure of power, which is why the signed-excess -change is the correct coverage measure. - -One-line summary for the paper ------------------------------- -In a recovery exercise that injects behavioural bunching of known -magnitude (E_true = 2,000/5,000/8,000 firms) into a step-free synthetic -population, the estimator detects every signal and recovers ~90% of -the injected excess mass (slightly attenuated, never inflated), confirming -it has power; together with the placebo's null result this shows the -estimator is both specific (no false positive) and sensitive (has power). +Recovery below 100% is genuine estimator attenuation, now measured +rather than asserted: the counterfactual is fitted on bins that include +the depressed (100, 112] missing-mass region outside the exclusion +window, pulling the fitted counterfactual down and truncating the +measured missing mass; the mass-conservation search then places y_R_hat +accordingly. The estimator under-states a true response and does not +over-state one; together with the placebo's null result (no false +positive on a step-free world) this characterises the estimator as +specific and, with quantified attenuation, sensitive. diff --git a/results/reform_menu_common_base.txt b/results/reform_menu_common_base.txt index ca031b4..313a2d6 100644 --- a/results/reform_menu_common_base.txt +++ b/results/reform_menu_common_base.txt @@ -3,31 +3,31 @@ REFORM MENU ON A SINGLE COMMON BASE (tab:schedule_costs) Base: GBP85k notch, 2023-24 microdata, UNAGED ======================================================================== Dataset : data/synthetic/synthetic_firms_2023-24.csv -VAT base (>=85k) : GBP 183.589 bn -Firms in [85k,105k): 123,085 +VAT base (>=85k) : GBP 184.765 bn +Firms in [85k,105k): 140,826 --- Threshold relocation GBP85k -> GBP100k (recomputed) ------------- - (A) DIRECT band-sum [85k,100k) : -507.9 m firms -94.3 (000s) - as % of VAT base : -0.277% - (B) SMOOTH counterfactual : -494.7 m firms -54.9 (000s) - HEADLINE (adopt A) : -508 m firms -94.3 (000s) + (A) DIRECT band-sum [85k,100k) : -752.9 m firms -111.9 (000s) + as % of VAT base : -0.408% + (B) SMOOTH counterfactual : -697.0 m firms -100.7 (000s) + HEADLINE (adopt A) : -753 m firms -111.9 (000s) --- Schedule reforms (computed on the SAME repo-generated base) ----- - Graduated taper [85k,105k] : -336.3 m affected firms -123.1 (000s) - Reduced rate 10% [85k,105k] : -342.9 m affected firms -123.1 (000s) - Reduced rate 15% [85k,105k] : -171.4 m affected firms -123.1 (000s) + Graduated taper [85k,105k] : -519.6 m affected firms -140.8 (000s) + Reduced rate 10% [85k,105k] : -484.0 m affected firms -140.8 (000s) + Reduced rate 15% [85k,105k] : -242.0 m affected firms -140.8 (000s) ======================================================================== CORRECTED tab:schedule_costs (repo-generated GBP85k, 2023-24 unaged) ======================================================================== Reform Lever Static (GBPm) -------------------------------------------------------------------------- -Raise threshold to GBP100,000 Location -508 -Graduated taper [85k,105k] Shape (phase-in) -336 -Reduced rate 10% [85k,105k] Rate (step) -343 -Reduced rate 15% [85k,105k] Rate (step) -171 +Raise threshold to GBP100,000 Location -753 +Graduated taper [85k,105k] Shape (phase-in) -520 +Reduced rate 10% [85k,105k] Rate (step) -484 +Reduced rate 15% [85k,105k] Rate (step) -242 ======================================================================== Firm-in-band counts: - Raise-to-100k band [85k,100k): 94,309 firms released - Taper / reduced-rate band [85k,105k): 123,085 firms + Raise-to-100k band [85k,100k): 111,940 firms released + Taper / reduced-rate band [85k,105k): 140,826 firms diff --git a/results/revenue_impact_2025_26.png b/results/revenue_impact_2025_26.png index 3c9c110..f50c5c0 100644 Binary files a/results/revenue_impact_2025_26.png and b/results/revenue_impact_2025_26.png differ diff --git a/results/seed_sensitivity.txt b/results/seed_sensitivity.txt new file mode 100644 index 0000000..a9afb3a --- /dev/null +++ b/results/seed_sensitivity.txt @@ -0,0 +1,10 @@ +GENERATOR-SEED SENSITIVITY (full-size 2023-24 builds; seeds 42/7/99) +definitive build: OBR near-threshold targets, side-consistent frame +scaling, no below-threshold liability calibration +====================================================================== +run E b_llat raise £m taper £m base £bn +seed 42 (paper) 7,933 1.91 752.9 519.6 184.8 +seed 7 7,750 1.88 754.2 520.9 184.7 +seed 99 8,072 1.93 749.9 517.9 184.8 + +half-range across seeds: E ±161 | b_llat ±0.02 | raise ±£2.1m | taper ±£1.5m | base ±£0.08bn diff --git a/results/static_sweep.txt b/results/static_sweep.txt new file mode 100644 index 0000000..18aa5bd --- /dev/null +++ b/results/static_sweep.txt @@ -0,0 +1,49 @@ +STATIC RESULTS DUMP +========================================================================== + +Anchor reform (85k -> 90k, 2023-24 vintage = HMRC's pre-reform basis) +model vs HMRC published costing (Spring Budget 2024), by fiscal year; +baseline column = counterfactual threshold path (85/85/87/89/92k). +-------------------------------------------------------------------------- + year hmrc_impact_m policyengine_impact_m +2024-25 -150.0 -316.6 +2025-26 -185.0 -322.9 +2026-27 -125.0 -195.1 +2027-28 -50.0 -66.4 +2028-29 65.0 102.9 + +Voluntary-retention sensitivity (anchor, per year): headline assumes +every released firm deregisters (full liability lost). If the Liu et +al. (2021) voluntary share (43%) of released-firm liability is +retained, the impact scales accordingly: + 2024-25: headline -316.6m -> retention-adjusted -180.5m (HMRC -150m) + 2025-26: headline -322.9m -> retention-adjusted -184.1m (HMRC -185m) + 2026-27: headline -195.1m -> retention-adjusted -111.2m (HMRC -125m) + 2027-28: headline -66.4m -> retention-adjusted -37.8m (HMRC -50m) + 2028-29: headline +102.9m -> retention-adjusted +58.7m (HMRC +65m) + +Threshold sweep (2024-25 vintage, GBP 90k baseline, 2025-26 fiscal year) +counterfactual method: smooth above-threshold extrapolation (degree 1) +-------------------------------------------------------------------------- + threshold_k revenue_change_m firms_change_k + 70.0 1042.801081 145.683685 + 75.0 776.246417 107.201802 + 80.0 513.594682 70.093893 + 85.0 254.845876 34.359959 + 90.0 -0.000000 -0.000000 + 95.0 -250.942947 -32.985985 + 100.0 -497.982966 -64.597995 + 105.0 -741.120055 -94.836030 + 110.0 -980.354215 -123.700091 + 115.0 -1215.685446 -151.190177 + 120.0 -1447.113747 -177.306289 + +Total VAT revenue at GBP 90k, 2025-26: 200.9bn +Total VAT revenue at GBP 90k, 2026-27: 206.1bn + +Bases and calibration-target comparison +-------------------------------------------------------------------------- + 2023-24: registered base (>= threshold, unaged) = 184.8bn + 2024-25: registered base (>= threshold, unaged) = 190.7bn + +Sweep thresholds: [70000, 75000, 80000, 85000, 90000, 95000, 100000, 105000, 110000, 115000, 120000] diff --git a/results/turnover_distribution_85k.png b/results/turnover_distribution_85k.png index 9e9822a..5f54e69 100644 Binary files a/results/turnover_distribution_85k.png and b/results/turnover_distribution_85k.png differ diff --git a/results/turnover_distribution_90k.png b/results/turnover_distribution_90k.png index dab3f36..1b69a3f 100644 Binary files a/results/turnover_distribution_90k.png and b/results/turnover_distribution_90k.png differ diff --git a/results/vat_firms_by_turnover_band_85k.png b/results/vat_firms_by_turnover_band_85k.png index 384baff..52343be 100644 Binary files a/results/vat_firms_by_turnover_band_85k.png and b/results/vat_firms_by_turnover_band_85k.png differ diff --git a/results/vat_firms_by_turnover_band_90k.png b/results/vat_firms_by_turnover_band_90k.png index bf51d94..c486af5 100644 Binary files a/results/vat_firms_by_turnover_band_90k.png and b/results/vat_firms_by_turnover_band_90k.png differ diff --git a/results/vat_threshold_revenue_impact.png b/results/vat_threshold_revenue_impact.png index 2d33be3..35bd2a1 100644 Binary files a/results/vat_threshold_revenue_impact.png and b/results/vat_threshold_revenue_impact.png differ diff --git a/scripts/seed_sensitivity.py b/scripts/seed_sensitivity.py new file mode 100644 index 0000000..a9bc2b5 --- /dev/null +++ b/scripts/seed_sensitivity.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 +"""Generator-seed sensitivity of the headline 2023-24 statistics. + +Rebuilds the full-size 2023-24 population under alternative generator seeds +and recomputes, on each build, the headline numbers the paper quotes: + + * excess mass E and b_llat (default estimator settings), + * the raise-to-100k cost (direct band-sum of [85k, 100k) liability), + * the graduated-taper cost (shared dynamic schedule code, static mode), + * the registered VAT base (>= 85k). + +The paper reports point estimates with no standard errors (the construction +is deterministic given the seed; there is no sampling estimand), so this +dispersion across seeds is the honest scale of generator Monte Carlo noise. + +The first seed listed is read from the canonical CSV if it matches the +config default (that CSV *is* the paper build); other seeds are full +generate+calibrate runs held in memory (several minutes each). + +Run: .venv/bin/python scripts/seed_sensitivity.py --seeds 42 7 99 +Writes: results/seed_sensitivity.txt +""" +from __future__ import annotations + +import argparse + +import pandas as pd + +from firm_microsim.bunching.model import RANGE_HI, RANGE_LO, _run_estimator +from firm_microsim.config import DEFAULT_CONFIG, RESULTS_DIR, SYNTHETIC_DATA_DIR +from firm_microsim.dynamic.model import E_HEADLINE, build_reforms, reform_revenue +from firm_microsim.generate import generate + +VINTAGE = "2023-24" +T_STAR = 85_000.0 +T_NEW = 100_000.0 +OUT = RESULTS_DIR / "seed_sensitivity.txt" +COLS = ["annual_turnover_k", "vat_liability_k", "weight"] + + +def headline_stats(df: pd.DataFrame) -> dict: + """Compute the paper's headline 2023-24 statistics on one build.""" + tk = df["annual_turnover_k"].to_numpy() + t = tk * 1000.0 + liab = df["vat_liability_k"].to_numpy() * 1000.0 + w = df["weight"].to_numpy() + + # Same population filter as BunchingEstimator.__init__ — the headline + # E/b_llat are defined on the [RANGE_LO, RANGE_HI] estimation range. + in_range = (tk >= RANGE_LO) & (tk <= RANGE_HI) + est = _run_estimator(tk[in_range], w[in_range], T_STAR / 1000.0) + + band = (t >= T_STAR) & (t < T_NEW) + raise_m = (liab[band] * w[band]).sum() / 1e6 + + reform_df = pd.DataFrame({"turnover": t, "liab": liab, "weight": w}) + taper_schedule = build_reforms()["taper"][0] + taper = reform_revenue(reform_df, taper_schedule, E_HEADLINE, behavioural=False) + taper_m = -taper["d_rev"] / 1e6 + + reg = t >= T_STAR + base_bn = (liab[reg] * w[reg]).sum() / 1e9 + + return { + "E": est["E"], + "b_llat": est["b_llat"], + "raise_m": raise_m, + "taper_m": taper_m, + "base_bn": base_bn, + } + + +def build_for_seed(seed: int) -> pd.DataFrame: + """Return the full-size 2023-24 build for ``seed`` (canonical CSV if it + is the config-default seed, else a fresh in-memory generate run).""" + canonical = SYNTHETIC_DATA_DIR / f"synthetic_firms_{VINTAGE}.csv" + if seed == DEFAULT_CONFIG.seed and canonical.exists(): + return pd.read_csv(canonical, usecols=COLS) + df = generate(vintage=VINTAGE, seed=seed, write=False) + return df[COLS] + + +def main(argv: list[str] | None = None) -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--seeds", type=int, nargs="+", default=[42, 7, 99]) + args = parser.parse_args(argv) + + rows = [] + for seed in args.seeds: + print(f"[seed {seed}] building...", flush=True) + stats = headline_stats(build_for_seed(seed)) + label = f"seed {seed} (paper)" if seed == DEFAULT_CONFIG.seed else f"seed {seed}" + rows.append((label, stats)) + print(f"[seed {seed}] E={stats['E']:,.0f} b_llat={stats['b_llat']:.2f} " + f"raise={stats['raise_m']:.1f} taper={stats['taper_m']:.1f} " + f"base={stats['base_bn']:.1f}", flush=True) + + def half_range(key: str) -> float: + vals = [s[key] for _, s in rows] + return (max(vals) - min(vals)) / 2.0 + + lines = [ + "GENERATOR-SEED SENSITIVITY (full-size 2023-24 builds; " + f"seeds {'/'.join(str(s) for s in args.seeds)})", + "definitive build: OBR near-threshold targets, side-consistent frame", + "scaling, no below-threshold liability calibration", + "=" * 70, + f"{'run':<18}{'E':>8}{'b_llat':>8}{'raise £m':>10}{'taper £m':>10}{'base £bn':>10}", + ] + for label, s in rows: + lines.append( + f"{label:<18}{s['E']:>8,.0f}{s['b_llat']:>8.2f}" + f"{s['raise_m']:>10.1f}{s['taper_m']:>10.1f}{s['base_bn']:>10.1f}" + ) + lines += [ + "", + f"half-range across seeds: E ±{half_range('E'):,.0f} | " + f"b_llat ±{half_range('b_llat'):.2f} | " + f"raise ±£{half_range('raise_m'):.1f}m | " + f"taper ±£{half_range('taper_m'):.1f}m | " + f"base ±£{half_range('base_bn'):.2f}bn", + ] + text = "\n".join(lines) + print(text) + OUT.parent.mkdir(parents=True, exist_ok=True) + OUT.write_text(text + "\n") + print(f"\nWrote {OUT}") + + +if __name__ == "__main__": + main() diff --git a/seed_7.log b/seed_7.log new file mode 100644 index 0000000..b3dea8b --- /dev/null +++ b/seed_7.log @@ -0,0 +1,56 @@ +2026-07-02 09:47:17,591 - INFO - Generating synthetic firms (threshold=£85k, seed=7, device=cpu) +2026-07-02 09:47:17,592 - INFO - Loading processed input tables from /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/processed/2023-24 +2026-07-02 09:47:17,596 - INFO - ons_turnover 89 rows +2026-07-02 09:47:17,596 - INFO - ons_employment 89 rows +2026-07-02 09:47:17,596 - INFO - hmrc_population_band 20 rows +2026-07-02 09:47:17,596 - INFO - hmrc_population_sector 89 rows +2026-07-02 09:47:17,596 - INFO - hmrc_liability_band 20 rows +2026-07-02 09:47:17,596 - INFO - hmrc_liability_sector 88 rows +2026-07-02 09:47:17,601 - INFO - Near-threshold targets: 25 OBR £1k bins over [65k, 90k], interpolated 2023-24 profile, total 453,902 firms +2026-07-02 09:47:17,601 - INFO - ONS total firms: 2,724,775 +2026-07-02 09:47:17,601 - INFO - HMRC VAT-registered firms (latest year): 2,178,960 +2026-07-02 09:47:17,601 - INFO - Generating base firms from ONS structure... +2026-07-02 09:47:17,880 - INFO - Generated 2,724,775 base firms +2026-07-02 09:47:17,894 - INFO - Generating input values... +2026-07-02 09:47:18,083 - INFO - Input/output ratio: mean=0.60 std=0.19; mean value-added share=0.40; firms with negative value added: 0 +2026-07-02 09:47:18,084 - INFO - Assigning employment from ONS distribution... +2026-07-02 09:47:20,782 - INFO - Target matrix shape: (133, 2724775) +2026-07-02 09:47:20,783 - INFO - Targets: 7 turnover + 88 sector + 7 employment + 0 VAT-liability sector + 6 VAT-liability band + 25 near-threshold = 133 +2026-07-02 09:47:20,783 - INFO - Starting multi-objective weight optimization... +2026-07-02 09:47:21,614 - INFO - Iteration 0: loss = 0.166107 +2026-07-02 09:47:27,822 - INFO - Iteration 100: loss = 0.070799 +2026-07-02 09:47:33,757 - INFO - Iteration 200: loss = 0.051868 +2026-07-02 09:47:39,612 - INFO - Iteration 300: loss = 0.046145 +2026-07-02 09:47:45,551 - INFO - Iteration 400: loss = 0.045638 +2026-07-02 09:47:51,888 - INFO - Iteration 500: loss = 0.045584 +2026-07-02 09:47:58,282 - INFO - Iteration 600: loss = 0.045293 +2026-07-02 09:48:05,696 - INFO - Iteration 700: loss = 0.045172 +2026-07-02 09:48:12,316 - INFO - Iteration 800: loss = 0.045130 +2026-07-02 09:48:19,694 - INFO - Iteration 900: loss = 0.045229 +2026-07-02 09:48:27,021 - INFO - Optimization complete. Turnover-band fit: +2026-07-02 09:48:27,024 - INFO - £1_to_Threshold 861596 vs 766864 (87.6%) +2026-07-02 09:48:27,024 - INFO - £Threshold_to_£150k 331509 vs 305320 (91.4%) +2026-07-02 09:48:27,024 - INFO - £150k_to_£300k 364184 vs 334470 (91.1%) +2026-07-02 09:48:27,024 - INFO - £300k_to_£500k 196640 vs 184080 (93.2%) +2026-07-02 09:48:27,024 - INFO - £500k_to_£1m 193043 vs 180500 (93.1%) +2026-07-02 09:48:27,024 - INFO - £1m_to_£10m 251676 vs 235060 (92.9%) +2026-07-02 09:48:27,024 - INFO - Greater_than_£10m 47388 vs 44680 (93.9%) +2026-07-02 09:48:27,024 - INFO - Adding 216,500 zero/negative-turnover firms (HMRC)... +2026-07-02 09:48:27,222 - INFO - Added 216,457 zero-turnover firms +2026-07-02 09:48:27,223 - INFO - Assigning employment from ONS distribution... +2026-07-02 09:48:28,181 - INFO - Assigning VAT registration flags... +2026-07-02 09:48:28,201 - INFO - Voluntary VAT row rate: 0.885 (target 678,350 / base-weighted rows 766,864) +2026-07-02 09:48:28,214 - INFO - VAT: 1957911 mandatory + 677859 voluntary = 2635770 registered +2026-07-02 09:48:28,214 - INFO - Assembling final DataFrame... +2026-07-02 09:48:28,583 - INFO - Generated 2,941,232 rows, weighted population 2,462,494 +2026-07-02 09:48:29,792 - INFO - VAT liability £1-to-Threshold (informational, NOT calibrated): 27.3% +2026-07-02 09:48:29,792 - INFO - === CALIBRATION SUMMARY (threshold £85k) === +2026-07-02 09:48:29,792 - INFO - HMRC Turnover Bands: 93.7% +2026-07-02 09:48:29,792 - INFO - ONS Population: 90.4% +2026-07-02 09:48:29,792 - INFO - Employment Bands: 77.1% +2026-07-02 09:48:29,792 - INFO - Sector Distribution: 92.9% +2026-07-02 09:48:29,792 - INFO - VAT Liability by Band: 91.3% +2026-07-02 09:48:29,792 - INFO - Overall Accuracy (5 calibrated dims): 89.1% +2026-07-02 09:48:29,792 - INFO - VAT Liability by Sector: 44.7% [informational, NOT calibrated] +2026-07-02 09:48:29,792 - INFO - Total Population: 2,462,494 firms +2026-07-02 09:48:36,227 - INFO - Wrote 2,941,232 rows to /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/synthetic/seed_check_7.csv (142.7 MB) diff --git a/seed_99.log b/seed_99.log new file mode 100644 index 0000000..b3c5201 --- /dev/null +++ b/seed_99.log @@ -0,0 +1,56 @@ +2026-07-02 09:48:38,249 - INFO - Generating synthetic firms (threshold=£85k, seed=99, device=cpu) +2026-07-02 09:48:38,250 - INFO - Loading processed input tables from /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/processed/2023-24 +2026-07-02 09:48:38,255 - INFO - ons_turnover 89 rows +2026-07-02 09:48:38,255 - INFO - ons_employment 89 rows +2026-07-02 09:48:38,255 - INFO - hmrc_population_band 20 rows +2026-07-02 09:48:38,255 - INFO - hmrc_population_sector 89 rows +2026-07-02 09:48:38,255 - INFO - hmrc_liability_band 20 rows +2026-07-02 09:48:38,255 - INFO - hmrc_liability_sector 88 rows +2026-07-02 09:48:38,258 - INFO - Near-threshold targets: 25 OBR £1k bins over [65k, 90k], interpolated 2023-24 profile, total 453,902 firms +2026-07-02 09:48:38,258 - INFO - ONS total firms: 2,724,775 +2026-07-02 09:48:38,258 - INFO - HMRC VAT-registered firms (latest year): 2,178,960 +2026-07-02 09:48:38,258 - INFO - Generating base firms from ONS structure... +2026-07-02 09:48:38,549 - INFO - Generated 2,724,775 base firms +2026-07-02 09:48:38,564 - INFO - Generating input values... +2026-07-02 09:48:38,764 - INFO - Input/output ratio: mean=0.60 std=0.19; mean value-added share=0.40; firms with negative value added: 0 +2026-07-02 09:48:38,765 - INFO - Assigning employment from ONS distribution... +2026-07-02 09:48:42,644 - INFO - Target matrix shape: (133, 2724775) +2026-07-02 09:48:42,644 - INFO - Targets: 7 turnover + 88 sector + 7 employment + 0 VAT-liability sector + 6 VAT-liability band + 25 near-threshold = 133 +2026-07-02 09:48:42,644 - INFO - Starting multi-objective weight optimization... +2026-07-02 09:48:43,627 - INFO - Iteration 0: loss = 0.165361 +2026-07-02 09:48:50,278 - INFO - Iteration 100: loss = 0.070695 +2026-07-02 09:48:56,458 - INFO - Iteration 200: loss = 0.050949 +2026-07-02 09:49:02,768 - INFO - Iteration 300: loss = 0.046097 +2026-07-02 09:49:09,075 - INFO - Iteration 400: loss = 0.045659 +2026-07-02 09:49:16,273 - INFO - Iteration 500: loss = 0.045449 +2026-07-02 09:49:22,942 - INFO - Iteration 600: loss = 0.045464 +2026-07-02 09:49:31,390 - INFO - Iteration 700: loss = 0.045198 +2026-07-02 09:49:40,197 - INFO - Iteration 800: loss = 0.045094 +2026-07-02 09:49:48,090 - INFO - Iteration 900: loss = 0.045053 +2026-07-02 09:49:55,083 - INFO - Optimization complete. Turnover-band fit: +2026-07-02 09:49:55,083 - INFO - £1_to_Threshold 861989 vs 767160 (87.6%) +2026-07-02 09:49:55,083 - INFO - £Threshold_to_£150k 331486 vs 305320 (91.4%) +2026-07-02 09:49:55,084 - INFO - £150k_to_£300k 364374 vs 334470 (91.1%) +2026-07-02 09:49:55,084 - INFO - £300k_to_£500k 197046 vs 184080 (93.0%) +2026-07-02 09:49:55,084 - INFO - £500k_to_£1m 192508 vs 180500 (93.3%) +2026-07-02 09:49:55,084 - INFO - £1m_to_£10m 251403 vs 235060 (93.0%) +2026-07-02 09:49:55,084 - INFO - Greater_than_£10m 47439 vs 44680 (93.8%) +2026-07-02 09:49:55,084 - INFO - Adding 216,500 zero/negative-turnover firms (HMRC)... +2026-07-02 09:49:55,113 - INFO - Added 216,457 zero-turnover firms +2026-07-02 09:49:55,113 - INFO - Assigning employment from ONS distribution... +2026-07-02 09:49:56,135 - INFO - Assigning VAT registration flags... +2026-07-02 09:49:56,140 - INFO - Voluntary VAT row rate: 0.884 (target 678,350 / base-weighted rows 767,160) +2026-07-02 09:49:56,151 - INFO - VAT: 1957615 mandatory + 678470 voluntary = 2636085 registered +2026-07-02 09:49:56,151 - INFO - Assembling final DataFrame... +2026-07-02 09:49:56,504 - INFO - Generated 2,941,232 rows, weighted population 2,462,702 +2026-07-02 09:49:57,624 - INFO - VAT liability £1-to-Threshold (informational, NOT calibrated): 27.6% +2026-07-02 09:49:57,624 - INFO - === CALIBRATION SUMMARY (threshold £85k) === +2026-07-02 09:49:57,624 - INFO - HMRC Turnover Bands: 93.7% +2026-07-02 09:49:57,625 - INFO - ONS Population: 90.4% +2026-07-02 09:49:57,625 - INFO - Employment Bands: 77.0% +2026-07-02 09:49:57,625 - INFO - Sector Distribution: 92.8% +2026-07-02 09:49:57,625 - INFO - VAT Liability by Band: 91.3% +2026-07-02 09:49:57,625 - INFO - Overall Accuracy (5 calibrated dims): 89.0% +2026-07-02 09:49:57,625 - INFO - VAT Liability by Sector: 45.0% [informational, NOT calibrated] +2026-07-02 09:49:57,625 - INFO - Total Population: 2,462,702 firms +2026-07-02 09:50:02,457 - INFO - Wrote 2,941,232 rows to /private/tmp/claude-501/-Users-maxghenis/a15bbb6c-8c15-4740-b985-f511b978ea75/scratchpad/fmp-fix/data/synthetic/seed_check_99.csv (142.7 MB) diff --git a/src/firm_microsim/__main__.py b/src/firm_microsim/__main__.py index 9c955b5..f179fc3 100644 --- a/src/firm_microsim/__main__.py +++ b/src/firm_microsim/__main__.py @@ -50,6 +50,15 @@ def build_parser() -> argparse.ArgumentParser: default=DEFAULT_CONFIG.seed, help="Random seed for reproducibility (default: %(default)s).", ) + parser.add_argument( + "--fast", + action="store_true", + help="Fast-iteration build: stratified thinning (30%% of rows in the " + "£15k-£150k analysis window, 5%% elsewhere, per-stratum floors), with " + "thinned mass carried as base weights so all targets stay true totals. " + "~10x fewer rows and proportionally faster calibration; expect ~1-3%% " + "Monte Carlo drift in local statistics. NOT for release artifacts.", + ) parser.add_argument( "--output", type=str, @@ -66,13 +75,13 @@ def build_parser() -> argparse.ArgumentParser: return parser -def run_pipeline(seed: int) -> None: +def run_pipeline(seed: int, fast: bool = False) -> None: """Full data build: every vintage -> calibration report -> figures.""" from . import figures, report for vintage in VINTAGES: logging.info("=== Generating vintage %s ===", vintage) - generate(vintage=vintage, seed=seed, + generate(vintage=vintage, seed=seed, fast=fast, output=f"synthetic_firms_{vintage}.csv") report.main() # writes results/calibration_accuracy.txt figures.generate_all() # writes results/*.png @@ -96,9 +105,10 @@ def main() -> None: threshold=args.threshold, seed=args.seed, output=args.output, + fast=args.fast, ) else: - run_pipeline(seed=args.seed) + run_pipeline(seed=args.seed, fast=args.fast) if __name__ == "__main__": diff --git a/src/firm_microsim/analysis/dominated_region_mass.py b/src/firm_microsim/analysis/dominated_region_mass.py index a3f93e8..a04cb73 100644 --- a/src/firm_microsim/analysis/dominated_region_mass.py +++ b/src/firm_microsim/analysis/dominated_region_mass.py @@ -14,7 +14,7 @@ from ``notch/model.py``. We also report the analogous masses for the reform-shrunk bands at lower headline rates (15% -> width £15,000, 10% -> width £9,444), and sanity-check the counterfactual band mass against the paper's -excess-mass E and displaced share Pi recovered from ``bunching/model.py``. +excess-mass E and mass-conservation geometry recovered from ``bunching/model.py``. Run: firm-microsim-dominated-region Out: results/dominated_region_mass.txt @@ -52,6 +52,11 @@ ("10% band", 0.10), ] +# Reduced-rate band runs [T*, T*+BAND_WIDTH]; at the band top it reverts to the +# standard rate tau, creating a SECOND notch whose dominated width is +# a' = T1 * (tau - r) / (1 - tau), T1 = T* + BAND_WIDTH. +REDUCED_RATE_BAND_WIDTH = 20.0 # £k (band [85k, 105k] in the paper) + def mass_in_band(centres, density, lo, hi, bin_width=BIN_WIDTH): """Integrate a binned density over [lo, hi) -> weighted firm count. @@ -69,12 +74,11 @@ def main() -> None: # --- Build observed + mass-conserving counterfactual densities ---------- est = BunchingEstimator(VINTAGE) - res = est.estimate() # full reduced-form bunching solve (E, Pi, y_R, ...) + res = est.estimate() # full reduced-form bunching solve (E, y_R, ...) centres = res["centres"] f_obs = res["f_obs"] f_cf = res["f_cf"] E = res["E"] # excess mass below T* (weighted firms) - Pi = res["Pi"] # displaced share y_R = res["y_R"] # endogenous marginal buncher (£k) Delta_R = res["Delta_R"] @@ -106,6 +110,24 @@ def main() -> None: "net": cf - obs, # net missing (displaced) mass in band }) + # --- Secondary dominated region at the reduced-rate band top ------------ + # A banded reduced rate reverts to the standard rate tau at the band top + # T1, creating a SECOND notch with dominated width a' = T1*(tau-r)/(1-tau). + # The total dominated turnover under a reduced rate is primary + secondary. + band_top = t_star + REDUCED_RATE_BAND_WIDTH # £105k + sec_rows = [] + for label, tau_r in RATE_VARIANTS[1:]: # 15% and 10% only + a_sec = band_top * (TAU - tau_r) / (1.0 - TAU) + lo, hi = band_top, band_top + a_sec + obs = mass_in_band(centres, f_obs, lo, hi) + cf = mass_in_band(centres, f_cf, lo, hi) + prim = next(r for r in rows if r["tau"] == tau_r) + sec_rows.append({ + "label": label, "tau": tau_r, "a_sec": a_sec, + "lo": lo, "hi": hi, "obs": obs, "cf": cf, + "prim_obs": prim["obs"], "total_obs": prim["obs"] + obs, + }) + # Baseline (20%) is the paper's actual dominated region. base = rows[0] @@ -164,24 +186,38 @@ def main() -> None: W(f" 10% -> band width GBP {rows[2]['a']*1000:,.0f}: net displaced = {rows[2]['net']:,.0f} firms" f" (CF total {rows[2]['cf']:,.0f})") W("") - W("CONSISTENCY CHECK vs paper's reduced-form bunching:") + W(f"SECONDARY NOTCH at the reduced-rate band top (T1 = GBP {band_top*1000:,.0f}):") + W(" A banded reduced rate reverts to tau=20% at T1, adding a SECOND") + W(" dominated region a' = T1*(tau-r)/(1-tau). Total dominated turnover and") + W(" mass = primary [T*, T*+a] + secondary [T1, T1+a'].") + for s in sec_rows: + W(f" {s['label']:<9} secondary [{s['lo']:.0f}, {s['hi']:.3f}) " + f"width GBP {s['a_sec']*1000:,.0f} OBS = {s['obs']:,.0f}") + W(f" primary OBS {s['prim_obs']:,.0f} + secondary OBS {s['obs']:,.0f}" + f" = TOTAL {s['total_obs']:,.0f} (baseline {base['obs']:,.0f}," + f" {100*(s['total_obs']/base['obs']-1):+.1f}%)") + W("") + W("REDUCED-FORM BUNCHING on this population (context for the masses above):") W(f" excess mass below T* E = {E:,.0f} firms") W(f" missing mass above T* Delta_R = {Delta_R:,.0f} firms") - W(f" displaced share Pi = {Pi:.3f}") W(f" marginal buncher y_R = GBP {y_R*1000:,.0f}") W(f" NET displaced mass in 20% dominated band = {missing_in_band:,.0f} firms") - W(f" -> NET band mass / E = {missing_in_band/E:.2f}" if E else "") - W(f" -> NET band mass / Delta_R = {missing_in_band/Delta_R:.2f}" if Delta_R else "") W("") - W(" By mass conservation the excess mass E (~8.7k) that bunches just below") - W(" T* is the mass that, absent the notch, would have spread into the region") - W(" above T*. The NET displaced mass in the dominated band (~13.7k) is the") - W(" same order of magnitude as E and Delta_R (~9.2k) -- it slightly exceeds") - W(" them because the wide 21.25k band also captures part of the smooth") - W(" density deficit beyond the marginal buncher y_R = GBP 90,583, not just") - W(" the bunching window. CONSISTENT: no order-of-magnitude discrepancy.") - W(" (The TOTAL CF density in the band, 150k, is NOT the displaced mass and") - W(" should not be compared to E -- that would be a category error.)") + if E < 100: + W(" The estimator finds NO excess mass below the threshold on this") + W(" population (E ~ 0): the corrected net-liability calibration produces") + W(" no synthetic bunching, so the dominated-region masses above are") + W(" TARGET-BAND GEOMETRY (weighted firms located in each band), not") + W(" behavioural displacement. The band masses answer 'how many weighted") + W(" firms sit where the schedule makes location dominated', which is the") + W(" policy-relevant exposure count for each reform variant.") + else: + W(" By mass conservation the excess mass E that bunches just below T*") + W(" is the mass that, absent the notch, would have spread into the") + W(" region above T*. Compare magnitudes of E, Delta_R, and the NET band") + W(" mass; the wide band also captures smooth-density deficit beyond y_R.") + W(" (The TOTAL CF density in the band is NOT the displaced mass and") + W(" should not be compared to E -- that would be a category error.)") W("") W(f" total observed weighted mass on [{est.firms['annual_turnover_k'].min():.0f}," f"{est.firms['annual_turnover_k'].max():.0f}] est. range = {total_obs_mass:,.0f}") diff --git a/src/firm_microsim/analysis/placebo_bunching.py b/src/firm_microsim/analysis/placebo_bunching.py index 71c605b..11b8fde 100644 --- a/src/firm_microsim/analysis/placebo_bunching.py +++ b/src/firm_microsim/analysis/placebo_bunching.py @@ -71,7 +71,7 @@ def estimate(turnover: np.ndarray, weight: np.ndarray, label: str) -> dict: r = _run_estimator(turnover, weight, T_STAR) print( f" {label:<28s} b={r['b']:+.4f} E={r['E']:>10,.0f} " - f"b_llat={r['b_llat']:.3f} y_R={r['y_R']:.2f} sigma={r['sigma']:.3f}" + f"b_llat={r['b_llat']:.3f} y_R={r['y_R']:.2f}" ) return r @@ -160,6 +160,9 @@ def patched_load(config): data.hmrc_bands = dict(data.hmrc_bands) data.hmrc_bands["£1_to_Threshold"] = dens * T_STAR data.hmrc_bands["£Threshold_to_£150k"] = dens * (150.0 - T_STAR) + # Remove the OBR near-threshold shape targets as well: the placebo + # world has NO fine structure in its targets at all. + data.near_threshold_bins = None return data gen_mod.load_data = patched_load diff --git a/src/firm_microsim/bunching/__init__.py b/src/firm_microsim/bunching/__init__.py index 0fb4813..6ee9bf8 100644 --- a/src/firm_microsim/bunching/__init__.py +++ b/src/firm_microsim/bunching/__init__.py @@ -11,7 +11,6 @@ BunchingEstimator, DEFAULT_DEGREE, DEFAULT_WINDOW, - TAU_E, TAU_MAX, ) @@ -20,5 +19,4 @@ "TAU_MAX", "DEFAULT_DEGREE", "DEFAULT_WINDOW", - "TAU_E", ] diff --git a/src/firm_microsim/bunching/__main__.py b/src/firm_microsim/bunching/__main__.py index 168e5ce..fc113fc 100644 --- a/src/firm_microsim/bunching/__main__.py +++ b/src/firm_microsim/bunching/__main__.py @@ -41,7 +41,7 @@ def main() -> None: if args.no_bootstrap: res = est.estimate() print(f" b = {res['b']:.4f} excess mass E = {res['E']:,.0f} " - f"sigma = {res['sigma']:.3f}") + f"y_R = {res['y_R']:.2f}") print(f" b (LLAT normalisation) = {res['b_llat']:.3f} " f"(cf. LLAT 2021: 1.361)") else: diff --git a/src/firm_microsim/bunching/model.py b/src/firm_microsim/bunching/model.py index 8e128bc..1cb5e4d 100644 --- a/src/firm_microsim/bunching/model.py +++ b/src/firm_microsim/bunching/model.py @@ -18,8 +18,11 @@ above), rather than fixed at an arbitrary window. From these objects it computes the bunching ratio ``b``, excess mass ``E``, the -CES/logit substitution elasticity ``sigma``, the local (notch-width) turnover -elasticity, and bootstrap standard errors. +mass-conservation geometry (``Delta_R``, ``y_R``), and bootstrap standard +errors. It deliberately reports NO elasticities: with the notch geometry these +data produce, no elasticity is identified from the density alone (see the +paper's placebo), and earlier wedge-normalised "elasticity" outputs inherited +an ad hoc ``tau/2`` normalisation from a deleted smoothed-schedule model. Normalisation note (literature comparability) --------------------------------------------- @@ -54,7 +57,6 @@ DEFAULT_DEGREE = 7 # counterfactual polynomial degree DEFAULT_WINDOW = 15.0 # excluded window half-width either side of t* (£1,000) -TAU_E = 0.05 # effective wedge for the CES substitution elasticity N_BOOT = 200 # bootstrap replications RNG_SEED = 20240617 @@ -254,72 +256,6 @@ def excess_bunching_llat( return excess_mass / avg_cf_height -# --------------------------------------------------------------------------- -# Elasticities -# --------------------------------------------------------------------------- - -def substitution_elasticity( - q_N_obs: float, - q_R_obs: float, - q_N_cf: float, - q_R_cf: float, - tau_e: float = TAU_E, -) -> float: - """CES/logit share equation: ``sigma = ln(RR) / ln(1 + tau_e)``. - - ``RR = (q_R_cf / q_N_cf) / (q_R_obs / q_N_obs)`` is the relative-risk of the - above/below share between counterfactual and observed worlds. - """ - if min(q_N_obs, q_R_obs, q_N_cf, q_R_cf) <= 0: - return np.nan - rr = (q_R_cf / q_N_cf) / (q_R_obs / q_N_obs) - if rr <= 0: - return np.nan - return float(np.log(rr) / np.log(1 + tau_e)) - - -def local_turnover_elasticity( - centres: np.ndarray, - f_obs: np.ndarray, - f_cf: np.ndarray, - t_star: float, - window_lo: float, - y_R: float, -) -> tuple[float, float]: - """Local (notch-width, Method B) turnover elasticity. - - Following the notch logic of Kleven--Waseem, the excess turnover span of the - marginal buncher identifies an elasticity relative to the effective wedge: - - eps = (dy / t_star) / tau_eff, tau_eff = TAU_MAX / 2 - - (``tau(t_star) = tau_max / 2`` holds at the threshold for any sigmoid - steepness, so ``tau_eff`` is steepness-invariant.) - - Returns ``(eps_median, eps_marginal)``: the bunching-mass-weighted median of - bin-level implied elasticities across the manipulation window, and the - headline marginal-buncher elasticity built from ``dyR = y_R - t_star``. - """ - tau_eff = TAU_MAX / 2.0 - mask = (centres >= t_star - window_lo) & (centres <= y_R) - excess = np.maximum(f_obs[mask] - f_cf[mask], 0.0) - dy = np.abs(centres[mask] - t_star) - eps_bins = (dy / t_star) / tau_eff - - if excess.sum() <= 0: - return np.nan, np.nan - - order = np.argsort(eps_bins) - e_sorted = eps_bins[order] - w_sorted = excess[order] - cw = np.cumsum(w_sorted) / np.sum(w_sorted) - eps_median = float(np.interp(0.5, cw, e_sorted)) - - dyR = max(y_R - t_star, 0.0) - eps_marginal = float((dyR / t_star) / tau_eff) - return eps_median, eps_marginal - - # --------------------------------------------------------------------------- # Single-pass estimator # --------------------------------------------------------------------------- @@ -331,9 +267,12 @@ def _run_estimator( degree: int = DEFAULT_DEGREE, window_lo: float = DEFAULT_WINDOW, window_hi: float = DEFAULT_WINDOW, - tau_e: float = TAU_E, ) -> dict: - """Run the full mass-conserving estimator once and return all statistics.""" + """Run the full mass-conserving estimator once and return all statistics. + + Reports density geometry only (``b``, ``b_llat``, ``E``, ``Delta_R``, + ``y_R``, ``dyR``); no elasticity is identified from these data. + """ centres, f_obs = bin_density(turnover, weight) f_cf = fit_counterfactual(centres, f_obs, t_star, degree, window_lo, window_hi) E, Delta_R, y_R, dyR = locate_marginal_buncher( @@ -342,12 +281,7 @@ def _run_estimator( b, q_N_obs, q_R_obs, q_N_cf, q_R_cf = bunching_stats( centres, f_obs, f_cf, t_star, window_lo, y_R ) - sigma = substitution_elasticity(q_N_obs, q_R_obs, q_N_cf, q_R_cf, tau_e) - eps_median, eps_marginal = local_turnover_elasticity( - centres, f_obs, f_cf, t_star, window_lo, y_R - ) b_llat = excess_bunching_llat(centres, f_obs, f_cf, t_star, window_lo, y_R) - Pi = 1 - (1 + tau_e) ** (-sigma) if np.isfinite(sigma) else np.nan return { "b": b, "b_llat": b_llat, @@ -355,10 +289,6 @@ def _run_estimator( "Delta_R": Delta_R, "y_R": y_R, "dyR": dyR, - "sigma": sigma, - "Pi": Pi, - "eps_local_median": eps_median, - "eps_marginal": eps_marginal, "centres": centres, "f_obs": f_obs, "f_cf": f_cf, @@ -411,13 +341,11 @@ def estimate( degree: int = DEFAULT_DEGREE, window_lo: float = DEFAULT_WINDOW, window_hi: float = DEFAULT_WINDOW, - tau_e: float = TAU_E, ) -> dict: """Point estimates over the full weighted sample. Returns a dict with ``b``, ``b_llat``, ``E``, ``Delta_R``, ``y_R``, - ``dyR``, ``sigma``, ``Pi``, ``eps_local_median``, ``eps_marginal``, and - the binned ``centres``, ``f_obs``, ``f_cf`` arrays. + ``dyR``, and the binned ``centres``, ``f_obs``, ``f_cf`` arrays. """ return _run_estimator( self.firms["annual_turnover_k"].to_numpy(), @@ -426,7 +354,6 @@ def estimate( degree=degree, window_lo=window_lo, window_hi=window_hi, - tau_e=tau_e, ) def bootstrap( @@ -446,14 +373,17 @@ def bootstrap( w = self.firms["weight"].to_numpy() n = len(turnover) p = w / w.sum() + # Each replicate carries uniform weights summing to the ORIGINAL + # weighted mass W (draws are already probability-proportional-to-w); + # unit weights would rescale mass statistics such as E by n/W. + rep_w = np.full(n, w.sum() / n) - keys = ["b", "b_llat", "E", "sigma", "Pi", - "eps_local_median", "eps_marginal", "dyR"] + keys = ["b", "b_llat", "E", "dyR"] rows = [] for _ in range(n_boot): idx = rng.choice(n, size=n, replace=True, p=p) res = _run_estimator( - turnover[idx], np.ones(n), self.t_star, **kw + turnover[idx], rep_w, self.t_star, **kw ) rows.append({k: res[k] for k in keys}) return pd.DataFrame(rows) @@ -482,13 +412,11 @@ def sensitivity( self, degrees: tuple[int, ...] = (5, 6, 7, 8), windows: tuple[float, ...] = (10.0, 15.0, 20.0, 25.0), - tau_es: tuple[float, ...] = (0.025, 0.05, 0.075, 0.10), ) -> dict[str, pd.DataFrame]: - """Point-estimate sensitivity grids. + """Point-estimate sensitivity grid. - Returns ``{"degree_window": df, "tau_e": df}``: the first sweeps the - counterfactual polynomial degree against the exclusion window - (symmetric), the second sweeps the effective wedge ``tau_e``. + Returns ``{"degree_window": df}``: the counterfactual polynomial degree + swept against the (symmetric) exclusion window. """ turnover = self.firms["annual_turnover_k"].to_numpy() w = self.firms["weight"].to_numpy() @@ -507,17 +435,7 @@ def sensitivity( "b": r["b"], "b_llat": r["b_llat"], "E": r["E"], - "sigma": r["sigma"], - "eps_local_median": r["eps_local_median"], } ) - te_rows = [] - for te in tau_es: - r = _run_estimator(turnover, w, self.t_star, tau_e=te) - te_rows.append({"tau_e": te, "sigma": r["sigma"], "Pi": r["Pi"]}) - - return { - "degree_window": pd.DataFrame(dw_rows), - "tau_e": pd.DataFrame(te_rows), - } + return {"degree_window": pd.DataFrame(dw_rows)} diff --git a/src/firm_microsim/calibration.py b/src/firm_microsim/calibration.py index fee8a49..0399c06 100644 --- a/src/firm_microsim/calibration.py +++ b/src/firm_microsim/calibration.py @@ -25,14 +25,15 @@ import torch from torch import Tensor -from .config import Config +from .config import Config, STANDARD_VAT_RATE logger = logging.getLogger(__name__) # ONS employment-size bands (used for both targets and validation). EMPLOYMENT_BANDS: List[str] = ["0-4", "5-9", "10-19", "20-49", "50-99", "100-249", "250+"] -# VAT-liability turnover bands above the Negative_or_Zero band. +# VAT-liability turnover bands above the Negative_or_Zero band (validation +# reports all of these). VAT_LIABILITY_BANDS: List[str] = [ "£1_to_Threshold", "£Threshold_to_£150k", @@ -43,6 +44,16 @@ "Greater_than_£10m", ] +# Bands actually CALIBRATED for liability. The £1_to_Threshold band is +# excluded: its HMRC total is remitted by below-threshold VOLUNTARY +# registrants, whose input-reclaim-driven net remittances (~£2,150 average) +# the model's standard-rate-on-value-added liability does not represent. +# Imposing that total on the whole below-threshold population forces the +# optimiser to crush weights in the £50k-£85k region (the visible seam at the +# OBR window edge). It is reported as an informational diagnostic instead, +# like VAT liability by sector. +VAT_LIABILITY_BANDS_CALIBRATED: List[str] = VAT_LIABILITY_BANDS[1:] + def map_to_hmrc_bands(turnover_values: Tensor, threshold: float) -> Tensor: """Map turnover values (£k) to HMRC band indices 0-7. @@ -126,19 +137,21 @@ class TargetSpec: original script. """ - def __init__(self, n_sectors: int, n_vat_sectors: int) -> None: + def __init__(self, n_sectors: int, n_vat_sectors: int, n_near: int = 0) -> None: self.n_turnover = 7 self.n_sectors = n_sectors self.n_employment = len(EMPLOYMENT_BANDS) self.n_vat_sectors = n_vat_sectors - self.n_vat_bands = len(VAT_LIABILITY_BANDS) + self.n_vat_bands = len(VAT_LIABILITY_BANDS_CALIBRATED) + self.n_near = n_near self.turnover_start = 0 self.sector_start = self.n_turnover self.employment_start = self.sector_start + self.n_sectors self.vat_sector_start = self.employment_start + self.n_employment self.vat_band_start = self.vat_sector_start + self.n_vat_sectors - self.n_targets = self.vat_band_start + self.n_vat_bands + self.near_start = self.vat_band_start + self.n_vat_bands + self.n_targets = self.near_start + self.n_near def build_target_matrix( @@ -152,6 +165,8 @@ def build_target_matrix( ons_employment_df: pd.DataFrame, vat_liability_sector_df: pd.DataFrame, vat_liability_bands: dict, + near_threshold_bins: pd.DataFrame | None = None, + base_weights: Tensor | None = None, ) -> Tuple[Tensor, Tensor, TargetSpec]: """Construct the calibration target matrix and target vector. @@ -173,6 +188,8 @@ def build_target_matrix( device = config.device threshold = config.vat_threshold n_firms = len(turnover_values) + if base_weights is None: + base_weights = torch.ones_like(turnover_values) sector_rows = hmrc_sector_df[hmrc_sector_df["Trade_Sector"] != "Total"].copy() if config.calibrate_vat_liability_sector: @@ -184,7 +201,8 @@ def build_target_matrix( # (Still reported as an informational diagnostic by validate.py.) vat_liability_sector_rows = vat_liability_sector_df.iloc[0:0].copy() - spec = TargetSpec(len(sector_rows), len(vat_liability_sector_rows)) + n_near = 0 if near_threshold_bins is None else len(near_threshold_bins) + spec = TargetSpec(len(sector_rows), len(vat_liability_sector_rows), n_near) target_matrix = torch.zeros(spec.n_targets, n_firms, device=device) band_indices = map_to_hmrc_bands(turnover_values, threshold) @@ -203,8 +221,10 @@ def build_target_matrix( row = spec.employment_start + band_idx target_matrix[row, employment_band_indices == band_idx] = 1.0 - # VAT liability (£k) per firm = turnover - input. - vat_liability_values = turnover_values - input_values + # Net VAT liability (£k) per firm = standard rate * value added + # = STANDARD_VAT_RATE * (turnover - input). This matches the HMRC + # net-VAT-liability targets, which are net of input reclaim. + vat_liability_values = STANDARD_VAT_RATE * (turnover_values - input_values) # VAT-liability-by-sector targets (weight firms by their liability). for offset, (_, vat_row) in enumerate(vat_liability_sector_rows.iterrows()): @@ -214,15 +234,56 @@ def build_target_matrix( target_matrix[row, mask] = vat_liability_values[mask] # VAT-liability-by-band targets. - for offset, band_name in enumerate(VAT_LIABILITY_BANDS): + for offset, band_name in enumerate(VAT_LIABILITY_BANDS_CALIBRATED): row = spec.vat_band_start + offset mask = _band_membership_mask(turnover_values, band_name, threshold) target_matrix[row, mask] = vat_liability_values[mask] + # Near-threshold £1k-bin membership rows (bins are (lo, lo+1], matching + # the coarse-band edge conventions). Target values are assembled below. + near_targets: list[float] = [] + if n_near: + # SHAPE-ONLY targets on BOTH sides of the threshold: each side takes + # the OBR profile's within-side shape, scaled to the synthetic frame's + # own base-weighted mass on that side. The OBR chart counts HMRC + # traders (a different unit and, below the threshold, a different + # universe than the ONS business frame), so its LEVELS are not + # imported on either side; mixing direct counts on one side with + # frame-scaled shape on the other inverted the cross-threshold + # ordering (more mass just above than just below - economically + # backwards for a liability notch). With side-consistent scaling the + # cross-threshold ratio is the frame's own, and the OBR data supply + # only the within-side profile (the rise into the threshold and the + # decline beyond it). + below = near_threshold_bins[near_threshold_bins["bin_lo_k"] < threshold] + above = near_threshold_bins[near_threshold_bins["bin_lo_k"] >= threshold] + below_lo = float(below["bin_lo_k"].min()) + above_hi = float(above["bin_lo_k"].max()) + 1.0 + below_mask = (turnover_values > below_lo) & (turnover_values <= threshold) + above_mask = (turnover_values > threshold) & (turnover_values <= above_hi) + below_rows = float(base_weights[below_mask].sum().item()) + above_rows = float(base_weights[above_mask].sum().item()) + below_total = float(below["count"].sum()) + above_total = float(above["count"].sum()) + for offset, (_, bin_row) in enumerate(near_threshold_bins.iterrows()): + lo = float(bin_row["bin_lo_k"]) + row = spec.near_start + offset + mask = (turnover_values > lo) & (turnover_values <= lo + 1.0) + target_matrix[row, mask] = 1.0 + if lo < threshold: + near_targets.append( + float(bin_row["count"]) / below_total * below_rows + ) + else: + near_targets.append( + float(bin_row["count"]) / above_total * above_rows + ) + # ---- Target values -------------------------------------------------- - # £1_to_Threshold keeps the ONS structure (current synthetic count); - # all higher bands match HMRC. - ons_threshold_count = float((band_indices == 1).sum().item()) + # £1_to_Threshold keeps the ONS structure (the base-weighted synthetic + # count, which equals the row count on unsampled builds); all higher + # bands match HMRC. + ons_threshold_count = float(base_weights[band_indices == 1].sum().item()) turnover_targets = [ ons_threshold_count, hmrc_bands["£Threshold_to_£150k"], @@ -251,7 +312,7 @@ def build_target_matrix( float(r.iloc[-1]) * 1000.0 for _, r in vat_liability_sector_rows.iterrows() ] vat_liability_band_targets = [ - float(vat_liability_bands[band]) * 1000.0 for band in VAT_LIABILITY_BANDS + float(vat_liability_bands[band]) * 1000.0 for band in VAT_LIABILITY_BANDS_CALIBRATED ] target_values_list = ( @@ -260,17 +321,19 @@ def build_target_matrix( + employment_targets + vat_liability_sector_targets + vat_liability_band_targets + + near_targets ) target_values = torch.tensor(target_values_list, dtype=torch.float32, device=device) logger.info("Target matrix shape: %s", tuple(target_matrix.shape)) logger.info( "Targets: 7 turnover + %d sector + %d employment + %d VAT-liability sector " - "+ %d VAT-liability band = %d", + "+ %d VAT-liability band + %d near-threshold = %d", spec.n_sectors, spec.n_employment, spec.n_vat_sectors, spec.n_vat_bands, + spec.n_near, spec.n_targets, ) return target_matrix, target_values, spec @@ -290,6 +353,9 @@ def _importance_weights(spec: TargetSpec, config: Config, device: str) -> Tensor w[spec.vat_band_start : spec.vat_band_start + spec.n_vat_bands] = ( config.vat_liability_band_importance ) + w[spec.near_start : spec.near_start + spec.n_near] = ( + config.near_threshold_importance + ) return w @@ -298,6 +364,7 @@ def optimize_weights( target_matrix: Tensor, target_values: Tensor, spec: TargetSpec, + base_weights: Tensor | None = None, ) -> Tensor: """Optimize per-firm weights to match all targets simultaneously. @@ -319,7 +386,14 @@ def optimize_weights( device = config.device _, n_firms = target_matrix.shape - log_weights = torch.zeros(n_firms, device=device, requires_grad=True) + # Under stratified sampling, weights start at (and the L1 penalty pulls + # toward) the per-stratum base weights that carry the thinned mass, so a + # sampled build is the same optimisation problem around a rescaled prior. + if base_weights is None: + base_log = torch.zeros(n_firms, device=device) + else: + base_log = torch.log(base_weights.to(device)) + log_weights = base_log.clone().requires_grad_(True) optimizer = torch.optim.Adam([log_weights], lr=config.learning_rate) importance = _importance_weights(spec, config, device) @@ -346,7 +420,9 @@ def optimize_weights( weighted_loss = sre_loss * importance total_loss = torch.mean(weighted_loss) # Keep the regularizer on the same normalized scale as the target loss. - total_loss = total_loss + config.l1_reg_coef * torch.mean(torch.abs(log_weights)) + total_loss = total_loss + config.l1_reg_coef * torch.mean( + torch.abs(log_weights - base_log) + ) total_loss.backward() torch.nn.utils.clip_grad_norm_([log_weights], max_norm=config.grad_clip_norm) diff --git a/src/firm_microsim/config.py b/src/firm_microsim/config.py index dd34b59..39f383c 100644 --- a/src/firm_microsim/config.py +++ b/src/firm_microsim/config.py @@ -68,6 +68,12 @@ def _default_repo_root() -> Path: } DEFAULT_VINTAGE: str = os.environ.get("DATA_VINTAGE", "2023-24") +# Standard UK VAT rate. A registered firm's net VAT liability is this rate +# applied to its value added (turnover less inputs): +# v_i = STANDARD_VAT_RATE * (turnover_i - inputs_i). +# This is the single place the rate is set. +STANDARD_VAT_RATE: float = 0.20 + # Processed input file names (placed in PROCESSED_DATA_DIR by an upstream # ETL process). These map onto the original ONS + HMRC official tables. INPUT_FILES: Dict[str, str] = { @@ -135,6 +141,9 @@ class Config: employment_importance: float = 1.0 vat_liability_sector_importance: float = 1.0 vat_liability_band_importance: float = 2.0 + # Near-threshold OBR £1k-band targets (EFO Mar-2023 Chart C data; + # applied only at the £85k threshold — see data_loader). + near_threshold_importance: float = 5.0 # Whether to include VAT-liability-by-sector as a calibration target. # Disabled by default: the model does not yet calibrate the input/output @@ -143,6 +152,22 @@ class Config: # informational diagnostic (see validate.py). Restore once input/output # calibration exists — tracked in the GitHub issues. calibrate_vat_liability_sector: bool = False + # Calibrate the near-threshold £1k-band shape to the OBR Chart C data + # (2023-24 / £85k vintage only; the chart covers the £85k era). + calibrate_near_threshold: bool = True + + # --- Fast-iteration stratified sampling ------------------------------- + # 1.0 / 1.0 = full synthetic census (release builds). Lower fractions + # thin the draws, carrying the removed mass as per-stratum base weights + # (strata: sector x HMRC band x inside/outside the analysis window), so + # every calibration target remains a TRUE total at any fraction. The + # analysis window keeps a higher fraction for near-threshold density + # resolution; a per-stratum floor protects sparse sector x band cells. + sample_tail_fraction: float = 1.0 + sample_window_fraction: float = 1.0 + sample_window_lo_k: float = 15.0 + sample_window_hi_k: float = 150.0 + sample_cell_floor: int = 40 # --- Paths (overridable) --------------------------------------------- data_dir: Path = DATA_DIR diff --git a/src/firm_microsim/data_loader.py b/src/firm_microsim/data_loader.py index 7c32459..974b888 100644 --- a/src/firm_microsim/data_loader.py +++ b/src/firm_microsim/data_loader.py @@ -8,17 +8,20 @@ employment-size band, per SIC sector. * HMRC VAT Annual Statistics — VAT-registered firm counts and net VAT liability, both by turnover band and by trade sector. + * OBR Economic and Fiscal Outlook (March 2023), Chart C — HMRC counts of + businesses by £1,000 turnover band around the £85k threshold, used as + near-threshold shape targets for the 2023-24 vintage. """ from __future__ import annotations import logging from dataclasses import dataclass -from typing import Dict +from typing import Dict, Optional import pandas as pd -from .config import Config +from .config import PROCESSED_DATA_DIR, Config logger = logging.getLogger(__name__) @@ -37,6 +40,11 @@ # VAT-liability bands exclude the Negative_or_Zero column for calibration. VAT_LIABILITY_BAND_COLUMNS = HMRC_BAND_COLUMNS[1:] +# OBR March-2023 EFO Chart C underlying data: businesses by £1,000 turnover +# band (£65k-£90k), outturn years plus a 2025-26 projection, in thousands. +# Shared across vintages, so it lives in data/processed/ (not a vintage dir). +OBR_NEAR_THRESHOLD_FILE = "obr_vat_bunching.csv" + @dataclass class LoadedData: @@ -51,6 +59,7 @@ class LoadedData: ons_total: int hmrc_bands: Dict[str, float] vat_liability_bands: Dict[str, float] + near_threshold_bins: Optional[pd.DataFrame] = None def _extract_ons_total(ons_turnover: pd.DataFrame) -> int: @@ -79,6 +88,52 @@ def _latest_vat_liability_bands( return {col: float(latest[col]) for col in HMRC_BAND_COLUMNS} +def _near_threshold_targets(config: Config) -> Optional[pd.DataFrame]: + """OBR Chart C £1,000-band counts, interpolated to the 2023-24 data year. + + Source: OBR Economic and Fiscal Outlook, March 2023, Chart C ("Bunching in + the VAT turnover distribution at the registration threshold") — HMRC counts + of businesses by £1,000 turnover band over £65,000-£90,000, with outturn + years to 2019-20 and a 2025-26 projection under the then-assumed frozen + £85,000 threshold. The 2023-24 profile is a linear interpolation + four-sixths of the way from the 2019-20 outturn to the 2025-26 projection, + matching the OBR's own expected deepening of bunching under the freeze. + Values are thousands of businesses, converted to firm counts. + + Applied only at the £85,000 threshold (the chart's threshold era): the + 2024-25 (£90k) vintage keeps coarse bands only, since no published fine + bands exist for the post-rise threshold. Returns a frame with columns + ``bin_lo_k`` (bin lower edge, £k; bins are (lo, lo+1]) and ``count``. + """ + if not config.calibrate_near_threshold or config.vat_threshold != 85: + return None + path = PROCESSED_DATA_DIR / OBR_NEAR_THRESHOLD_FILE + if not path.exists(): + logger.warning("Near-threshold targets requested but %s missing", path) + return None + df = pd.read_csv(path) + # Keep bins strictly below £90k: the chart's stated range is £65k-£90k + # and its right-edge bin shows a boundary upturn we do not trust. + df = df[df["turnover"] < 90_000].reset_index(drop=True) + w = 4.0 / 6.0 # 2023-24 sits four years along the 2019-20 -> 2025-26 span + interp = df["2019-20"] + w * (df["2025-26"] - df["2019-20"]) + out = pd.DataFrame( + { + "bin_lo_k": df["turnover"].astype(float) / 1000.0, + "count": interp.astype(float) * 1000.0, + } + ) + logger.info( + "Near-threshold targets: %d OBR £1k bins over [%.0fk, %.0fk], " + "interpolated 2023-24 profile, total %s firms", + len(out), + out["bin_lo_k"].min(), + out["bin_lo_k"].max() + 1, + f"{out['count'].sum():,.0f}", + ) + return out + + def load_data(config: Config) -> LoadedData: """Load all processed input tables and derive calibration targets. @@ -88,8 +143,9 @@ def load_data(config: Config) -> LoadedData: Returns: A :class:`LoadedData` bundle with raw frames, the ONS total firm - count, the latest HMRC VAT-registration band targets, and the latest - VAT-liability-by-band targets. + count, the latest HMRC VAT-registration band targets, the latest + VAT-liability-by-band targets, and (for the £85k vintage) the OBR + near-threshold £1k-band targets. Raises: FileNotFoundError: If any expected input CSV is missing. @@ -114,6 +170,7 @@ def load_data(config: Config) -> LoadedData: ons_total = _extract_ons_total(ons_turnover) hmrc_bands = _latest_hmrc_band_targets(hmrc_population_band) vat_liability_bands = _latest_vat_liability_bands(hmrc_liability_band) + near_threshold_bins = _near_threshold_targets(config) logger.info("ONS total firms: %s", f"{ons_total:,}") logger.info( @@ -131,4 +188,5 @@ def load_data(config: Config) -> LoadedData: ons_total=ons_total, hmrc_bands=hmrc_bands, vat_liability_bands=vat_liability_bands, + near_threshold_bins=near_threshold_bins, ) diff --git a/src/firm_microsim/dynamic/__main__.py b/src/firm_microsim/dynamic/__main__.py index 1e4492d..0d97328 100644 --- a/src/firm_microsim/dynamic/__main__.py +++ b/src/firm_microsim/dynamic/__main__.py @@ -108,7 +108,9 @@ def main(argv=None): for rname, (sched, label) in reforms.items(): rs = reform_revenue(df, sched, E_HEADLINE, behavioural=False) beh = {} - if args.behavioural: + # The taper (regions=None) is excluded from the behavioural layer: its + # rate varies continuously, so the region-confined solve is undefined. + if args.behavioural and getattr(sched, "regions", None) is not None: for e in elasticities: beh[e] = reform_revenue(df, sched, e, behavioural=True) diff --git a/src/firm_microsim/dynamic/model.py b/src/firm_microsim/dynamic/model.py index f09ae67..8498f16 100644 --- a/src/firm_microsim/dynamic/model.py +++ b/src/firm_microsim/dynamic/model.py @@ -36,30 +36,47 @@ * General smooth schedule FOC: ``(1 - tau(y)) - y * tau'(y) = (y/n)**(1/e)``. -ABILITY RECOVERY (accounting anchor, NOT structural identification) +SCOPE: INTENSIVE MARGIN ONLY, REGION-CONFINED +--------------------------------------------- +The behavioural layer prices the INTENSIVE margin only: each firm re-optimises +turnover *within the schedule region that contains its observed turnover* +(regions are the maximal intervals on which the effective-rate fraction ``f`` +is constant). Relocation across a notch — bunching below a threshold from +above, or de-registering past a band edge — is the EXTENSIVE margin, which is +the separate analytic object (dominated region + marginal buncher) and is +deliberately out of scope here. Confining the response to the firm's own +region makes the solve a closed form, makes the ``e -> 0`` limit collapse onto +the static costing *exactly*, and removes any dependence on solver iteration +details at schedule discontinuities (a damped fixed point has no fixed point +for abilities that straddle a notch, so its iterates oscillate and the +"solution" is an artifact of the iteration count — the previous implementation +had exactly this defect). + +RESPONSE (formulation A: value-added tax, deductible share cancels) ------------------------------------------------------------------- -Given ``e`` and a firm's observed turnover ``y_obs`` under the BASELINE £85,000 -notch, using the firm's observed net VAT rate ``tau0 = liab / y_obs`` once -registered:: +Under formulation A the firm maximises +``pi = (1 - delta)(1 - tau f(y)) y - C(y; n, e)``, so the interior optimum is +``y* = n [(1-delta)(1-tau f)]**e``. The reform response RATIO from the +baseline (fraction ``f0``) to the reform (fraction ``f1``) is therefore:: - y_obs < T* : unregistered => n = y_obs. - y_obs >= T* : registered => n = y_obs / (1 - tau0)**e. + y_star / y_obs = [(1 - tau*f1) / (1 - tau*f0)] ** e, -This rationalises the observed allocation given ``e``; it is an accounting -anchor, not structural identification (``e`` is not identified from the -synthetic data — see the placebo). +with ``tau`` the STATUTORY rate: the deductible share ``delta`` cancels, so +the response needs neither ``delta`` nor the firm's net rate — ``e`` is the +sole knob (``d ln y / d ln(1 - tau f) = e`` exactly). The ratio is clipped to +the firm's schedule region. REVENUE CONVENTION ------------------ -The stored net VAT remittance ``liab`` is NOT ``0.20 * turnover`` — it is -output-minus-input VAT (a firm-specific net rate ``liab/y_obs`` averaging ~3% -of turnover). Under a reform schedule that scales the standard rate by a -fraction ``f(y) in [0,1]`` over the band, a registered firm's reform remittance -is ``liab * (y_star / y_obs) * f(y_star)``: the firm's net VAT-to-turnover ratio -is held fixed, turnover is re-optimised to ``y_star`` (iso-elastic response), -and the schedule fraction is applied. This is exactly ``tau_R(y_star)*y_star`` -with ``tau_R(y) = (liab/y_obs) * f(y)`` and it reproduces the trusted STATIC -reform costs in the ``e -> 0`` (no-response) limit. +The stored net VAT remittance ``liab`` is NOT ``0.20 * turnover`` — it is the +standard rate applied to value added, ``0.20 * (turnover - input)`` (a +firm-specific net rate ``liab/y_obs`` of roughly 8% of turnover, i.e. +``0.20 * value-added-share``). Under a reform schedule with effective-rate +fraction ``f(y) in [0,1]``, a registered firm's reform remittance is +``liab * (y_star / y_obs) * f(y_star)`` — value added stays a fixed share of +turnover, turnover is re-optimised, and the schedule fraction is applied. In +the ``e -> 0`` (no-response) limit ``y_star = y_obs`` and this reproduces the +STATIC reform costs exactly. CROSS-CHECKS (see :func:`crosscheck`) ------------------------------------- @@ -67,9 +84,15 @@ 2. Marginal buncher ``n_H(e)`` = 112,795 / 127,382 / 143,527 at e = 0.05 / 0.17 / 0.32 (our iso-elastic indifference solve matches ``notch.model`` to within ±£200). -3. Elasticity check: ``d ln(y_star)/d ln(1-tau) = e`` numerically. -4. ``e -> 0`` limit: behavioural reform costs converge to the static costs - computed on the in-repository generated population. +3. Elasticity check: ``d ln(y_star)/d ln(1-tau f) = e`` numerically. +4. ``e -> 0`` limit: behavioural reform costs equal the static costs to + first order in ``e`` (checked at e = 1e-6 to within £0.1m). +5. Baseline reproduction: solving the BASELINE schedule returns every firm's + observed turnover exactly (the accounting anchor is internally consistent). +6. Raise-to-£100k invariance: the behavioural cost of a pure threshold raise + equals its static cost at EVERY ``e`` — released firms leave the VAT base + (their expansion is untaxed) and no other firm's effective rate changes, + so a level move has no intensive-margin revenue offset in this model. """ from __future__ import annotations @@ -89,7 +112,10 @@ T_STAR = 85_000.0 # registration threshold (£) TAPER_TOP = 105_000.0 # taper / reduced-rate band upper edge (£) -# Headline elasticity bracket (median 0.17, bracketed by 0.05 and 0.32). +# ASSUMED sweep values for the e-sensitivity analysis. None is identified from +# the synthetic data. The low end (0.05) is the external Kleven-Waseem (2013) +# anchor; 0.17 and 0.32 are assumption choices spanning the range used in the +# threshold literature, reported to show how the costings move with e. ELASTICITIES = (0.05, 0.17, 0.32) E_HEADLINE = 0.17 @@ -145,6 +171,12 @@ def schedule_notch(y, T=T_STAR): return (y >= T).astype(float) +# Piecewise-flat region metadata: list of (lo, hi, fraction) half-open [lo, hi) +# intervals covering [0, inf). ``None`` marks a schedule that is NOT piecewise +# flat (the taper), for which the region-confined intensive solve is undefined. +schedule_notch.regions = [(0.0, T_STAR, 0.0), (T_STAR, np.inf, 1.0)] + + def make_schedule_raise(T_new=100_000.0): """Raise the threshold to ``T_new``: the notch simply moves to ``T_new``.""" @@ -152,6 +184,7 @@ def sched(y): y = np.asarray(y, dtype=float) return (y >= T_new).astype(float) + sched.regions = [(0.0, float(T_new), 0.0), (float(T_new), np.inf, 1.0)] return sched @@ -161,6 +194,13 @@ def schedule_taper(y, T=T_STAR, top=TAPER_TOP): return np.clip((y - T) / (top - T), 0.0, 1.0) +# The taper's fraction varies continuously with y, so it has no flat regions: +# its intensive response cannot be priced by the region-confined solve (and its +# marginal-rate channel is not represented by the flat-rate FOC), so the +# behavioural layer excludes it. +schedule_taper.regions = None + + def make_schedule_reduced_rate(tau_low, T=T_STAR, top=TAPER_TOP, tau_std=TAU_MAX): """Banded reduced rate: fraction ``tau_low/tau_std`` in [T, top], 1 above.""" frac_low = tau_low / tau_std @@ -173,6 +213,11 @@ def sched(y): f[y > top] = 1.0 return f + sched.regions = [ + (0.0, float(T), 0.0), + (float(T), float(top), float(frac_low)), + (float(top), np.inf, 1.0), + ] return sched @@ -182,22 +227,7 @@ def schedule_effective_tau(schedule, y, tau_max=TAU_MAX): # --------------------------------------------------------------------------- -# Notch geometry for a schedule: where do registration notches sit? -# --------------------------------------------------------------------------- -def _schedule_notch_threshold(schedule, T=T_STAR): - """The turnover at which registration first bites under ``schedule``. - - For the raise-to-T_new schedule this is T_new; for taper/reduced-rate it is - T*. Detected numerically as the smallest y with fraction(y) > 0. - """ - grid = np.arange(T - 50_000.0, T + 60_000.0, 100.0) - f = np.asarray(schedule(grid), dtype=float) - pos = grid[f > 1e-12] - return float(pos.min()) if pos.size else T - - -# --------------------------------------------------------------------------- -# Forward solver: iso-elastic re-optimisation under a reform schedule +# Forward solver: region-confined iso-elastic response under a reform schedule # --------------------------------------------------------------------------- def forward_solve_iso_batch( n, @@ -206,65 +236,78 @@ def forward_solve_iso_batch( tau0, *, T=T_STAR, - fp_iter=60, + y_obs=None, + base_schedule=schedule_notch, + tau_std=TAU_MAX, + **_deprecated, ): - """Vectorised iso-elastic INTENSIVE-margin response for an array of abilities. - - Each firm faces its OWN baseline net VAT rate ``tau0`` (= ``liab/y_obs``, - the share of turnover it actually remits — ~3% on average, output VAT minus - input credits; NOT the statutory 20%, which is output-only). A reform - schedule scales that by the effective-rate fraction ``f(y) in [0,1]``, so the - firm's effective rate at turnover ``y`` is ``tau0 * f(y)`` and its - iso-elastic interior optimum solves the FOC:: - - (1 - tau0*f(y)) - y*(tau0*f'(y)) = (y/n)**(1/e) => y* = n*(1-tau_eff)**e - - for the locally-relevant effective rate ``tau_eff``. This makes ``e`` the SOLE - governing knob: the response to the net-of-tax rate has elasticity exactly - ``e``, and as ``e -> 0`` every firm freezes at ``y* = n``, with the recovered - ``n -> y_obs``, so the behavioural cost collapses onto the STATIC cost - (cross-check 4). The EXTENSIVE margin (bunching / de-registration) is the - separate analytic object (dominated region + marginal buncher) and is NOT - re-litigated here, so a small intensive elasticity does not spuriously empty - the registered population. - - Implementation: a damped fixed-point on ``y = n*(1 - tau0*f(y))**e``, robust - for both the flat-rate bands (immediate convergence) and the continuously - varying taper. ``n`` below the schedule's registration threshold stays at - ``n`` (unregistered; ``f=0``). Non-finite / non-positive ``n`` is returned - unchanged. Returns ``y_star`` (£), same shape as ``n``. + """Vectorised region-confined INTENSIVE-margin response (closed form). + + Each firm's observed turnover ``y_obs`` is anchored as optimal under the + BASELINE schedule (the £85k notch, fraction ``f0``). Under a reform whose + fraction on the firm's own region is ``f1``, the formulation-A optimum is:: + + y_star = y_obs * [(1 - tau_std*f1) / (1 - tau_std*f0)] ** e, + + the deductible share cancelling in the ratio, then clipped to the reform + region containing ``y_obs``. Firms whose region fraction is unchanged + (``f1 = f0``) do not move; released firms (``f1 = 0 < f0``) expand toward + their frictionless optimum but remit nothing; band firms scale up as the + band rate falls, clipped at the band top. Crossing a notch (the extensive + margin) is out of scope by construction — see the module docstring. + + ``n`` and ``tau0`` are accepted for API compatibility; the formulation-A + response ratio requires neither (the statutory ``tau_std`` and the + schedule fractions pin it). ``schedule`` must be piecewise flat (a + ``.regions`` attribute); the taper has ``regions = None`` and raises. + Returns ``y_star`` (£), same shape as ``y_obs``. """ - n = np.asarray(n, dtype=float) - tau0 = np.broadcast_to(np.asarray(tau0, dtype=float), n.shape).astype(float) - good = np.isfinite(n) & (n > 0) + regions = getattr(schedule, "regions", None) + if regions is None: + raise ValueError( + "region-confined intensive solve requires a piecewise-flat " + "schedule; the graduated taper is excluded from the behavioural " + "layer (its rate varies continuously with turnover)." + ) + if y_obs is None: + raise TypeError("forward_solve_iso_batch requires y_obs (observed £)") - T_sched = _schedule_notch_threshold(schedule, T) + y_obs = np.asarray(y_obs, dtype=float) + good = np.isfinite(y_obs) & (y_obs > 0) - # Fixed-point for the registered interior optimum y = n*(1 - tau0*f(y))**e. - # Start at y=n; damped update keeps it stable through the taper band. - y = np.where(good, n, 1.0) - for _ in range(fp_iter): - f = np.asarray(schedule(y), dtype=float) - tau_eff = np.clip(tau0 * f, 0.0, 0.999) - y_new = n * (1.0 - tau_eff) ** e - y = 0.5 * y + 0.5 * y_new + f0 = np.asarray(base_schedule(y_obs), dtype=float) + f1 = np.asarray(schedule(y_obs), dtype=float) - # A firm whose frictionless optimum is below the schedule's registration - # threshold is unregistered and simply locates at n (no tax wedge). - y = np.where(n < T_sched, n, y) + ratio = ((1.0 - tau_std * f1) / (1.0 - tau_std * f0)) ** e + y_star = y_obs * ratio - return np.where(good, y, n) + # Clip into the reform region containing y_obs. Region membership follows + # the schedule callable itself (fraction match), so boundary conventions + # (e.g. an inclusive band top) agree exactly with the static evaluation. + penny = 0.01 + for lo, hi, frac in regions: + member = good & (np.abs(f1 - frac) < 1e-12) & (y_obs >= lo) + if not np.any(member): + continue + if np.isfinite(hi): + f_at_hi = float(np.asarray(schedule(np.array([hi])), dtype=float)[0]) + hi_clip = hi if abs(f_at_hi - frac) < 1e-12 else hi - penny + else: + hi_clip = np.inf + y_star = np.where(member, np.clip(y_star, lo, hi_clip), y_star) + return np.where(good, y_star, y_obs) -def forward_solve_iso(n, e, schedule, tau0=TAU_MAX, **kw): + +def forward_solve_iso(y_obs, e, schedule, tau0=TAU_MAX, **kw): """Scalar wrapper around :func:`forward_solve_iso_batch`. - ``tau0`` defaults to the statutory ``TAU_MAX`` so the elasticity cross-check - (which probes the registered optimum ``n*(1-tau)**e``) uses the full - statutory wedge; the population revenue solve passes each firm's own net rate. + The first argument is the firm's observed (baseline-anchored) turnover in + pounds; the response ratio is governed solely by ``e``, the statutory rate, + and the baseline/reform schedule fractions at that turnover. """ out = forward_solve_iso_batch( - np.atleast_1d(float(n)), e, schedule, tau0, **kw) + None, e, schedule, tau0, y_obs=np.atleast_1d(float(y_obs)), **kw) return float(out[0]) @@ -328,23 +371,22 @@ def reform_revenue( ``df`` must provide ``turnover`` (£), ``liab`` (£, baseline net VAT remittance), and ``weight``. - Each firm faces its OWN baseline net VAT rate ``tau0 = liab/y_obs`` (~3% of - turnover on average — the share it actually remits, output VAT minus input - credits). A reform schedule scales that by the effective-rate fraction - ``f(y)``, so the firm's effective rate is ``tau0 * f(y)`` and its remittance - is ``liab * (y/y_obs) * f(y)`` (net VAT proportional to turnover). + A firm's remittance under a schedule with effective-rate fraction ``f(y)`` + is ``liab * (y/y_obs) * f(y)``: net VAT stays proportional to turnover + (value added a fixed share) and the schedule fraction is applied. - BASELINE (£85k notch) and REFORM are evaluated SYMMETRICALLY through the same - iso-elastic forward solve: + BASELINE (£85k notch) and REFORM are evaluated SYMMETRICALLY through the + same region-confined forward solve: * STATIC (``behavioural=False``): turnover fixed at observed; only the effective-rate fraction changes (notch ``f=1`` above T* vs the reform's ``f``). This reproduces the trusted static reform costs. - * BEHAVIOURAL: firms in ``[band_lo, band_hi]`` re-optimise turnover under the - iso-elastic model with elasticity ``e`` — under the £85k notch for the - baseline (``t_notch``) and under the reform schedule (``t_new``). As - ``e -> 0`` both freeze at observed turnover, so the behavioural cost - converges to the static cost (cross-check 4). + * BEHAVIOURAL: firms in ``[band_lo, band_hi]`` re-optimise turnover within + their own schedule region (formulation-A ratio, elasticity ``e``) — under + the £85k notch for the baseline (``t_notch``, which reproduces observed + turnover exactly: the accounting anchor) and under the reform schedule + (``t_new``). As ``e -> 0`` the ratio -> 1, so the behavioural cost + collapses onto the static cost exactly (cross-check 4). Returns a dict with baseline/reform revenue, the change vs baseline, the number of firms re-optimising, the near-threshold mass change, and the @@ -355,6 +397,8 @@ def reform_revenue( w = df["weight"].to_numpy(dtype=float) # Firm-specific baseline net VAT rate (share of turnover actually remitted). + # Not needed for the formulation-A response ratio (the deductible share + # cancels); retained for diagnostics. with np.errstate(divide="ignore", invalid="ignore"): tau0 = np.where(t_obs > 0, liab / t_obs, 0.0) @@ -362,15 +406,20 @@ def reform_revenue( idx = np.where(band)[0] if behavioural: - n = recover_ability(t_obs, e, T=T, tau=tau0) t_new = t_obs.copy() t_new[idx] = forward_solve_iso_batch( - n[idx], e, schedule, tau0[idx], T=T) - # Baseline turnover under the £85k notch via the SAME machinery — the - # apples-to-apples reference (both worlds re-optimised identically). + None, e, schedule, tau0[idx], T=T, y_obs=t_obs[idx]) + # Baseline turnover under the £85k notch via the SAME machinery — this + # must reproduce observed turnover exactly (accounting anchor). t_notch = t_obs.copy() t_notch[idx] = forward_solve_iso_batch( - n[idx], e, schedule_notch, tau0[idx], T=T) + None, e, schedule_notch, tau0[idx], T=T, y_obs=t_obs[idx]) + anchor_gap = float(np.max(np.abs(t_notch - t_obs))) if idx.size else 0.0 + if anchor_gap > 1e-6: + raise AssertionError( + f"baseline solve failed to reproduce observed turnover " + f"(max gap £{anchor_gap:.4f}) — accounting anchor violated" + ) else: t_new = t_obs t_notch = t_obs @@ -499,22 +548,19 @@ def check(name, value, target, tol, unit=""): # The two solves must agree with each other to ±£200. check(f"buncher agreement(e={e})", nH_iso, nH, 200.0, " GBP") - # 3. ELASTICITY CHECK: d ln(y*)/d ln(1-tau) = e for a registered firm. - # The firm faces effective rate tau0*f(y); with tau0=TAU_MAX and a flat - # fraction f=tau/TAU_MAX the effective rate is exactly tau, so the - # registered optimum is y* = n*(1-tau)**e. Perturb tau and confirm the - # log-response equals the input e (e is the governing knob). - n_test = 200_000.0 + # 3. ELASTICITY CHECK: d ln(y*)/d ln(1 - tau*f) = e for a registered firm. + # Probe two wide reduced-rate bands (fractions 0.5 and 0.6, effective + # rates 10% and 12%); the log response ratio must equal e exactly. + y_probe = 200_000.0 for e in (0.05, 0.17, 0.32): - tau_a, dtau = 0.20, 0.01 - def flat(tau): - return lambda y: (np.asarray(y, dtype=float) >= T_STAR).astype(float) * (tau / TAU_MAX) - y0 = forward_solve_iso(n_test, e, flat(tau_a), tau0=TAU_MAX) - y1 = forward_solve_iso(n_test, e, flat(tau_a + dtau), tau0=TAU_MAX) - elas = (np.log(y1) - np.log(y0)) / (np.log(1 - (tau_a + dtau)) - np.log(1 - tau_a)) - check(f"elasticity d ln y*/d ln(1-tau) (e={e})", elas, e, 0.02, "") - - # Static + behavioural(e->0) reform costs. + s_a = make_schedule_reduced_rate(0.10, top=1e9) + s_b = make_schedule_reduced_rate(0.12, top=1e9) + y_a = forward_solve_iso(y_probe, e, s_a) + y_b = forward_solve_iso(y_probe, e, s_b) + elas = (np.log(y_a) - np.log(y_b)) / (np.log(1 - 0.10) - np.log(1 - 0.12)) + check(f"elasticity d ln y*/d ln(1-tau f) (e={e})", elas, e, 1e-9, "") + + # Static + behavioural reform costs on the in-repository population. df = load_reform_data(data_path) t = df["turnover"].to_numpy() liab = df["liab"].to_numpy() @@ -523,14 +569,27 @@ def flat(tau): record("baseline registered base", base / 1e9, " bn") reforms = build_reforms() - e_lim = 0.001 # e -> 0 limit + static_costs = {} for rname, (sched, _label) in reforms.items(): - # Static. + # Static (all reforms, including the taper). rs = reform_revenue(df, sched, E_HEADLINE, behavioural=False) + static_costs[rname] = rs["d_rev"] record(f"static {rname}", rs["d_rev"], " GBP") - # 4. e -> 0 behavioural must converge to the static cost. - rb = reform_revenue(df, sched, e_lim, behavioural=True) - check(f"behavioural(e->0) {rname}", rb["d_rev"], rs["d_rev"], 20e6, " GBP") + if getattr(sched, "regions", None) is None: + continue # taper: behavioural layer excluded (non-flat schedule) + # 4. e -> 0 nesting must be EXACT (to £0.1m at e = 1e-6). The baseline + # reproduction (check 5) is asserted inside reform_revenue itself. + rb = reform_revenue(df, sched, 1e-6, behavioural=True) + check(f"behavioural(e->0) {rname}", rb["d_rev"], rs["d_rev"], 0.1e6, " GBP") + + # 6. Raise-to-£100k invariance: a pure level move has NO intensive-margin + # revenue offset — behavioural cost equals static cost at EVERY swept e + # (released firms leave the base; no other firm's effective rate changes). + sched_raise, _ = reforms["raise100k"] + for e in ELASTICITIES: + rb = reform_revenue(df, sched_raise, e, behavioural=True) + check(f"raise100k behavioural==static (e={e})", + rb["d_rev"], static_costs["raise100k"], 0.1e6, " GBP") if verbose: print("CROSSCHECK PASSED — analytic invariants and repo-data checks passed:") diff --git a/src/firm_microsim/generate.py b/src/firm_microsim/generate.py index d47bce6..efbcbc3 100644 --- a/src/firm_microsim/generate.py +++ b/src/firm_microsim/generate.py @@ -50,7 +50,7 @@ build_target_matrix, optimize_weights, ) -from .config import Config, DEFAULT_CONFIG +from .config import Config, DEFAULT_CONFIG, STANDARD_VAT_RATE from .data_loader import LoadedData, load_data from .validate import ValidationReport, validate @@ -138,9 +138,12 @@ def generate_input_values( ) -> Tensor: """Draw per-firm input expenditure (£k) from Beta input/output ratios. - Most firms get inputs at 60-95% of turnover (positive VAT liability); - sector-specific shifts allow some firms inputs > turnover (negative - liability), matching HMRC's negative net-liability sectors. + The input/output ratio is centred near 0.6 (value added ~40% of turnover, + in line with the UK non-financial business economy) with sector-specific + shifts, and clamped to [0.1, 0.95] so value added is always strictly + positive. Net VAT liability is then the standard rate applied to value + added (see :func:`generate_synthetic_firms`); the model is a standard-rate + turnover-tax approximation and does not represent net-repayment positions. Args: turnover_values: Per-firm turnover (£k). @@ -154,7 +157,7 @@ def generate_input_values( n_firms = len(turnover_values) base_ratios = torch.distributions.Beta(4.0, 2.0).sample((n_firms,)).to(device) - scaled = 0.3 + base_ratios * 1.0 # map [0,1] -> [0.3, 1.3] + scaled = 0.2 + base_ratios * 0.6 # map [0,1] -> [0.2, 0.8]; Beta(4,2) mean -> 0.6 sector_noise = torch.randn(n_firms, device=device) * 0.15 sic_np = sic_codes.cpu().numpy() @@ -166,21 +169,23 @@ def generate_input_values( scaled = scaled + neg_t.float() * (torch.rand(n_firms, device=device) * 0.3) scaled = scaled - high_t.float() * (torch.rand(n_firms, device=device) * 0.2) - # Floor the input/output ratio at 0.6 (value-added <= 40% of turnover). - # A lower floor lets a few firms get implausibly low input (VA up to 90% - # of turnover), which both produces unrealistic per-firm VAT liabilities - # and lets the weight optimiser concentrate huge weights on those outliers - # to hit the liability targets — distorting the near-threshold density and - # the static threshold sweep. 0.6 matches the documented 60-95% intent. - final_ratios = torch.clamp(scaled + sector_noise, 0.6, 1.5) + # Clamp the input/output ratio to [0.1, 0.95]: value added is always + # strictly positive (between 5% and 90% of turnover), so no firm has inputs + # exceeding turnover. The upper bound 0.95 rules out negative net VAT + # liability (the model is a standard-rate approximation that abstracts from + # net-repayment positions); the lower bound 0.1 prevents implausibly high + # value added that the weight optimiser could exploit with outlier weights. + final_ratios = torch.clamp(scaled + sector_noise, 0.1, 0.95) input_values = torch.where( turnover_values > 0, turnover_values * final_ratios, torch.zeros_like(turnover_values) ) logger.info( - "Input/output ratio: mean=%.2f std=%.2f; firms with negative VAT liability: %s", + "Input/output ratio: mean=%.2f std=%.2f; mean value-added share=%.2f; " + "firms with negative value added: %s", final_ratios.mean().item(), final_ratios.std().item(), + (1.0 - final_ratios).mean().item(), f"{int((final_ratios > 1.0).sum().item()):,}", ) return input_values @@ -236,8 +241,84 @@ def assign_employment( return torch.tensor(values, dtype=torch.float32, device=device) +def stratified_thin( + turnover_values: Tensor, sic_codes: Tensor, config: Config +) -> tuple[Tensor, Tensor]: + """Stratified thinning for fast iteration builds. + + Keeps rows inside the analysis window ``[sample_window_lo_k, + sample_window_hi_k]`` at ``sample_window_fraction`` and rows outside it at + ``sample_tail_fraction``, with at least ``sample_cell_floor`` retained rows + per stratum. Strata are sector x HMRC band x window-side. Each retained + row carries a base weight equal to its stratum's rows-drawn / rows-kept + ratio, so base-weighted totals reproduce the full draw's totals exactly + per stratum, and every calibration target remains a true total. + + Returns ``(keep_indices, base_weights_for_kept_rows)``. + """ + import numpy as np + from .calibration import map_to_hmrc_bands + + t = turnover_values.cpu().numpy() + sic = sic_codes.cpu().numpy() + band = map_to_hmrc_bands(turnover_values, config.vat_threshold).cpu().numpy() + in_window = ( + (t >= config.sample_window_lo_k) & (t <= config.sample_window_hi_k) + ) + frac = np.where(in_window, config.sample_window_fraction, config.sample_tail_fraction) + + rng = np.random.default_rng(config.seed + 1) + u = rng.random(len(t)) + keep = u < frac + + # Per-stratum floor + exact ratio base weights. + df = pd.DataFrame({"sic": sic, "band": band, "win": in_window, "keep": keep}) + df["order"] = u # deterministic per-stratum top-up ordering + grp = df.groupby(["sic", "band", "win"], sort=False) + floor = config.sample_cell_floor + kept_counts = grp["keep"].transform("sum") + sizes = grp["keep"].transform("size") + need_topup = (kept_counts < np.minimum(floor, sizes)) & (~df["keep"]) + if need_topup.any(): + # Keep the lowest-u unkept rows per deficient stratum up to the floor. + deficit = (np.minimum(floor, sizes) - kept_counts).clip(lower=0) + sel = df.index[need_topup] + rank = ( + df.loc[sel] + .groupby(["sic", "band", "win"], sort=False)["order"] + .rank(method="first") + ) + topup_idx = sel[rank.to_numpy() <= deficit.loc[sel].to_numpy()] + df.loc[topup_idx, "keep"] = True + + kept_counts = df.groupby(["sic", "band", "win"], sort=False)["keep"].transform("sum") + base = (sizes / kept_counts.replace(0, 1)).to_numpy() + + keep_np = df["keep"].to_numpy() + keep_idx = torch.tensor(np.where(keep_np)[0], device=config.device) + base_kept = torch.tensor( + base[keep_np], dtype=turnover_values.dtype, device=config.device + ) + logger.info( + "Stratified thinning: kept %s of %s rows (%.1f%%); base weights " + "1.0-%.1f; window [%.0fk, %.0fk] at %.0f%%, tails at %.0f%%", + f"{int(keep_np.sum()):,}", + f"{len(keep_np):,}", + 100.0 * keep_np.mean(), + float(base_kept.max().item()), + config.sample_window_lo_k, + config.sample_window_hi_k, + 100.0 * config.sample_window_fraction, + 100.0 * config.sample_tail_fraction, + ) + return keep_idx, base_kept + + def assign_vat_flags( - turnover_values: Tensor, hmrc_bands: Dict[str, float], config: Config + turnover_values: Tensor, + hmrc_bands: Dict[str, float], + config: Config, + base_weights: Tensor | None = None, ) -> Tensor: """Assign VAT registration flags. @@ -259,18 +340,21 @@ def assign_vat_flags( device = config.device below = (turnover_values > 0) & (turnover_values <= threshold) - n_below = int(below.sum().item()) + if base_weights is None: + n_below = float(below.sum().item()) + else: + n_below = float(base_weights[below].sum().item()) target_below = float(hmrc_bands["£1_to_Threshold"]) voluntary_rate = target_below / n_below if n_below > 0 else 0.15 logger.info( - "Voluntary VAT row rate: %.3f (target %s / synthetic rows %s)", + "Voluntary VAT row rate: %.3f (target %s / base-weighted rows %s)", voluntary_rate, f"{target_below:,.0f}", - f"{n_below:,}", + f"{n_below:,.0f}", ) mandatory = turnover_values > threshold - if n_below > 0: + if int(below.sum().item()) > 0: voluntary = below & (torch.rand(len(turnover_values), device=device) < voluntary_rate) else: voluntary = torch.zeros_like(below) @@ -328,6 +412,7 @@ def generate( threshold: Optional[float] = None, seed: Optional[int] = None, output: Optional[str] = None, + fast: bool = False, write: bool = True, return_report: bool = False, ): @@ -368,6 +453,11 @@ def generate( overrides["vat_threshold"] = float(threshold) if seed is not None: overrides["seed"] = int(seed) + if fast: + overrides.update( + sample_window_fraction=0.30, + sample_tail_fraction=0.05, + ) if overrides: # replace() re-runs Config.__post_init__, which re-derives # processed_dir from the (possibly new) data_vintage. @@ -387,6 +477,15 @@ def generate( base_sic, base_turnover = generate_base_firms(data.ons_turnover, cfg.device) base_input = generate_input_values(base_turnover, base_sic, cfg.device) + # Fast-iteration mode: stratified thinning with per-stratum base weights. + if cfg.sample_tail_fraction < 1.0 or cfg.sample_window_fraction < 1.0: + keep_idx, base_weights = stratified_thin(base_turnover, base_sic, cfg) + base_sic = base_sic[keep_idx] + base_turnover = base_turnover[keep_idx] + base_input = base_input[keep_idx] + else: + base_weights = torch.ones_like(base_turnover) + # Temporary per-firm employment-band assignment for the target matrix. tmp_emp = assign_employment(len(base_sic), data.ons_employment, cfg.device) emp_band_idx = torch.tensor( @@ -406,16 +505,27 @@ def generate( data.ons_employment, data.hmrc_liability_sector, data.vat_liability_bands, + near_threshold_bins=getattr(data, "near_threshold_bins", None), + base_weights=base_weights, ) - weights = optimize_weights(cfg, target_matrix, target_values, spec) + weights = optimize_weights( + cfg, target_matrix, target_values, spec, base_weights=base_weights + ) final_sic, final_turnover, final_input, final_weights = _add_zero_turnover_firms( base_sic, base_turnover, base_input, weights, data.hmrc_bands, cfg.device ) employment = assign_employment(len(final_sic), data.ons_employment, cfg.device) - vat_flags = assign_vat_flags(final_turnover, data.hmrc_bands, cfg) + # Zero-turnover rows appended above carry base weight 1 (never thinned). + n_extra = len(final_turnover) - len(base_weights) + final_base = torch.cat( + [base_weights, torch.ones(n_extra, device=cfg.device, dtype=base_weights.dtype)] + ) + vat_flags = assign_vat_flags( + final_turnover, data.hmrc_bands, cfg, base_weights=final_base + ) logger.info("Assembling final DataFrame...") sic_np = final_sic.cpu().numpy().astype(int) @@ -427,7 +537,7 @@ def generate( "sic_code": [str(s).zfill(5) for s in sic_np], "annual_turnover_k": turnover_np, "annual_input_k": input_np, - "vat_liability_k": turnover_np - input_np, + "vat_liability_k": STANDARD_VAT_RATE * (turnover_np - input_np), "employment": employment.cpu().numpy().astype(int), "weight": final_weights.cpu().numpy(), "vat_registered": vat_flags.cpu().numpy().astype(bool), diff --git a/src/firm_microsim/notch/model.py b/src/firm_microsim/notch/model.py index af7ee59..0d0cc70 100644 --- a/src/firm_microsim/notch/model.py +++ b/src/firm_microsim/notch/model.py @@ -44,8 +44,10 @@ TAU = 0.20 # statutory UK VAT rate (full effective rate once registered) ALPHA = 0.989 # returns-to-scale (near-CRS; flags taxed-branch degeneracy) -# Structural turnover elasticities for the marginal-buncher solve, calibrated to -# the paper's reduced-form bunching estimates (median ~0.17, mean ~0.32). +# ASSUMED turnover elasticities for the marginal-buncher solve. These are the +# midpoint and upper sweep values of the paper's e-sensitivity analysis (see +# dynamic.model.ELASTICITIES); they are assumption choices, NOT identified from +# the synthetic data and NOT derived from the reduced-form bunching outputs. E_MEDIAN = 0.17 E_MEAN = 0.32 diff --git a/src/firm_microsim/report.py b/src/firm_microsim/report.py index 67b3061..3d1c444 100644 --- a/src/firm_microsim/report.py +++ b/src/firm_microsim/report.py @@ -33,6 +33,12 @@ def _vintage_lines(vintage: str) -> list[str]: """Return the report lines for one vintage (or a skip notice).""" cfg = Config.for_vintage(vintage) csv_path = cfg.synthetic_dir / f"synthetic_firms_{vintage}.csv" + if not csv_path.exists(): + # A bare ``firm_microsim.generate()`` writes the generic + # ``cfg.output_file`` name rather than the vintage-suffixed one. + fallback = cfg.synthetic_dir / cfg.output_file + if fallback.exists(): + csv_path = fallback out = ["", "=" * 64, f" Vintage {vintage} | threshold £{int(cfg.vat_threshold)}k", diff --git a/src/firm_microsim/static/figures.py b/src/firm_microsim/static/figures.py index 388fc3f..cfcc746 100644 --- a/src/firm_microsim/static/figures.py +++ b/src/firm_microsim/static/figures.py @@ -29,7 +29,7 @@ _style_ax, ) -from .model import FISCAL_YEARS, POLICY_THRESHOLD, StaticVATModel +from .model import POLICY_THRESHOLD, StaticVATModel REF_GREY = "#888888" # current-threshold reference line HMRC_COLOR = PALETTE[4] # lighter teal for the HMRC series @@ -87,7 +87,10 @@ def plot_hmrc_comparison(model: StaticVATModel) -> None: b2 = ax.bar(x + w / 2, df["policyengine_impact_m"], w, label="Model estimate", color=PRIMARY, zorder=3) ax.axhline(0, color="black", linewidth=0.8, zorder=2) - ax.set_ylim(-265, 110) + # Headroom scales with the data so bar labels never clip. + lo = min(df["hmrc_impact_m"].min(), df["policyengine_impact_m"].min()) + hi = max(df["hmrc_impact_m"].max(), df["policyengine_impact_m"].max()) + ax.set_ylim(lo * 1.35, hi * 1.25) # Value label on each bar (£m), padded clear of the bar end. for bars in (b1, b2): @@ -97,13 +100,6 @@ def plot_hmrc_comparison(model: StaticVATModel) -> None: f"£{int(round(h))}m", ha="center", va="bottom" if h > 0 else "top", fontsize=TICK_SIZE - 2) - # Baseline / policy threshold values under each fiscal-year group. - for i, fy in enumerate(FISCAL_YEARS): - ax.text(i, -220, - f"Baseline: £{fy['baseline'] / 1000:.0f}k\n" - f"Policy: £{fy['policy'] / 1000:.0f}k", - ha="center", va="top", fontsize=TICK_SIZE - 3, color="#666666") - ax.set_xticks(x) ax.set_xticklabels(df["year"]) ax.set_ylabel("Revenue impact (£m)", fontsize=LABEL_SIZE) diff --git a/src/firm_microsim/validate.py b/src/firm_microsim/validate.py index 291660d..0f3b240 100644 --- a/src/firm_microsim/validate.py +++ b/src/firm_microsim/validate.py @@ -17,8 +17,11 @@ import numpy as np import pandas as pd -from .calibration import EMPLOYMENT_BANDS, VAT_LIABILITY_BANDS -from .config import Config +from .calibration import ( + EMPLOYMENT_BANDS, + VAT_LIABILITY_BANDS_CALIBRATED, +) +from .config import Config, STANDARD_VAT_RATE from .data_loader import LoadedData logger = logging.getLogger(__name__) @@ -127,7 +130,7 @@ def validate( threshold = config.vat_threshold df = synthetic_df.copy() df["hmrc_band"] = df["annual_turnover_k"].apply(lambda t: _hmrc_band_name(t, threshold)) - df["vat_liability_k"] = df["annual_turnover_k"] - df["annual_input_k"] + df["vat_liability_k"] = STANDARD_VAT_RATE * (df["annual_turnover_k"] - df["annual_input_k"]) df["sic_numeric"] = df["sic_code"].astype(int) df["weighted_liability_m"] = df["vat_liability_k"] * df["weight"] / 1000.0 all_bands = df.groupby("hmrc_band")["weight"].sum() @@ -200,8 +203,19 @@ def validate( float(synth_liab_band.get(band, 0.0)), float(data.vat_liability_bands[band]), ) - for band in VAT_LIABILITY_BANDS + for band in VAT_LIABILITY_BANDS_CALIBRATED ] + # The below-threshold liability band is NOT calibrated (voluntary + # registrants' net remittances are outside the liability model); log it + # as an informational diagnostic, like VAT liability by sector. + below_acc = _accuracy( + float(synth_liab_band.get("£1_to_Threshold", 0.0)), + float(data.vat_liability_bands["£1_to_Threshold"]), + ) + logger.info( + "VAT liability £1-to-Threshold (informational, NOT calibrated): %.1f%%", + 100.0 * below_acc, + ) vat_liability_band_accuracy = ( float(np.mean(liab_band_accs)) if liab_band_accs else 0.0 )