Skip to content

Commit c884da6

Browse files
committed
Use SSA actual SSI payments target
1 parent e019dce commit c884da6

6 files changed

Lines changed: 73 additions & 11 deletions

File tree

policyengine_us_data/calibration/chunked_matrix_assembler.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,9 @@ def run_single_chunk(self, chunk_id: int) -> ChunkResult:
380380
continue
381381
try:
382382
hh_vars[variable] = chunk_sim.calculate(
383-
variable, state.time_period, map_to="household"
383+
variable,
384+
state.time_period,
385+
map_to="household",
384386
).values.astype(np.float32)
385387
except Exception as exc:
386388
logger.warning(
@@ -394,7 +396,9 @@ def run_single_chunk(self, chunk_id: int) -> ChunkResult:
394396
continue
395397
try:
396398
target_entity_vars[variable] = chunk_sim.calculate(
397-
variable, state.time_period, map_to=entity_key
399+
variable,
400+
state.time_period,
401+
map_to=entity_key,
398402
).values.astype(np.float32)
399403
except Exception as exc:
400404
logger.warning(

policyengine_us_data/db/etl_national_targets.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
SSI_RECIPIENT_TARGET_SOURCE,
3333
SSI_RECIPIENT_TARGET_YEAR,
3434
SSI_RECIPIENT_TARGETS_2024,
35+
get_ssi_annual_payment_target,
3536
)
3637
from policyengine_us_data.utils.target_variables import (
3738
target_variable_components,
@@ -798,7 +799,13 @@ def extract_national_targets(year: int = DEFAULT_YEAR):
798799
source = "CBO Budget Projections"
799800
notes = f"CBO projection for {variable_name}"
800801
if variable_name == "ssi":
801-
source = SSI_CBO_TARGET_SOURCE
802+
ssi_target = get_ssi_annual_payment_target(time_period)
803+
if ssi_target is None:
804+
source = SSI_CBO_TARGET_SOURCE
805+
else:
806+
value = ssi_target["value"]
807+
source = ssi_target["source"]
808+
notes = ssi_target["notes"]
802809
cbo_targets.append(
803810
{
804811
"variable": variable_name,

policyengine_us_data/utils/loss.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from policyengine_us_data.utils.soi import pe_to_soi, get_soi, get_tracked_soi_row
2929
from policyengine_us_data.utils.ssi_targets import (
3030
SSI_RECIPIENT_TARGETS_2024,
31+
get_ssi_annual_payment_target,
3132
)
3233
from policyengine_us_data.utils.target_variables import (
3334
target_variable_components,
@@ -248,6 +249,11 @@ def _add_ssi_recipient_targets(loss_matrix, targets_array, sim, time_period):
248249

249250

250251
def _cbo_program_target_value(sim, variable_name: str, time_period):
252+
if variable_name == "ssi":
253+
ssi_target = get_ssi_annual_payment_target(time_period)
254+
if ssi_target is not None:
255+
return ssi_target["value"]
256+
251257
param_name = CBO_PARAM_NAME_MAP.get(variable_name, variable_name)
252258
return sim.tax_benefit_system.parameters(time_period).calibration.gov.cbo._children[
253259
param_name
@@ -1339,7 +1345,11 @@ def build_loss_matrix(dataset: type, time_period):
13391345

13401346
for variable_name in CBO_PROGRAMS:
13411347
label = f"nation/cbo/{variable_name}"
1342-
loss_matrix[label] = sim.calculate(variable_name, map_to="household").values
1348+
loss_matrix[label] = sim.calculate(
1349+
variable_name,
1350+
time_period,
1351+
map_to="household",
1352+
).values
13431353
if any(loss_matrix[label].isna()):
13441354
raise ValueError(f"Missing values for {label}")
13451355
targets_array.append(_cbo_program_target_value(sim, variable_name, time_period))

policyengine_us_data/utils/ssi_targets.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,39 @@
33
SSI_CBO_TARGET_SOURCE = (
44
"https://www.cbo.gov/system/files/2026-02/51313-2026-02-ssi.xlsx"
55
)
6+
SSI_ANNUAL_PAYMENT_TARGET_SOURCE = (
7+
"https://www.ssa.gov/policy/docs/statcomps/ssi_asr/2024/sect01.html"
8+
)
9+
SSI_OACT_PAYMENT_DATE_TARGET_SOURCE = (
10+
"https://www.ssa.gov/oact/ssir/SSI25/IV_C_Payments.html"
11+
)
12+
SSI_OACT_CY2024_PAYMENT_DATE_ALL = 63_080_000_000
13+
SSI_OACT_FY2024_PAYMENT_DATE_ALL = 57_600_000_000
14+
SSI_ANNUAL_PAYMENT_TARGET_NOTES = (
15+
"SSA SSI Annual Statistical Report, 2024, Table 2; Federal SSI total "
16+
"annual payments for all recipients, excluding federally administered "
17+
"state supplementation. ASR allocates payments to the month due, so this "
18+
"target aligns with annual `ssi` over January-December benefit months. "
19+
"Do not replace it with OACT payment-date accounting; OACT Table IV.C2 "
20+
"reports FY2024 all Federal SSI payments of $57.600B because fiscal-year "
21+
"payment-date totals can contain 11, 12, or 13 monthly payments. The "
22+
"smaller gap between ASR CY2024 and OACT FY2024 is not a pure 12-vs-11 "
23+
"month comparison: OACT Table IV.C1 reports CY2024 all Federal SSI "
24+
"payments of $63.080B on a payment-date basis, $5.480B above OACT "
25+
"FY2024, and OACT obligations are not reduced for certain recovered "
26+
"overpayments remitted directly to Treasury that ASR nets out."
27+
)
28+
SSI_ANNUAL_PAYMENT_TARGETS = {
29+
2024: {
30+
"value": 59_665_127_000,
31+
"source": SSI_ANNUAL_PAYMENT_TARGET_SOURCE,
32+
"notes": SSI_ANNUAL_PAYMENT_TARGET_NOTES,
33+
},
34+
}
35+
36+
37+
def get_ssi_annual_payment_target(year) -> dict | None:
38+
return SSI_ANNUAL_PAYMENT_TARGETS.get(int(str(year)[:4]))
639

740

841
SSI_RECIPIENT_TARGET_YEAR = 2024

tests/unit/calibration/test_loss_targets.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,10 +378,10 @@ def test_add_ssi_recipient_targets_adds_total_and_age_counts():
378378
)
379379

380380

381-
def test_legacy_cbo_ssi_target_uses_cbo_projection():
381+
def test_legacy_cbo_ssi_target_uses_ssa_actual_when_available():
382382
sim = _FakeCBOProgramTargetSimulation()
383383

384-
assert _cbo_program_target_value(sim, "ssi", 2024) == 57_000_000_000
384+
assert _cbo_program_target_value(sim, "ssi", 2024) == 59_665_127_000
385385
assert _cbo_program_target_value(sim, "snap", 2024) == 1_000.0
386386

387387

tests/unit/test_etl_national_targets.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
load_state_acs_rent_targets,
2121
)
2222
from policyengine_us_data.utils.ssi_targets import (
23-
SSI_CBO_TARGET_SOURCE,
23+
SSI_ANNUAL_PAYMENT_TARGET_SOURCE,
2424
SSI_RECIPIENT_TARGETS_2024,
2525
)
2626

@@ -442,7 +442,7 @@ def test_extract_national_targets_includes_ssi_count_targets():
442442
}
443443

444444

445-
def test_extract_national_targets_uses_ssi_cbo_target(monkeypatch):
445+
def test_extract_national_targets_uses_ssi_ssa_actual_when_available(monkeypatch):
446446
class FakeIncomeBySource:
447447
_children = {
448448
target["parameter"]: 0
@@ -488,9 +488,17 @@ class FakeTaxBenefitSystem:
488488
target for target in raw_targets["cbo_targets"] if target["variable"] == "ssi"
489489
)
490490

491-
assert ssi_target["value"] == 57_000_000_000
492-
assert ssi_target["source"] == SSI_CBO_TARGET_SOURCE
493-
assert ssi_target["notes"] == "CBO projection for ssi"
491+
assert ssi_target["value"] == 59_665_127_000
492+
assert ssi_target["source"] == SSI_ANNUAL_PAYMENT_TARGET_SOURCE
493+
assert "SSA SSI Annual Statistical Report, 2024, Table 2" in ssi_target["notes"]
494+
assert "month due" in ssi_target["notes"]
495+
assert "annual `ssi` over January-December benefit months" in ssi_target["notes"]
496+
assert "OACT Table IV.C2" in ssi_target["notes"]
497+
assert "$57.600B" in ssi_target["notes"]
498+
assert "OACT Table IV.C1" in ssi_target["notes"]
499+
assert "$63.080B" in ssi_target["notes"]
500+
assert "$5.480B above OACT FY2024" in ssi_target["notes"]
501+
assert "recovered overpayments" in ssi_target["notes"]
494502

495503

496504
def test_load_national_targets_uses_medicaid_enrolled_for_enrollment_counts(

0 commit comments

Comments
 (0)