Metadata-Version: 2.4
Name: spm-calculator
Version: 1.0.0
Summary: Calculate SPM (Supplemental Poverty Measure) thresholds for any US geography and year
Author-email: PolicyEngine <hello@policyengine.org>
License-Expression: MIT
Project-URL: Homepage, https://spm-calculator.vercel.app/
Project-URL: Documentation, https://github.com/PolicyEngine/spm-calculator/tree/main/docs
Project-URL: Repository, https://github.com/PolicyEngine/spm-calculator
Project-URL: Issues, https://github.com/PolicyEngine/spm-calculator/issues
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pandas>=2.0
Requires-Dist: numpy>=1.24
Requires-Dist: requests>=2.28
Requires-Dist: census>=0.8
Requires-Dist: us>=3.0
Requires-Dist: openpyxl>=3.1.5
Provides-Extra: ce
Requires-Dist: curl-cffi>=0.7; extra == "ce"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: ruff==0.15.0; extra == "dev"
Dynamic: license-file

# spm-calculator

Calculate Supplemental Poverty Measure (SPM) thresholds with published national
inputs and conditional CE/ACS rolling forecasts. The package works offline for
standalone calculations and supplies the same forecast artifact to optional
PolicyEngine, Microcosm Frame and actual Axiom core integrations.

This checkout is the **local 1.0.0 candidate**. These instructions describe this
source, not an announced PyPI release or production website, wrapper or API
promotion.

Version 1.0 changes the public calculation API and removes the legacy modules.
Existing PolicyEngine environments require coordinated dependency pins; read
the [1.0 migration guide](docs/migration.md) before upgrading.

## Published 2025 inputs

The national reference family has two SPM adults and two children. The bundled
2025 thresholds and tenure-specific housing shares come from the BLS workbooks:

| Tenure | Annual national threshold, USD | Housing share |
| --- | ---: | ---: |
| Owner with mortgage | 41,322.707394 | 0.4285074824 |
| Owner without mortgage | 34,325.997720 | 0.3120194707 |
| Renter | 41,700.555713 | 0.4336857704 |

The [BLS housing-share workbook](spm_calculator/data/current/bls_spm_shares.xlsx)
supplies the shelter-plus-utilities fractions. The [published-cell receipt](spm_calculator/data/current/bls_published_cell_receipt.json)
links threshold cells to the source workbooks and rounded BLS page values.
The [source and validation guide](docs/validation.md) distinguishes these
published values from replicated or projected amounts. A published national
base does not make a local 2025 estimate an official Census threshold: the
selected area's rent input can be modeled.

## Install this candidate locally

From this checkout, using Python 3.9 or newer:

```sh
python -m pip install -e .
```

A calculation needs no Census API key or source download. Optional integrations
require their own runtime installations; see the linked guides below.

## Calculate a threshold

```python
from spm_calculator import SPMUnit, load_forecast

forecast = load_forecast()
result = forecast.calculate_unit(
    SPMUnit(
        unit_id="example-family",
        num_adults=2,
        num_children=2,
        tenure="renter",
        year=2025,
        geography_kind="national",
        resources=40_000,
    )
)
print(f"Threshold: ${result['threshold']:,.2f}")  # $41,700.56
print(result["is_in_poverty"])  # True
print(forecast.forecast_id, forecast.content_sha256)
```

Here `resources` means already measured annual SPM resources, not gross income.
Omit it when only a threshold is needed. `SPMUnit` accepts already classified
counts. In person-based integrations, an adult is a person aged at least 18,
or aged at least 15 with an explicit SPM independence role. Native SPM membership
and source roles determine those counts; household size alone does not.

For a county, resolve its assignment for the target year, then calculate with
that SPM estimation area:

```python
from spm_calculator import SPMUnit, load_forecast

forecast = load_forecast()
assignment = forecast.resolve_county(
    2026, "06037", county_vintage="2020", scenario="ce_trend"
)
result = forecast.calculate_unit(
    SPMUnit(
        "example-family", 2, 2, "renter", 2026,
        geography_kind=assignment["kind"],
        geography_id=assignment["area_id"],
    ),
    scenario="ce_trend",
)
print(result["threshold"], result["national_status"])
print(result["provenance"]["geography"])
```

County is an assignment input, not an estimation unit. Use
`forecast.areas_for_year(year, scenario=...)` to list that year's supported
areas and their statuses. `metro` is the API kind for named MSAs, state residual
metro/nonmetro areas and explicitly modeled residual areas; inspect `area_type`
and `official_published_area` rather than inferring official status from the
kind. National calculations are an explicit location choice. Unknown locations,
years and scenarios raise errors.

## Conditional 2026–2035 forecasts

The default schema-2 artifact covers 2022–2035. It preserves published national
values through 2025 and projects 2026–2035 using moving five-year Consumer
Expenditure Survey and American Community Survey windows. `ce_trend` is the
default real-spending scenario; `zero_real` provides zero real-spending growth.
The artifact records price assumptions, their source vintage, housing shares,
rent indices, source windows and diagnostics separately for each selected year.

These are conditional research estimates. Public-use rent allocation,
unresolved CE sample policies, fixed future donors and weights, and unestimated
forecast uncertainty limit interpretation. Relative rent indices stabilize from
2029 under the baseline donor and price assumptions even as windows advance;
this is not evidence of persistent local growth differences. Read the
[rolling forecast methods and validation limits](docs/rolling-forecasts.md)
before comparing scenarios or historical geography series breaks.

## Command line

After local installation:

```sh
spm-calculator info
spm-calculator verify
spm-calculator calculate --year 2025 --adults 2 --children 2 --tenure renter --national
spm-calculator --scenario ce_trend calculate --year 2026 --adults 2 --children 2 --county 06037
spm-calculator areas --year 2035
spm-calculator --scenario zero_real export --format csv
```

Global options (`--forecast`, `--expect-sha256`, `--as-of`, `--scenario`) precede
the subcommand. Retain a reviewed content digest and supply it on replay; the
reader does not obtain a newer artifact over the network. See the
[quickstart](docs/quickstart.md) and [artifact contract](docs/spm-releases.md).

## Integrations and local app

- [PolicyEngine](docs/policyengine-release-integration.md): the accompanying
  country candidate reads forecast configuration by default and retains its
  tax, benefit and resource formulas. Wrapper/API production adoption is not
  published by this documentation.
- [Microcosm Frame](docs/microcosm-integration.md): preserve native membership
  and typed weights, attach canonical results and summarize with Frame operations.
- [Axiom core](docs/axiom-integration.md): execute person classification,
  native unit counts, bounded canonical scale lookup and threshold/housing/poverty
  arithmetic in real core. The dense Microcosm AxiomEngine does not support this
  bridge; exact decimal poverty boundaries can differ from Python float results.

Run the browser candidate locally from `web` with `bun install --frozen-lockfile`
and `bun run dev`. Its export consumes the canonical artifact. A local build
or this README does not establish production deployment.

## Sources and research history

- [Validation](docs/validation.md): published BLS cells and shares, Census
  geography anchors, forecast comparisons and reproducible checks.
- [Methodology](docs/methodology.md): threshold, housing and equivalence formulas.
- [Current CE replication experiment](docs/current-ce-replication.md): source
  policies, measured replication differences and unresolved approximations.
- [2026 BLS correction and frozen experiments](docs/bls-2026-correction.md):
  historical publication vintages and the immutable 2025 forecast commitment.
- [API reference](docs/api.md): current calculation and membership interfaces.

[MIT license](LICENSE).
