Skip to content

Conversation

@MaxGhenis
Copy link
Collaborator

@MaxGhenis MaxGhenis commented Oct 2, 2025

Summary

Fixes the bug where two-child limit budgetary impact was incorrectly constant across projection years.

Problem

The birth_year variable was being loaded from the dataset as a static value, preventing it from being recalculated based on the projection year. This caused:

  • Birth years to remain constant (e.g., 2006-2023 range in both 2026 and 2029)
  • Number of children exempt from two-child limit to stay constant
  • Cost of repealing the limit to be incorrectly flat across years

With a consistent age distribution in the microdata:

  • 2026: 10-year-olds should represent children born in 2016 → exempt (< 2017)
  • 2029: 10-year-olds should represent children born in 2019 → NOT exempt (≥ 2017)

Solution

Skip loading birth_year from the dataset in simulation.py, allowing the Variable formula (period.year - age) to calculate it fresh for each projection year.

# Skip birth_year - it should be calculated from age and period
# to properly reflect the projection year in multi-year datasets
if variable == "birth_year":
    continue

Results

Population Demographics

Before fix:

  • 2026: 14,870 children born <2017 (exempt), birth years 2006-2023
  • 2029: 14,870 children born <2017 (exempt), birth years 2006-2023
  • Same cost in both years ❌

After fix:

  • 2026: 10,638 children born <2017 (exempt), birth years 2009-2026
  • 2029: 6,504 children born <2017 (exempt), birth years 2012-2029
  • 4,134 more children subject to limit in 2029

Budgetary Impact (Repeal Cost)

With the fix applied:

  • 2026: £3.28bn total (£0.00bn CTC, £3.28bn UC)
  • 2029: £3.76bn total (£0.00bn CTC, £3.76bn UC)
  • Change: +£0.47bn (+14.4%)

The cost now correctly increases over time as more children born after April 2017 enter the population ✓

Dependencies

Test Plan

  • Verified birth years now update correctly by projection year
  • Confirmed number of affected children increases over time
  • Ran microsimulation showing 14.4% cost increase from 2026 to 2029
  • Changelog updated

🤖 Generated with Claude Code

Fixes issue where two-child limit budgetary impact was incorrectly
constant across projection years (e.g., same £2.2bn in 2026 and 2029).

The bug: birth_year was being loaded from the dataset as a static value,
preventing it from being recalculated based on the projection year. With
a consistent age distribution in the microdata:
- 2026: 10-year-olds should represent children born in 2016 (exempt)
- 2029: 10-year-olds should represent children born in 2019 (not exempt)

The fix: Skip loading birth_year from the dataset, allowing the Variable
formula (period.year - age) to calculate it fresh for each projection year.

Now the number of children subject to the two-child limit correctly
increases over time (+4,134 from 2026 to 2029), and the cost of repealing
the limit will rise appropriately in projections.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
MaxGhenis added a commit to PolicyEngine/policyengine-uk-data that referenced this pull request Oct 2, 2025
birth_year should be calculated from age and period in the model,
not stored as static data in the dataset. This allows birth_year to
properly update in multi-year projections.

With static birth_year in the dataset:
- 2026: birth_year stays 2006-2023 (based on 2023 survey)
- 2029: birth_year stays 2006-2023 (incorrect)

By calculating birth_year = period.year - age:
- 2026: birth_year becomes 2009-2026 (correct for 2026)
- 2029: birth_year becomes 2012-2029 (correct for 2029)

This fix is required for PolicyEngine/policyengine-uk#1352 to work
correctly and ensure two-child limit cost projections increase over
time as expected.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
MaxGhenis added a commit to PolicyEngine/policyengine-uk-data that referenced this pull request Oct 2, 2025
birth_year should be calculated from age and period in the model,
not stored as static data in the dataset. This allows birth_year to
properly update in multi-year projections.

With static birth_year in the dataset:
- 2026: birth_year stays 2006-2023 (based on 2023 survey)
- 2029: birth_year stays 2006-2023 (incorrect)

By calculating birth_year = period.year - age:
- 2026: birth_year becomes 2009-2026 (correct for 2026)
- 2029: birth_year becomes 2012-2029 (correct for 2029)

This fix is required for PolicyEngine/policyengine-uk#1352 to work
correctly and ensure two-child limit cost projections increase over
time as expected.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@MaxGhenis
Copy link
Collaborator Author

Closing as unnecessary. Removing birth_year from the dataset (PolicyEngine/policyengine-uk-data#198) is sufficient - the Variable formula will automatically calculate it from age and period when it's not present in the input data.

@MaxGhenis MaxGhenis closed this Oct 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants