--- name: policyengine-us description: PolicyEngine-US tax and benefit microsimulation patterns, situation creation, and common workflows --- # PolicyEngine-US PolicyEngine-US models the US federal and state tax and benefit system. ## For Users 👥 ### What is PolicyEngine-US? PolicyEngine-US is the "calculator" for US taxes and benefits. When you use policyengine.org/us, PolicyEngine-US runs behind the scenes. **What it models:** **Federal taxes:** - Income tax (with standard/itemized deductions) - Payroll tax (Social Security, Medicare) - Capital gains tax **Federal benefits:** - Earned Income Tax Credit (EITC) - Child Tax Credit (CTC) - SNAP (food stamps) - WIC, ACA premium tax credits - Social Security, SSI, TANF **State programs (varies by state):** - State income tax (all 50 states + DC) - State EITC, CTC - State-specific benefits **See full list:** https://policyengine.org/us/parameters ### Understanding Variables When you see results in PolicyEngine, these are variables: **Income variables:** - `employment_income` - W-2 wages - `self_employment_income` - 1099 income - `qualified_dividend_income` - Dividends - `capital_gains` - Capital gains **Tax variables:** - `income_tax` - Federal income tax - `state_income_tax` - State income tax - `payroll_tax` - FICA taxes **Benefit variables:** - `eitc` - Earned Income Tax Credit - `ctc` - Child Tax Credit - `snap` - SNAP benefits **Summary variables:** - `household_net_income` - Income after taxes and benefits - `household_tax` - Total taxes - `household_benefits` - Total benefits ## For Analysts 📊 ### Installation and Setup ```bash # Install PolicyEngine-US pip install policyengine-us # Or with uv (recommended) uv pip install policyengine-us ``` ### Quick Start ```python from policyengine_us import Simulation # Create a household situation = { "people": { "you": { "age": {2024: 30}, "employment_income": {2024: 50000} } }, "families": {"family": {"members": ["you"]}}, "marital_units": {"marital_unit": {"members": ["you"]}}, "tax_units": {"tax_unit": {"members": ["you"]}}, "spm_units": {"spm_unit": {"members": ["you"]}}, "households": { "household": { "members": ["you"], "state_name": {2024: "CA"} } } } # Calculate taxes and benefits sim = Simulation(situation=situation) income_tax = sim.calculate("income_tax", 2024)[0] eitc = sim.calculate("eitc", 2024)[0] print(f"Income tax: ${income_tax:,.0f}") print(f"EITC: ${eitc:,.0f}") ``` ### Web App to Python **Web app URL:** ``` policyengine.org/us/household?household=12345 ``` **Equivalent Python (conceptually):** The household ID represents a situation dictionary. To replicate in Python, you'd create a similar situation. ### When to Use This Skill - Creating household situations for tax/benefit calculations - Running microsimulations with PolicyEngine-US - Analyzing policy reforms and their impacts - Building tools that use PolicyEngine-US (calculators, analysis notebooks) - Debugging PolicyEngine-US calculations ## For Contributors 💻 ### Repository **Location:** PolicyEngine/policyengine-us **To see current implementation:** ```bash git clone https://github.com/PolicyEngine/policyengine-us cd policyengine-us # Explore structure tree policyengine_us/ ``` **Key directories:** ```bash ls policyengine_us/ # - variables/ - Tax and benefit calculations # - parameters/ - Policy rules (YAML) # - reforms/ - Pre-defined reforms # - tests/ - Test cases ``` ## Core Concepts ### 1. Situation Dictionary Structure PolicyEngine requires a nested dictionary defining household composition and characteristics: ```python situation = { "people": { "person_id": { "age": {2024: 35}, "employment_income": {2024: 50000}, # ... other person attributes } }, "families": { "family_id": {"members": ["person_id", ...]} }, "marital_units": { "marital_unit_id": {"members": ["person_id", ...]} }, "tax_units": { "tax_unit_id": {"members": ["person_id", ...]} }, "spm_units": { "spm_unit_id": {"members": ["person_id", ...]} }, "households": { "household_id": { "members": ["person_id", ...], "state_name": {2024: "CA"} } } } ``` **Key Rules:** - All entities must have consistent member lists - Use year keys for all values: `{2024: value}` - State must be two-letter code (e.g., "CA", "NY", "TX") - All monetary values in dollars (not cents) ### 2. Creating Simulations ```python from policyengine_us import Simulation # Create simulation from situation simulation = Simulation(situation=situation) # Calculate variables income_tax = simulation.calculate("income_tax", 2024) eitc = simulation.calculate("eitc", 2024) household_net_income = simulation.calculate("household_net_income", 2024) ``` **Common Variables:** **Income:** - `employment_income` - W-2 wages - `self_employment_income` - 1099/business income - `qualified_dividend_income` - Qualified dividends - `capital_gains` - Capital gains - `interest_income` - Interest income - `social_security` - Social Security benefits - `pension_income` - Pension/retirement income **Deductions:** - `charitable_cash_donations` - Cash charitable giving - `real_estate_taxes` - State and local property taxes - `mortgage_interest` - Mortgage interest deduction - `medical_expense` - Medical and dental expenses - `casualty_loss` - Casualty and theft losses **Tax Outputs:** - `income_tax` - Total federal income tax - `payroll_tax` - FICA taxes - `state_income_tax` - State income tax - `household_tax` - Total taxes (federal + state + local) **Benefits:** - `eitc` - Earned Income Tax Credit - `ctc` - Child Tax Credit - `snap` - SNAP benefits - `household_benefits` - Total benefits **Summary:** - `household_net_income` - Income minus taxes plus benefits ### 3. Using Axes for Parameter Sweeps To vary a parameter across multiple values: ```python situation = { # ... normal situation setup ... "axes": [[{ "name": "employment_income", "count": 1001, "min": 0, "max": 200000, "period": 2024 }]] } simulation = Simulation(situation=situation) # Now calculate() returns arrays of 1001 values incomes = simulation.calculate("employment_income", 2024) # Array of 1001 values taxes = simulation.calculate("income_tax", 2024) # Array of 1001 values ``` **Important:** Remove axes before creating single-point simulations: ```python situation_single = situation.copy() situation_single.pop("axes", None) simulation = Simulation(situation=situation_single) ``` ### 4. Policy Reforms ```python from policyengine_us import Simulation # Define a reform (modifies parameters) reform = { "gov.irs.credits.ctc.amount.base_amount": { "2024-01-01.2100-12-31": 5000 # Increase CTC to $5000 } } # Create simulation with reform simulation = Simulation(situation=situation, reform=reform) ``` ## Common Patterns ### Pattern 1: Single Household Calculation ```python from policyengine_us import Simulation situation = { "people": { "parent": { "age": {2024: 35}, "employment_income": {2024: 60000} }, "child": { "age": {2024: 5} } }, "families": {"family": {"members": ["parent", "child"]}}, "marital_units": {"marital_unit": {"members": ["parent"]}}, "tax_units": {"tax_unit": {"members": ["parent", "child"]}}, "spm_units": {"spm_unit": {"members": ["parent", "child"]}}, "households": { "household": { "members": ["parent", "child"], "state_name": {2024: "NY"} } } } sim = Simulation(situation=situation) income_tax = sim.calculate("income_tax", 2024)[0] ctc = sim.calculate("ctc", 2024)[0] ``` ### Pattern 2: Marginal Tax Rate Analysis ```python # Create baseline with axes varying income situation_with_axes = { # ... situation setup ... "axes": [[{ "name": "employment_income", "count": 1001, "min": 0, "max": 200000, "period": 2024 }]] } sim = Simulation(situation=situation_with_axes) incomes = sim.calculate("employment_income", 2024) taxes = sim.calculate("income_tax", 2024) # Calculate marginal tax rate import numpy as np mtr = np.gradient(taxes) / np.gradient(incomes) ``` ### Pattern 3: Charitable Donation Impact ```python # Baseline (no donation) situation_baseline = create_situation(income=100000, donation=0) sim_baseline = Simulation(situation=situation_baseline) tax_baseline = sim_baseline.calculate("income_tax", 2024)[0] # With donation situation_donation = create_situation(income=100000, donation=5000) sim_donation = Simulation(situation=situation_donation) tax_donation = sim_donation.calculate("income_tax", 2024)[0] # Tax savings from donation tax_savings = tax_baseline - tax_donation effective_discount = tax_savings / 5000 # e.g., 0.24 = 24% discount ``` ### Pattern 4: State Comparison ```python states = ["CA", "NY", "TX", "FL"] results = {} for state in states: situation = create_situation(state=state, income=75000) sim = Simulation(situation=situation) results[state] = { "state_income_tax": sim.calculate("state_income_tax", 2024)[0], "total_tax": sim.calculate("household_tax", 2024)[0] } ``` ## Helper Scripts This skill includes helper scripts in the `scripts/` directory: ```python from policyengine_skills.situation_helpers import ( create_single_filer, create_married_couple, create_family_with_children, add_itemized_deductions ) # Quick situation creation situation = create_single_filer( income=50000, state="CA", age=30 ) # Add deductions situation = add_itemized_deductions( situation, charitable_donations=5000, mortgage_interest=10000, real_estate_taxes=8000 ) ``` ## Common Pitfalls and Solutions ### Pitfall 1: Member Lists Out of Sync **Problem:** Different entities have different members ```python # WRONG "tax_units": {"tax_unit": {"members": ["parent"]}}, "households": {"household": {"members": ["parent", "child"]}} ``` **Solution:** Keep all entity member lists consistent: ```python # CORRECT all_members = ["parent", "child"] "families": {"family": {"members": all_members}}, "tax_units": {"tax_unit": {"members": all_members}}, "households": {"household": {"members": all_members}} ``` ### Pitfall 2: Forgetting Year Keys **Problem:** `"age": 35` instead of `"age": {2024: 35}` **Solution:** Always use year dictionary: ```python "age": {2024: 35}, "employment_income": {2024: 50000} ``` ### Pitfall 3: Net Taxes vs Gross Taxes **Problem:** Forgetting to subtract benefits from taxes **Solution:** Use proper calculation: ```python # Net taxes (what household actually pays) net_tax = sim.calculate("household_tax", 2024) - \ sim.calculate("household_benefits", 2024) ``` ### Pitfall 4: Axes Persistence **Problem:** Axes remain in situation when creating single-point simulation **Solution:** Remove axes before single-point simulation: ```python situation_single = situation.copy() situation_single.pop("axes", None) ``` ### Pitfall 5: State-Specific Variables **Problem:** Using NYC-specific variables without `in_nyc: True` **Solution:** Set NYC flag for NY residents in NYC: ```python "households": { "household": { "state_name": {2024: "NY"}, "in_nyc": {2024: True} # Required for NYC taxes } } ``` ## NYC Handling For New York City residents: ```python situation = { # ... people setup ... "households": { "household": { "members": ["person"], "state_name": {2024: "NY"}, "in_nyc": {2024: True} # Enable NYC tax calculations } } } ``` ## Version Compatibility - Always use `policyengine-us>=1.155.0` for 2024 calculations - Check version: `import policyengine_us; print(policyengine_us.__version__)` - Different years may require different package versions ## Debugging Tips 1. **Enable tracing:** ```python simulation.trace = True result = simulation.calculate("variable_name", 2024) ``` 2. **Check intermediate calculations:** ```python agi = simulation.calculate("adjusted_gross_income", 2024) taxable_income = simulation.calculate("taxable_income", 2024) ``` 3. **Verify situation structure:** ```python import json print(json.dumps(situation, indent=2)) ``` 4. **Test with PolicyEngine web app:** - Go to policyengine.org/us/household - Enter same inputs - Compare results ## Additional Resources - **Documentation:** https://policyengine.org/us/docs - **API Reference:** https://github.com/PolicyEngine/policyengine-us - **Example Notebooks:** https://github.com/PolicyEngine/analysis-notebooks - **Variable Explorer:** https://policyengine.org/us/variables ## Examples Directory See `examples/` for complete working examples: - `single_filer.yaml` - Single person household - `married_couple.yaml` - Married filing jointly - `family_with_children.yaml` - Family with dependents - `itemized_deductions.yaml` - Using itemized deductions - `donation_sweep.yaml` - Analyzing donation impacts with axes