Skip to content
This repository was archived by the owner on May 13, 2026. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ Thumbs.db

# Data/cache
.cache/
!aca_calc/data/
!aca_calc/data/*.json
!src/data/
!src/data/**
# data/ is gitignored except for the stub fixtures committed for build/CI.
data/*
!data/households
Expand All @@ -68,4 +72,4 @@ next-env.d.ts
.vercel

# Env
.env*.local
.env*.local
13 changes: 0 additions & 13 deletions .streamlit/config.toml

This file was deleted.

135 changes: 81 additions & 54 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,66 @@

## Code Structure

### Main Application (`app.py`)
### React Application

**Key Functions:**
The user-facing ACA calculator lives in the Next.js/React app:

1. **`calculate_ptc()`** - Core calculation logic
- Builds household situation dictionary
- Applies reform parameters if requested
- Returns PTC and SLCSP values
- County format: "Travis County" → "TRAVIS_COUNTY_TX"
- `app/`: Next.js shell
- `src/App.jsx`: top-level application routing and tabs
- `src/components/Calculator.jsx`: calculator orchestration
- `src/components/CalculatorForm.jsx`: household input form
- `src/components/CalculatorResults.jsx`: calculator outputs and charts
- `src/views/LocalImpact.jsx`: local enrollment and premium context

2. **`create_chart()`** - Visualization
- Generates income sweep curves
- Shows user's position on curves
- Compares baseline vs reform scenarios
Run it locally with:

3. **`main()`** - Streamlit UI
- Handles user inputs
- Displays results
- Manages session state
```bash
npm run dev
```

The calculator route is `/#calculator`.

### Python Package

Reusable PolicyEngine and data access logic lives in `aca_calc/`:

1. `aca_calc/calculations/ptc.py`
- Builds household situations
- Applies ACA reform parameters when requested
- Returns PTC, SLCSP, FPL, and FPL percentage values

2. `aca_calc/calculations/household.py`
- Builds PolicyEngine household dictionaries
- Handles spouse, dependent, county, ZIP, and income-axis structure

3. `aca_calc/enrollment_context.py`
- Loads checked-in CMS Marketplace enrollment fixtures
- Labels HealthCare.gov-platform states versus fallback-only states
- Provides county and congressional district local context

### Data Files

- **`counties.json`**: 3,143 counties across all 50 states + DC
- **`process_counties.py`**: Updates county data from PolicyEngine
- `counties.json`: counties across all states plus DC
- `aca_calc/data/enrollment_context_2026_counties.json`: tiny county fixture
- `aca_calc/data/enrollment_context_2026_districts.json`: tiny district fixture
- `aca_calc/data/marketplace_platforms_2026.json`: state Marketplace platform config
- `process_counties.py`: updates county data from PolicyEngine

## Testing

```bash
# Quick verification test
python tests/test_reform_verification.py
npm run lint
npm run build
uv run pytest
```

# Comprehensive tests
python tests/test_app_comprehensive.py
For local impact work, the focused Python tests are:

# State-specific tests
python tests/test_texas.py
python tests/test_nj.py
```bash
uv run pytest \
tests/test_enrollment_context.py \
tests/test_enrollment_ingest.py \
tests/test_congressional_district_ingest.py
```

## PolicyEngine Integration
Expand All @@ -49,70 +72,74 @@ python tests/test_nj.py
situation = {
"people": {...},
"families": {...},
"spm_units": {...}, # Required!
"spm_units": {...},
"tax_units": {...},
"households": {...},
"marital_units": {...} # If married/partnered
"marital_units": {...},
}
```

**Important**: Always include `spm_units` for accurate ACA calculations.
Always include `spm_units` for accurate ACA calculations. Add
`marital_units` when the household includes a spouse or child dependents.

### Reform Parameters

IRA enhancements modify these PolicyEngine parameters:

```python
"gov.aca.ptc_phase_out_rate[0-6].amount" # Contribution percentages
"gov.aca.ptc_income_eligibility[2].amount" # Remove 400% FPL cap
"gov.aca.ptc_phase_out_rate[0-6].amount"
"gov.aca.ptc_income_eligibility[2].amount"
```

### County Format

PolicyEngine expects: `COUNTY_NAME_STATE`
- Examples: `TRAVIS_COUNTY_TX`, `BERGEN_COUNTY_NJ`
- All caps, underscores instead of spaces
- State abbreviation suffix
PolicyEngine expects `COUNTY_NAME_STATE`:

- `TRAVIS_COUNTY_TX`
- `BERGEN_COUNTY_NJ`

Use all caps, underscores instead of spaces, and a state abbreviation suffix.

## Common Issues

### SLCSP Returns $0

- Check county name format
- Verify state has marketplace data
- Try without county (uses state default)
- Verify state has Marketplace pricing data
- Try without county to use the state default

### Reform Not Applied
- Ensure `use_reform=True` parameter
- Check Reform.from_dict() imports correctly
- Verify date format: "2026-01-01.2100-12-31"

### Calculations Don't Match Notebook
- Ensure `use_reform=True`
- Check `Reform.from_dict()` imports correctly
- Verify date ranges use the expected PolicyEngine parameter format

### Calculations Do Not Match Notebook Values

- Check PolicyEngine version
- Verify household structure matches
- Confirm income is split correctly for couples

## Adding Features

### New State-Specific Logic
1. Add to `calculate_ptc()` function
2. Test with multiple counties in that state
3. Compare against PolicyEngine web app

1. Add reusable logic under `aca_calc/`.
2. Wire UI behavior through React components in `src/`.
3. Test with multiple counties or districts in that state.

### UI Changes
1. Modify `main()` function
2. Update session state handling
3. Test with various household types

### New Visualizations
1. Add to or modify `create_chart()`
2. Use Plotly for consistency
3. Include hover tooltips
1. Keep navigation in `src/App.jsx`.
2. Keep calculator state in the calculator components.
3. Match existing component and CSS conventions.

## Performance Tips
### New Visualizations

- Use `@st.cache_data` for expensive operations
- Load counties.json once at startup
- Minimize redundant PolicyEngine simulations
1. Prefer existing Recharts/D3 patterns.
2. Keep chart data preparation separate from visual rendering.
3. Include labels and hover states that work on desktop and mobile.

## Questions?

Check PolicyEngine docs: https://policyengine.github.io/policyengine-us/
Check PolicyEngine docs: https://policyengine.github.io/policyengine-us/
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ format:
@echo "Formatting complete"

debug:
uv run streamlit run app.py
npm run dev

clean:
rm -rf __pycache__ .pytest_cache .coverage htmlcov
Expand Down
98 changes: 61 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,54 @@
# ACA Premium Tax Credit Calculator

Compare 2026 Premium Tax Credits with and without Inflation Reduction Act (IRA) enhancements.
Compare 2026 Premium Tax Credits with and without Inflation Reduction Act
(IRA) enhancements, and pair household impacts with local Marketplace
enrollment context.

**🔗 [Try the Calculator](https://policyengine-aca-calc.streamlit.app/)**
**Try the calculator:** https://www.policyengine.org/us/aca-calc#calculator

## Overview

The Inflation Reduction Act enhanced ACA subsidies through 2025. This calculator shows what your credits would be in 2026 with and without extending these enhancements.
The Inflation Reduction Act enhanced ACA subsidies through 2025. This
calculator shows what household credits would be in 2026 with and without
extending those enhancements.

**Key Differences:**
- **With IRA Extension**: No income cap, lower premium contributions (0-8.5% of income)
- **After IRA Expires**: 400% FPL cap ("subsidy cliff"), higher contributions (2-9.5% of income)
Key differences:

## Quick Start

### Use the Live App
- **With IRA extension:** no income cap, lower premium contributions
(0-8.5% of income)
- **After IRA expires:** 400% FPL cap ("subsidy cliff"), higher contributions
(2-9.5% of income)
- **Local impact:** Marketplace enrollment context for HealthCare.gov-platform
geographies where fine-grained CMS PUF data are available

Visit **[https://policyengine-aca-calc.streamlit.app/](https://policyengine-aca-calc.streamlit.app/)** to use the calculator immediately.
## Quick Start

### Run Locally

```bash
# Install dependencies
pip install -r requirements.txt

# Run the app
streamlit run app.py
npm install
npm run dev
```

The app will open at http://localhost:8501
The React app runs at http://localhost:3000. The calculator is available at
http://localhost:3000/#calculator.

Python tests and data utilities use the Python package in `aca_calc/`:

```bash
uv run pytest
```

## Features

- ✅ **All 50 States + DC**: Accurate calculations for every jurisdiction
- ✅ **3,143 Counties**: County-specific marketplace pricing
- ✅ **Real-time Comparison**: Side-by-side baseline vs. IRA extension
- ✅ **Interactive Charts**: See how credits change across income levels
- ✅ **Household Flexibility**: Single, married, with/without dependents
- All 50 states plus DC
- County-specific ACA pricing inputs
- Interactive household calculator for baseline, IRA extension, and additional
reform scenarios
- Local impact page with county and congressional district Marketplace
enrollment context
- Tiny checked-in CMS-style enrollment fixtures, structured for later ingestion
of processed full PUF files

## Example Results

Expand All @@ -50,32 +62,44 @@ The app will open at http://localhost:8501
## Technical Details

Built with:
- **[PolicyEngine US](https://policyengine.org)**: Open-source tax-benefit microsimulation
- **[Streamlit](https://streamlit.io)**: Interactive web interface
- **[Plotly](https://plotly.com)**: Data visualization

County data sourced from PolicyEngine's ACA rating areas database.
- **Next.js + React:** interactive web application
- **PolicyEngine US:** open-source tax-benefit microsimulation
- **Recharts + D3:** data visualization
- **Python utilities:** enrollment fixture loaders and ingest helpers

County data are sourced from PolicyEngine's ACA rating area data. Enrollment
context starts with small checked-in fixtures under `aca_calc/data/` and can be
repointed to processed CMS Marketplace PUF files later.

## Project Structure

```
```text
.
├── app.py # Main Streamlit application
├── counties.json # County data for all states
├── process_counties.py # County data processor
├── requirements.txt # Python dependencies
├── tests/ # Test files
├── notebooks/ # Analysis notebooks
└── archive/ # Historical files
├── app/ # Next.js app shell
├── src/ # React UI, pages, and client-side helpers
│ ├── components/ # Calculator, charts, and shared components
│ └── views/LocalImpact.jsx # Local impact view
├── aca_calc/ # Python calculation and data-access helpers
│ ├── calculations/ # PolicyEngine household/PTC utilities
│ └── data/ # Small checked-in enrollment fixtures
├── tests/ # Python unit tests
├── package.json # React/Next scripts
├── pyproject.toml # Python package/dependencies
└── requirements.txt # Python runtime dependencies
```

## Development

```bash
# Run tests
python tests/test_reform_verification.py
npm run lint
npm run build
uv run pytest
```

To update county data:

# Update county data
```bash
python process_counties.py
```

Expand All @@ -85,4 +109,4 @@ Open source - see PolicyEngine US license for underlying calculations.

## Credits

Calculations powered by [PolicyEngine US](https://github.com/PolicyEngine/policyengine-us)
Calculations powered by [PolicyEngine US](https://github.com/PolicyEngine/policyengine-us).
Loading
Loading