Skip to content

Commit 9cdbef8

Browse files
Add enhanced FRS (wealth + consumption imputation) and VAT (#8)
* Add enhanced FRS (wealth + consumption imputation), VAT, and fix state pension scaling Ports the EFRS pipeline from policyengine-uk-data to Rust: trains random forest models on WAS (wealth) and LCFS (consumption) survey data, predicts onto FRS households, and calibrates energy consumption to NEED 2023 targets. Adds a household-level VAT calculation (standard/reduced/zero rates by COICOP category) wired into net income, enabling distributional analysis of consumption tax reforms. Fixes state pension reform responsiveness: reported SP amounts are now scaled by reform_rate/baseline_rate so that changing the SP parameter actually affects household net income. Previously reported amounts were passed through verbatim, making SP reforms have near-zero distributional impact. New CLI flags: --extract-efrs, --was-dir, --lcfs-dir. Co-Authored-By: Claude <noreply@anthropic.com> * Move HICBC to income tax charge, add EFRS auto-detect default HICBC is now correctly modelled as an income tax charge on the highest earner (Phase 2b of simulation) rather than a child benefit reduction. Child benefit is paid in full; the charge is tapered between the HICBC threshold and taper end based on adjusted net income. Also adds auto-detection of data/efrs_clean (preferred) or data/frs_clean when no explicit data source is specified on the CLI. Co-Authored-By: Claude <noreply@anthropic.com> * Fix state pension (new vs basic SP), add fiscal_year to Simulation, add efrs to Python DATASETS State pension now matches policyengine-uk approach: new SP recipients (reached SP age after April 2016) get the full parameter rate directly; basic SP recipients get reported amounts scaled by reform ratio. Also adds fiscal_year parameter to Simulation constructor and adds "efrs" to the Python interface's DATASETS tuple for GCS download support. Co-Authored-By: Claude <noreply@anthropic.com> * State pension flows through to income tax: reorder simulation phases Calculate per-person state pension in Phase 1a before income tax in Phase 1b, so SP reforms correctly affect taxable income. Previously income tax used reported SP amounts regardless of reform parameters, causing £0 revenue change for SP reforms. Also fixes HMAC download truncation in Python data module (adds content-length verification and timeout). Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 54af6fe commit 9cdbef8

58 files changed

Lines changed: 2206 additions & 227 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 189 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ indicatif = "0.17"
1515
comfy-table = "7"
1616
colored = "2"
1717
anyhow = "1"
18+
smartcore = "0.4"
19+
rand = "0.8"
1820

1921
[profile.release]
2022
opt-level = 3

interfaces/python/policyengine_uk_compiled/data.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,21 @@ def _download_object(key: str, dest: Path, access_key: str, secret_key: str):
3737
url = f"https://{GCS_HOST}/{GCS_BUCKET}{path}"
3838
req = urllib.request.Request(url, headers=headers)
3939
dest.parent.mkdir(parents=True, exist_ok=True)
40-
with urllib.request.urlopen(req) as resp:
40+
with urllib.request.urlopen(req, timeout=300) as resp:
41+
expected = int(resp.headers.get("Content-Length", 0))
42+
written = 0
4143
with open(dest, "wb") as f:
4244
while True:
4345
chunk = resp.read(1 << 20)
4446
if not chunk:
4547
break
4648
f.write(chunk)
49+
written += len(chunk)
50+
if expected and written != expected:
51+
dest.unlink(missing_ok=True)
52+
raise IOError(
53+
f"Incomplete download for {key}: got {written} of {expected} bytes"
54+
)
4755

4856

4957
def _get_credentials() -> tuple[str, str]:
@@ -60,7 +68,7 @@ def _get_credentials() -> tuple[str, str]:
6068
return token.split(":", 1)
6169

6270

63-
DATASETS = ("frs", "lcfs", "spi", "was")
71+
DATASETS = ("frs", "efrs", "lcfs", "spi", "was")
6472

6573

6674
def ensure_dataset_year(dataset: str, year: int) -> Path:

parameters/1994_95.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ uc_migration:
130130
tax_credits: 0.0
131131
income_support: 0.0
132132

133+
134+
vat:
135+
standard_rate: 0.175
136+
reduced_rate: 0.05
137+
zero_rate: 0.0
138+
133139
growth_factors:
134140
cpi_rate: 0.0
135141
gdp_deflator: 0.0

parameters/1995_96.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ uc_migration:
130130
tax_credits: 0.0
131131
income_support: 0.0
132132

133+
134+
vat:
135+
standard_rate: 0.175
136+
reduced_rate: 0.05
137+
zero_rate: 0.0
138+
133139
growth_factors:
134140
cpi_rate: 0.0
135141
gdp_deflator: 0.0

parameters/1996_97.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ uc_migration:
130130
tax_credits: 0.0
131131
income_support: 0.0
132132

133+
134+
vat:
135+
standard_rate: 0.175
136+
reduced_rate: 0.05
137+
zero_rate: 0.0
138+
133139
growth_factors:
134140
cpi_rate: 0.0
135141
gdp_deflator: 0.0

parameters/1997_98.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ uc_migration:
130130
tax_credits: 0.0
131131
income_support: 0.0
132132

133+
134+
vat:
135+
standard_rate: 0.175
136+
reduced_rate: 0.05
137+
zero_rate: 0.0
138+
133139
growth_factors:
134140
cpi_rate: 0.0
135141
gdp_deflator: 0.0

parameters/1998_99.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ uc_migration:
130130
tax_credits: 0.0
131131
income_support: 0.0
132132

133+
134+
vat:
135+
standard_rate: 0.175
136+
reduced_rate: 0.05
137+
zero_rate: 0.0
138+
133139
growth_factors:
134140
cpi_rate: 0.0
135141
gdp_deflator: 0.0

parameters/1999_00.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ uc_migration:
130130
tax_credits: 0.0
131131
income_support: 0.0
132132

133+
134+
vat:
135+
standard_rate: 0.175
136+
reduced_rate: 0.05
137+
zero_rate: 0.0
138+
133139
growth_factors:
134140
cpi_rate: 0.0
135141
gdp_deflator: 0.0

parameters/2000_01.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ uc_migration:
130130
tax_credits: 0.0
131131
income_support: 0.0
132132

133+
134+
vat:
135+
standard_rate: 0.175
136+
reduced_rate: 0.05
137+
zero_rate: 0.0
138+
133139
growth_factors:
134140
cpi_rate: 0.0
135141
gdp_deflator: 0.0

0 commit comments

Comments
 (0)