|
1 | 1 | """Shared SSI calibration targets.""" |
2 | 2 |
|
3 | | -from datetime import date, timedelta |
4 | | - |
5 | 3 | SSI_CBO_TARGET_SOURCE = ( |
6 | 4 | "https://www.cbo.gov/system/files/2026-02/51313-2026-02-ssi.xlsx" |
7 | 5 | ) |
8 | | -SSI_PAYMENT_TIMING_SOURCE = "https://www.ssa.gov/oact/ssir/SSI24/IV_C_Payments.html" |
9 | | -SSI_PAYMENT_RULE_SOURCE = "https://www.ssa.gov/OP_Home/cfr20/416/416-0502.htm" |
10 | | -SSI_PAYMENT_TARGET_SOURCE = ( |
11 | | - f"{SSI_CBO_TARGET_SOURCE}; {SSI_PAYMENT_TIMING_SOURCE}; {SSI_PAYMENT_RULE_SOURCE}" |
12 | | -) |
13 | | - |
14 | | - |
15 | | -def _as_fiscal_year(year) -> int: |
16 | | - return int(str(year)[:4]) |
17 | | - |
18 | | - |
19 | | -def _is_new_years_day_observed(day: date) -> bool: |
20 | | - new_years_day = date(day.year, 1, 1) |
21 | | - next_new_years_day = date(day.year + 1, 1, 1) |
22 | | - return ( |
23 | | - day == new_years_day |
24 | | - or (new_years_day.weekday() == 6 and day == date(day.year, 1, 2)) |
25 | | - or (next_new_years_day.weekday() == 5 and day == date(day.year, 12, 31)) |
26 | | - ) |
27 | | - |
28 | | - |
29 | | -def _is_labor_day(day: date) -> bool: |
30 | | - return day.month == 9 and day.weekday() == 0 and day.day <= 7 |
31 | | - |
32 | | - |
33 | | -def _is_federal_holiday_affecting_ssi_payment(day: date) -> bool: |
34 | | - return _is_new_years_day_observed(day) or _is_labor_day(day) |
35 | | - |
36 | | - |
37 | | -def _ssi_payment_date(year: int, month: int) -> date: |
38 | | - payment_date = date(year, month, 1) |
39 | | - while payment_date.weekday() >= 5 or _is_federal_holiday_affecting_ssi_payment( |
40 | | - payment_date |
41 | | - ): |
42 | | - payment_date -= timedelta(days=1) |
43 | | - return payment_date |
44 | | - |
45 | | - |
46 | | -def _ssi_fiscal_year_benefit_months(year) -> list[date]: |
47 | | - fiscal_year = _as_fiscal_year(year) |
48 | | - fiscal_year_start = date(fiscal_year - 1, 10, 1) |
49 | | - fiscal_year_end = date(fiscal_year, 9, 30) |
50 | | - |
51 | | - benefit_months = [] |
52 | | - for calendar_year in (fiscal_year - 1, fiscal_year): |
53 | | - for month in range(1, 13): |
54 | | - payment_day = _ssi_payment_date(calendar_year, month) |
55 | | - if fiscal_year_start <= payment_day <= fiscal_year_end: |
56 | | - benefit_months.append(date(calendar_year, month, 1)) |
57 | | - return benefit_months |
58 | | - |
59 | | - |
60 | | -def get_ssi_fiscal_year_payment_count(year) -> int: |
61 | | - """Return SSI benefit months with payment dates in the federal fiscal year.""" |
62 | | - return len(_ssi_fiscal_year_benefit_months(year)) |
63 | | - |
64 | | - |
65 | | -def get_ssi_single_year_available_payment_count(year) -> int: |
66 | | - """Return fiscal-year SSI benefit months available from a single-year H5.""" |
67 | | - fiscal_year = _as_fiscal_year(year) |
68 | | - return sum( |
69 | | - benefit_month.year == fiscal_year |
70 | | - for benefit_month in _ssi_fiscal_year_benefit_months(year) |
71 | | - ) |
72 | | - |
73 | | - |
74 | | -def scale_ssi_fiscal_year_target_for_single_year_data(value, year) -> float: |
75 | | - """Scale full fiscal-year SSI outlays to months computable from one H5 year.""" |
76 | | - return ( |
77 | | - float(value) |
78 | | - * get_ssi_single_year_available_payment_count(year) |
79 | | - / get_ssi_fiscal_year_payment_count(year) |
80 | | - ) |
81 | | - |
82 | | - |
83 | | -def get_ssi_payment_target_notes(year) -> str: |
84 | | - fiscal_year = _as_fiscal_year(year) |
85 | | - available_count = get_ssi_single_year_available_payment_count(year) |
86 | | - payment_count = get_ssi_fiscal_year_payment_count(year) |
87 | | - return ( |
88 | | - "CBO SSI federal fiscal-year outlays scaled to the benefit months " |
89 | | - "computable from a single-year PolicyEngine-US-data H5 using " |
90 | | - "policyengine-us ssi_federal_fiscal_year_outlays; " |
91 | | - f"FY{fiscal_year} has {payment_count} SSI benefit months paid in the " |
92 | | - f"federal fiscal year, of which {available_count} are benefit months " |
93 | | - f"in calendar year {fiscal_year}" |
94 | | - ) |
95 | 6 |
|
96 | 7 |
|
97 | 8 | SSI_RECIPIENT_TARGET_YEAR = 2024 |
|
0 commit comments