diff --git a/changelog.d/1114-indirect-tax-page-corrections.changed.md b/changelog.d/1114-indirect-tax-page-corrections.changed.md new file mode 100644 index 0000000000..a6f99dea6f --- /dev/null +++ b/changelog.d/1114-indirect-tax-page-corrections.changed.md @@ -0,0 +1 @@ +Corrected the indirect tax effects planning page (`docs/book/policy/indirect-tax-effects-plan.md`): UKMOD's TCO technical note does not give the 0.8 consumption elasticity reported in #1114, labour supply responses run through two separate routes, fuel duty also reads LPG and natural gas inputs, and a formula on a consumption input would not change values supplied by a dataset. diff --git a/docs/book/policy/indirect-tax-effects-plan.md b/docs/book/policy/indirect-tax-effects-plan.md index 7c1fb0b296..a6a9692780 100644 --- a/docs/book/policy/indirect-tax-effects-plan.md +++ b/docs/book/policy/indirect-tax-effects-plan.md @@ -21,27 +21,38 @@ Right now PolicyEngine UK computes: 1. **Direct effect**: the full structural change to income tax, NI, UC and so on under the reform. -2. **Behavioural response on labour supply**: modelled with the +2. **Behavioural response on labour supply**: available through two + separate routes. `employment_income_behavioral_response` applies the substitution and income elasticities under - `gov.simulation.labour_supply_responses` (`policyengine_uk/dynamics/labour_supply.py`, - `employment_income_behavioral_response`). + `gov.simulation.labour_supply_responses` (both 0 by default). + Separately, calling `Simulation.apply_dynamics` on a simulation with a + baseline runs `apply_labour_supply_responses` + (`policyengine_uk/dynamics/labour_supply.py`), which applies the OBR's + elasticities by demographic group when + `gov.dynamic.obr_labour_supply_assumptions` is true, as it is by + default. 3. **Indirect-tax response**: *not modelled*. Households' consumption bundles are read from the dataset and don't shift in response to income changes. -#1114 reports that UKMOD handles this in its indirect tax (TCO) module with -an aggregate **consumption elasticity of 0.8**: a 1% rise in net income gives a 0.8% rise in -consumption, which then flows through VAT and excise revenue. That figure -has not yet been checked against UKMOD's own documentation, so it needs a -primary source before it is used as a default. +#1114 suggests that UKMOD handles this in its indirect taxation (TCO) +extension with a consumption elasticity of 0.8, citing only a ChatGPT +conversation. UKMOD's own +[TCO technical note](https://www.microsimulation.ac.uk/wp-content/uploads/2026/01/TCO-extension-v3.pdf) +(revised October 2025) does not give 0.8. It describes three alternative +assumptions: constant income shares (an income elasticity of +1 for every +commodity), constant expenditure shares (nominal savings held fixed, so the +whole change in disposable income goes to spending) and constant quantities +(an income elasticity of 0). Any default therefore needs another primary +source. ## Scope ### Phase 1: household-level consumption response - New parameter `gov/simulation/indirect_tax_response/consumption_elasticity.yaml`, - defaulting to 0 (no response) until a sourced value such as UKMOD's is - confirmed and cited in its metadata. + defaulting to 0 (no response) until a sourced value is confirmed and + cited in its metadata. - New variable `consumption_response_factor` (Household, YEAR) = `1 + elasticity * (net_income_change / baseline_net_income)`. - Apply the factor to the twelve COICOP categories that `consumption` @@ -51,7 +62,8 @@ primary source before it is used as a default. `reduced_rate_vat_consumption`), so it picks up the change. - The duties do not read those categories. Fuel duty reads `petrol_litres` and `diesel_litres`, which divide the `petrol_spending` - and `diesel_spending` inputs by pump prices. Alcohol duty reads the + and `diesel_spending` inputs by pump prices, and the `lpg_kg` and + `natural_gas_kg` inputs. Alcohol duty reads the `*_litres` inputs under `variables/input/consumption/alcohol/`, and tobacco duty reads `cigarettes_per_week` and the `*_grams_per_week` inputs under `variables/input/consumption/tobacco/`. The same factor @@ -60,10 +72,11 @@ primary source before it is used as a default. ### Phase 2: heterogeneity by category - A single economy-wide elasticity hides that some categories (food - staples, domestic energy) are nearly income-inelastic while others - (recreation, restaurants) are not. Replace the single + staples, domestic energy) are less income-elastic than others + (recreation, restaurants). Replace the single `consumption_elasticity.yaml` with a per-category set, calibrated to - ONS *Living Costs and Food Survey* income-elasticity estimates. + income elasticities estimated from the ONS *Living Costs and Food + Survey*. ### Phase 3: incidence link @@ -93,10 +106,11 @@ primary source before it is used as a default. Each `*_consumption` input variable currently reads straight from the dataset. Two options for the hook: -1. **Decorate at the input layer**: add `defined_for` / - `default_formula` that multiplies by `consumption_response_factor`. - This is clean but ties the consumption inputs to indirect-tax - modelling. +1. **Decorate at the input layer**: give each input a formula that + multiplies by `consumption_response_factor`. This ties the consumption + inputs to indirect-tax modelling, and policyengine-core does not run a + formula for a period the dataset already supplies, so it would not + change dataset values. 2. **Insert a derived layer**: keep `*_consumption_baseline` (reads from data) and introduce `*_consumption` formulas that apply the response factor. This is the safer route: users who do not need the indirect @@ -109,28 +123,33 @@ Recommendation: route (2). The dataset-side variable becomes ### Tests -- A reform that drops income tax for low-income households should - produce a *positive* `consumer_incident_tax_revenue_change` aggregate - (more take-home pay -> more consumption -> more VAT). +- Once Phase 3 derives `consumer_incident_tax_revenue_change` from the + response, a reform that drops income tax for low-income households should + produce a *positive* aggregate (more take-home pay -> more consumption -> + more VAT). Today the variable spreads the amount set by the + `consumer_incident_tax_change` parameter (in £bn) over households in + proportion to their consumption, so in a `policyengine_uk` simulation + with positive weighted consumption its weighted aggregate equals that + amount whatever the reform does to income. - A reform that raises NI should produce a *negative* aggregate. - The aggregate should track elasticity × (sum of net income change × VAT-equivalent rate) to within a small tolerance. ## Open questions -- Should the elasticity vary by household income decile? Empirical - evidence suggests low-income households have higher marginal - consumption propensity. +- Should the elasticity vary by household income decile, for example if + lower-income households spend a larger share of extra income? - Should saving be modelled explicitly (the residual after consumption)? - Phase 1 implicitly assumes any income change above the elasticity - applies to saving. + Phase 1 implicitly assumes that whatever part of an income change is not + consumed (a share of 1 − elasticity × baseline consumption / baseline + net income) is saved. - How does this interact with the existing labour-supply response so we don't double-count? ## References -- UKMOD documentation, to confirm the 0.8 consumption elasticity reported in #1114 (not yet checked). -- ONS [Living Costs and Food Survey](https://www.ons.gov.uk/peoplepopulationandcommunity/personalandhouseholdfinances/expenditure/bulletins/familyspendingintheuk/latest): income-elasticity calibration source for Phase 2. +- UKMOD, [Indirect Taxation (TCO) Extension technical note](https://www.microsimulation.ac.uk/wp-content/uploads/2026/01/TCO-extension-v3.pdf) (revised October 2025): its three expenditure assumptions; it does not give the 0.8 reported in #1114. +- ONS, [Family spending in the UK](https://www.ons.gov.uk/peoplepopulationandcommunity/personalandhouseholdfinances/expenditure/bulletins/familyspendingintheuk/latest): the Living Costs and Food Survey's headline publication; Phase 2 income elasticities would be estimated from LCF microdata. - HMRC, [VAT annual statistics](https://www.gov.uk/government/statistics/value-added-tax-vat-annual-statistics): calibration target for the aggregate. - Existing infrastructure: [`consumer_incident_tax_revenue_change`](https://github.com/PolicyEngine/policyengine-uk/blob/main/policyengine_uk/variables/contrib/policyengine/consumer_incident_tax_revenue_change.py) and the `gov/simulation/labour_supply_responses/` parameter tree for the parallel labour-supply pattern. - Related issue: [#1114](https://github.com/PolicyEngine/policyengine-uk/issues/1114).