model 01 — tax-benefit microsimulation · pe-microsim · UK · US · hosted

Calculate taxes and benefits.

Compare current law with a reform for a UK or US household, or estimate population-wide revenue and distributional effects.

code

A household in one call.

Four steps from nothing to a population-wide costing; each step's code sits alongside its narrative.

1

Pick a route: hosted MCP, CLI, or Python

Hosted MCP server

The quickest route is the hosted MCP server, with five tools — calculate_household, household_reform_impact, population_reform_impact, list_reform_parameters, and score_reform with model="microsim". The UK microdata credential is provisioned server-side.

CLI and Python

The pe-macro CLI mirrors the same tools one for one; the Python package underneath is what the rest of this page walks through.

The three routes in, tool by tool
MCP toolCLI mirror
calculate_householdpe-macro household
household_reform_impactpe-macro household-impact
population_reform_impactpe-macro population-impact
list_reform_parameterspe-macro parameters
score_reform with model="microsim"pe-macro score

The third route is the Python package directly — import policyengine as pe, walked through below.

Every number from this model is a static score. Prices, wages and output do not move. For second-round effects on GDP, route the same reform through the OBR emulator: score_reform with model="obr" takes this package's static costing as the direct effect and returns the economy-wide feedback.
2

Install

From PyPI

The base install is shared tooling only; add [models] for the pinned UK + US country models, or a single country extra.

install
pip install policyengine            # shared tooling, no country models
pip install "policyengine[models]"  # + pinned UK and US models
pip install "policyengine[uk]"      # UK model only
pip install "policyengine[us]"      # US model only
3

Calculate a household

Describe, pick a year, read

Describe the people, pick a year, read the results — no data access or credentials needed. Pass a reform dict to apply parameter changes.

Household-level reform impact

differencing runs with and without reform gives the household-level impact: for the UK earner opposite, a 25% basic rate ({"gov.hmrc.income_tax.rates.uk[0].rate": 0.25}) adds £1,872 of income tax and cuts net income by the same amount.

household calculation
import policyengine as pe

# UK: single adult earning £50,000 — current law
uk = pe.uk.calculate_household(
    people=[{"age": 35, "employment_income": 50_000}],
    year=2026,
)
print(uk.person[0].income_tax)                   # £7,486
print(uk.person[0].national_insurance)           # £2,994
print(uk.household.hbai_household_net_income)    # £39,520

# US: single filer in California, with a reform applied
us = pe.us.calculate_household(
    people=[{"age": 35, "employment_income": 60_000}],
    tax_unit={"filing_status": "SINGLE"},
    household={"state_code": "CA"},
    year=2026,
    reform={"gov.irs.credits.ctc.amount.adult_dependent": 1000},
)
print(us.tax_unit.income_tax, us.household.household_net_income)
4

Score a whole population

Representative datasets

The same package runs whole representative datasets — the enhanced UK Family Resources Survey, the US CPS — aggregating any variable by decile, entity or demographic.

UK population microdata is gated — set HUGGING_FACE_TOKEN from an account with access to policyengine/policyengine-uk-data before running UK population examples locally. The hosted MCP server provisions this credential server-side.
population scoring
import policyengine as pe
from policyengine.core import Simulation
from policyengine.outputs.aggregate import Aggregate, AggregateType

datasets = pe.uk.ensure_datasets(datasets=["enhanced_frs_2023_24"],
                                 years=[2026], data_folder="./data")
simulation = Simulation(dataset=datasets["enhanced_frs_2023_24_2026"],
                        tax_benefit_model_version=pe.uk.model)
simulation.run()

agg = Aggregate(simulation=simulation, variable="universal_credit",
                aggregate_type=AggregateType.SUM, entity="benunit")
agg.run()
print(f"Total UC spending: £{agg.result / 1e9:.1f}bn")
what it can answer

From one family to the whole distribution.

Common microsimulation questions and how to answer them
questionhow
What does this reform do to this family? calculate_household / household_reform_impact — every tax, benefit and income variable at person, benefit-unit/tax-unit and household level. On the hosted MCP server and the pe-macro CLI.
What does it cost, and who wins? population_reform_impact and pe.uk.economic_impact_analysis — budgetary impact, decile changes, winners and losers, poverty, inequality, regional impacts. Hosted, enhanced-FRS credential provisioned server-side.
What levers exist? list_reform_parameters — the parameter tree you can write reforms against.
It cannot tell you what a reform does to GDP, interest rates, or the fiscal forecast. It is static and partial-equilibrium by design: behavioural responses are optional and post-hoc (e.g. labour-supply elasticities), with no general equilibrium. That second act is what the macro members add — short-run and long-run.