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.
This commit is contained in:
@@ -77,7 +77,9 @@ class RuleYear(BaseModel):
|
||||
# reporting (not the reduced/OQR-penalty CF). Verified against each
|
||||
# year's Final Rule preamble and cross-checked against the empirical
|
||||
# payment_rate / relative_weight ratio in opps.addendum_b (CY2021+).
|
||||
# CY2020 uses the corrected $80.793 (the raw final rule stated $80.784).
|
||||
# CY2020 = 80.784, the as-published NFRM value that reproduces the CY2020
|
||||
# Addendum B national rates we ingest (verified to the cent). CMS later cited
|
||||
# a corrected $80.793, but the archived NFRM addenda — our source — use 80.784.
|
||||
|
||||
RULES: dict[int, RuleYear] = {
|
||||
2014: RuleYear(
|
||||
@@ -127,7 +129,7 @@ RULES: dict[int, RuleYear] = {
|
||||
),
|
||||
2020: RuleYear(
|
||||
year=2020,
|
||||
conversion_factor=80.793,
|
||||
conversion_factor=80.784,
|
||||
outlier_threshold=4625.0,
|
||||
cms_rule_id="CMS-1717-FC",
|
||||
federal_register_citation="84 FR 61142",
|
||||
|
||||
@@ -1,4 +1,39 @@
|
||||
hcpcs,status_indicator,relative_weight,payment_rate,year
|
||||
57170,T,0.1421,10.33,2014
|
||||
P9038,R,3.0182,219.34,2014
|
||||
28635,T,17.2302,1252.15,2014
|
||||
25151,T,35.4456,2575.9,2014
|
||||
33249,Q3,442.3292,32144.95,2014
|
||||
A9527,U,0.1787,13.25,2015
|
||||
74160,Q3,3.2481,240.83,2015
|
||||
23000,T,18.0849,1340.89,2015
|
||||
75833,Q2,34.5196,2559.42,2015
|
||||
33270,J1,415.4941,30806.39,2015
|
||||
A9527,U,0.0968,7.14,2016
|
||||
62252,S,3.2713,241.18,2016
|
||||
24071,T,19.1832,1414.28,2016
|
||||
27696,T,32.4936,2395.59,2016
|
||||
33249,J1,413.561,30489.78,2016
|
||||
C2645,U,0.0625,4.69,2017
|
||||
74262,Q3,3.532,264.9,2017
|
||||
17108,T,19.0286,1427.16,2017
|
||||
54620,J1,33.8861,2541.49,2017
|
||||
69930,J1,424.3083,31823.55,2017
|
||||
P9043,R,0.1957,15.39,2018
|
||||
67810,T,3.4036,267.65,2018
|
||||
14000,T,19.944,1568.32,2018
|
||||
93530,J1,35.7776,2813.41,2018
|
||||
C9741,J1,414.903,32626.31,2018
|
||||
C2645,U,0.059,4.69,2019
|
||||
67938,T,3.5667,283.52,2019
|
||||
15760,T,19.4862,1548.96,2019
|
||||
52250,J1,36.8205,2926.86,2019
|
||||
38240,J1,476.6985,37892.76,2019
|
||||
C2645,U,0.0581,4.69,2020
|
||||
59070,T,3.3508,270.69,2020
|
||||
C5273,T,20.0852,1622.56,2020
|
||||
38525,J1,37.4977,3029.21,2020
|
||||
38240,J1,463.3555,37431.71,2020
|
||||
C2645,U,0.0566,4.69,2021
|
||||
37195,T,3.7532,310.75,2021
|
||||
51040,J1,21.6552,1792.99,2021
|
||||
|
||||
|
@@ -37,15 +37,16 @@ _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:
|
||||
# CY2014-CY2020 — each year's Federal Register OPPS/ASC Final Rule
|
||||
# preamble ("we are using a conversion factor of $X").
|
||||
# CY2021-CY2026 — empirical payment_rate / relative_weight in
|
||||
# opps.addendum_b (5,000+ APC-priced rows/year), which
|
||||
# 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.793 is the corrected value; the final rule as published
|
||||
# stated 80.784 and CMS later corrected it (the CY2021 rule
|
||||
# builds off 80.793).
|
||||
# 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] = {
|
||||
@@ -55,7 +56,7 @@ _EXPECTED_CF: dict[int, float] = {
|
||||
2017: 75.001,
|
||||
2018: 78.636,
|
||||
2019: 79.490,
|
||||
2020: 80.793,
|
||||
2020: 80.784,
|
||||
2021: 82.797,
|
||||
2022: 84.177,
|
||||
2023: 85.585,
|
||||
@@ -98,8 +99,8 @@ class TestAddendumBFixtureConsistency:
|
||||
Addendum B rows.
|
||||
|
||||
The fixture holds real published ``payment_rate`` values (never
|
||||
computed), spanning APC weights from ~0.05 to ~700 across CY2021-
|
||||
CY2026. If any of those years' conversion factors is wrong, the
|
||||
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.
|
||||
@@ -119,7 +120,7 @@ class TestAddendumBFixtureConsistency:
|
||||
)
|
||||
pricer = OppsPricer()
|
||||
years = pricer.years_available(con)
|
||||
assert years == [2021, 2022, 2023, 2024, 2025, 2026]
|
||||
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"
|
||||
|
||||
Reference in New Issue
Block a user