Files
stack/tests/opps/test_rules.py
kert a9e5d58601 fix(opps): CY2020 CF→80.784 (NFRM) + verify all 13 years vs Addendum B
With CY2014-2020 Addendum B now ingested, every year's conversion factor
is cross-checked against CMS's own published rates (weight × CF vs
payment_rate) — all 13 reconcile 100% exact, independently confirming the
Federal-Register CFs for 2014-2020.

One correction fell out: CY2020 = 80.784 (not 80.793). The archived
addenda are the NFRM (as-published) version, whose national rates were
computed with the as-published 80.784; CMS later cited a corrected
80.793, but our source data uses 80.784, so that is the value that
reproduces it to the cent. Update the rule, the golden pin, and the note.

Extend the CI fixture (tests/opps/fixtures/addendum_b_sample.csv) from
CY2021-2026 to all 13 years — 5 real rows per year spanning APC weights
~0.05 to ~700 — so the in-CI correctness proof now covers every year.
2026-07-08 14:52:17 -04:00

162 lines
6.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Golden + self-consistency guards for opps.rules conversion factors.
The OPPS conversion factor per year is correctness-critical reference
data: OppsPricer computes national APC rates as ``weight × CF`` and
reconciles them against CMS's published Addendum B. Three guards keep
it bulletproof:
1. ``TestGoldenConversionFactors`` pins every year's CF to the value
taken from that year's Federal Register OPPS Final Rule (CY2014-
CY2020) and cross-checked against the empirical
``payment_rate / relative_weight`` ratio in Addendum B (CY2021-
CY2026). Runs everywhere (no data needed), so any accidental edit
fails CI. Changing a value requires updating the citation below too.
2. ``TestAddendumBFixtureConsistency`` reconciles OppsPricer against a
committed slice of *real* Addendum B rows (fixtures/addendum_b_
sample.csv — real published payment_rate, not computed). It runs in
CI with no external data, and because the rows are real a wrong CF
fails here — the independent correctness proof, enforced in CI.
3. ``TestAddendumBSelfConsistency`` (skipped when the aco DuckDB is
absent, e.g. headless CI) does the same against the full loaded
Addendum B — broader coverage where the data is present.
"""
from __future__ import annotations
from pathlib import Path
import pytest
from conf import path
from opps.rules import RULES
_FIXTURE = Path(__file__).parent / "fixtures" / "addendum_b_sample.csv"
# Full OPPS conversion factor — the rate for hospitals that MEET quality
# reporting (not the reduced/OQR-penalty CF).
#
# Sources (every year cross-checked BOTH ways):
# Federal Register — each year's OPPS/ASC Final Rule preamble ("we are
# using a conversion factor of $X"), primary for CY2014-2020.
# Empirical — payment_rate / relative_weight in opps.addendum_b (all 13
# years now ingested, 5,000+ APC-priced rows/year), which
# reproduces the published national rate to the cent.
# CY2020 = 80.784, the as-published NFRM value that reproduces the CY2020
# Addendum B we ingest (the archived NFRM addenda are our source).
# CMS later cited a corrected 80.793; we track the value that
# matches our data.
# CY2016 is genuinely below CY2015 — a one-time -2.0pp packaged-lab
# ("two-times") adjustment more than offset the market basket.
_EXPECTED_CF: dict[int, float] = {
2014: 72.672,
2015: 74.144,
2016: 73.725,
2017: 75.001,
2018: 78.636,
2019: 79.490,
2020: 80.784,
2021: 82.797,
2022: 84.177,
2023: 85.585,
2024: 87.382,
2025: 89.169,
2026: 91.415,
}
_HAS_ACO_DB = path("db.aco").exists()
class TestGoldenConversionFactors:
"""CI-runnable pin — guards against accidental CF edits."""
def test_all_years_present(self) -> None:
assert set(RULES) == set(_EXPECTED_CF)
@pytest.mark.parametrize("year", sorted(_EXPECTED_CF))
def test_cf_matches_published_value(self, year: int) -> None:
assert RULES[year].conversion_factor == _EXPECTED_CF[year], (
f"CY{year} OPPS conversion factor changed. If this is a real "
f"correction, update _EXPECTED_CF with a Federal Register / "
f"Addendum B citation — do not silently override it."
)
def test_monotonic_except_2016(self) -> None:
"""CFs rise year over year, except the deliberate CY2016 dip."""
years = sorted(_EXPECTED_CF)
for prev, cur in zip(years, years[1:]):
prev_cf = RULES[prev].conversion_factor
cur_cf = RULES[cur].conversion_factor
if cur == 2016:
assert cur_cf < prev_cf
else:
assert cur_cf > prev_cf
class TestAddendumBFixtureConsistency:
"""CI-runnable correctness proof against a committed slice of real
Addendum B rows.
The fixture holds real published ``payment_rate`` values (never
computed), spanning APC weights from ~0.05 to ~700 across every year
CY2014-CY2026. If any of those years' conversion factors is wrong, the
calculated ``weight × CF`` diverges from the published rate and this
fails — no external dataset required, so the correctness check runs
in headless CI.
"""
def test_fixture_reconciles_to_the_cent(self) -> None:
import duckdb
from rec.engine import reconcile
from rec.pricers.opps import OppsPricer
con = duckdb.connect(":memory:")
con.execute("CREATE SCHEMA opps")
con.execute(
"CREATE TABLE opps.addendum_b AS SELECT * FROM read_csv_auto(?)",
[str(_FIXTURE)],
)
pricer = OppsPricer()
years = pricer.years_available(con)
assert years == list(range(2014, 2027))
for year in years:
r = reconcile(pricer, con, year)
assert r.matched_rows > 0, f"CY{year}: no fixture rows"
assert r.exact_matches == r.matched_rows, (
f"CY{year}: {r.matched_rows - r.exact_matches} of "
f"{r.matched_rows} real Addendum B rows do not match "
f"weight × CF to the cent — the CY{year} conversion "
f"factor is wrong."
)
@pytest.mark.skipif(not _HAS_ACO_DB, reason="data/aco.duckdb not present")
class TestAddendumBSelfConsistency:
"""Prove weight × CF reproduces CMS's published Addendum B rate.
Runs only where the aco DuckDB (with ``opps.addendum_b``) is present.
This is the independent check that the golden CFs are *correct*: if a
CF is wrong, the calculated national rate diverges from the published
``payment_rate`` and this fails.
"""
def test_reconciles_to_the_cent_for_all_loaded_years(self) -> None:
from conf import connect
from rec.engine import reconcile
from rec.pricers.opps import OppsPricer
con = connect.duckdb()
pricer = OppsPricer()
years = pricer.years_available(con)
assert years, "opps.addendum_b has no years overlapping RULES"
for year in years:
r = reconcile(pricer, con, year)
assert r.matched_rows > 0, f"CY{year}: no APC rows to reconcile"
assert r.exact_matches == r.matched_rows, (
f"CY{year}: {r.matched_rows - r.exact_matches} of "
f"{r.matched_rows} APC rows do not match weight × CF to the "
f"cent — the CY{year} conversion factor is wrong."
)