Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Indirect tax effects of reforms (planned)

What this is about

When a direct tax reform changes a household’s disposable income, real households respond by adjusting consumption. That changes the indirect tax revenue (VAT, excise duties, fuel duty) the household generates. 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: available through two separate routes. employment_income_behavioral_response applies the substitution and income elasticities under 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 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 (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

Phase 2: heterogeneity by category

Implementation outline

Variables

Hook points

Each *_consumption input variable currently reads straight from the dataset. Two options for the hook:

  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 tax response keep the pre-reform consumption as *_consumption_baseline.

Recommendation: route (2). The dataset-side variable becomes *_consumption_baseline; the response factor is applied at *_consumption.

Tests

Open questions

References