55
66from policyengine_us import Microsimulation
77
8- #H5_PATH = 'hf://policyengine/test/'
9- H5_PATH = ' /home/baogorek/devl/sep/policyengine-us-data/policyengine_us_data/datasets/cps/long_term/projected_datasets/'
8+ # H5_PATH = 'hf://policyengine/test/'
9+ H5_PATH = " /home/baogorek/devl/sep/policyengine-us-data/policyengine_us_data/datasets/cps/long_term/projected_datasets/"
1010
1111# 2027 --------------------------------------
12- sim = Microsimulation (dataset = H5_PATH + "2027.h5" )
12+ sim = Microsimulation (dataset = H5_PATH + "2027.h5" )
1313parameters = sim .tax_benefit_system .parameters
1414
1515## Total social security
16- assert sim .default_calculation_period == ' 2027'
17- ss_estimate_cost_b = sim .calculate ("social_security" ).sum () / 1E9
16+ assert sim .default_calculation_period == " 2027"
17+ ss_estimate_cost_b = sim .calculate ("social_security" ).sum () / 1e9
1818
1919### Trustees SingleYearTRTables_TR2025.xlsx, Tab VI.G10 (nominal dollars in billions)
2020### Intermediate scenario for row 69, for Intermediate Scenario, 2027, Cost is: $1,715 billion
2323
2424## Taxable Payroll for Social Security
2525taxible_estimate_b = (
26- sim .calculate ("taxable_earnings_for_social_security" ).sum () / 1E9
27- + sim .calculate ("social_security_taxable_self_employment_income" ).sum () / 1E9
26+ sim .calculate ("taxable_earnings_for_social_security" ).sum () / 1e9
27+ + sim .calculate ("social_security_taxable_self_employment_income" ).sum ()
28+ / 1e9
2829)
2930
3031### Trustees SingleYearTRTables_TR2025.xlsx, Tab VI.G6 (nominal dollars in billions)
4950
5051
5152# 2100 --------------------------------------
52- sim = Microsimulation (dataset = H5_PATH + "2100.h5" )
53+ sim = Microsimulation (dataset = H5_PATH + "2100.h5" )
5354parameters = sim .tax_benefit_system .parameters
5455
5556## Total social security
56- assert sim .default_calculation_period == ' 2100'
57- ss_estimate_cost_b = sim .calculate ("social_security" ).sum () / 1E9
57+ assert sim .default_calculation_period == " 2100"
58+ ss_estimate_cost_b = sim .calculate ("social_security" ).sum () / 1e9
5859
5960### Trustees SingleYearTRTables_TR2025.xlsx, Tab VI.G10 (nominal dollars in billions)
6061### Intermediate scenario for row 69, for Intermediate Scenario, 2100, Cost is: $34,432 billion
61- ss_trustees_cost_b = 34_432
62+ ss_trustees_cost_b = 34_432
6263# Rounding takes it off a bit. We calibrated to CPI ratio times 2025-dollar cost
63- assert np .allclose (ss_estimate_cost_b , ss_trustees_cost_b , rtol = .0001 )
64+ assert np .allclose (ss_estimate_cost_b , ss_trustees_cost_b , rtol = 0 .0001 )
6465
6566## Taxable Payroll for Social Security
6667taxible_estimate_b = (
67- sim .calculate ("taxable_earnings_for_social_security" ).sum () / 1E9
68- + sim .calculate ("social_security_taxable_self_employment_income" ).sum () / 1E9
68+ sim .calculate ("taxable_earnings_for_social_security" ).sum () / 1e9
69+ + sim .calculate ("social_security_taxable_self_employment_income" ).sum ()
70+ / 1e9
6971)
7072
7173### Trustees SingleYearTRTables_TR2025.xlsx, Tab VI.G6 (nominal dollars in billions)
8688### "Mid Year" CSV from https://www.ssa.gov/oact/HistEst/Population/2024/Population2024.html
8789### Row 16067, Col C, contains 5162540
8890ss_age6_pop = 5_162_540
89- assert np .allclose (ss_age6_pop , total_age6_est , atol = 1 )
91+ assert np .allclose (ss_age6_pop , total_age6_est , atol = 1 )
9092
9193# Taxation of benefits -------
9294# Trustees report stops at 2099 so project at current rate one year out, bring to billions
9395sim .default_calculation_period
94- hi_tob_trustees = 1761.5
95- hi_tob_estimate_b = sim .calculate ("tob_revenue_medicare_hi" , map_to = "household" ).sum () / 1E9
96+ hi_tob_trustees = 1761.5
97+ hi_tob_estimate_b = (
98+ sim .calculate ("tob_revenue_medicare_hi" , map_to = "household" ).sum () / 1e9
99+ )
96100hi_tob_estimate_b
97101
98- oasdi_tob_trustees = 2101.3
99- oasdi_tob_estimate_b = sim .calculate ("tob_revenue_oasdi" ).sum () / 1E9
102+ oasdi_tob_trustees = 2101.3
103+ oasdi_tob_estimate_b = sim .calculate ("tob_revenue_oasdi" ).sum () / 1e9
100104oasdi_tob_estimate_b
101105
102106
@@ -125,17 +129,14 @@ def create_h6_reform():
125129 "gov.irs.social_security.taxability.threshold.base.main.HEAD_OF_HOUSEHOLD" : {},
126130 "gov.irs.social_security.taxability.threshold.base.main.SURVIVING_SPOUSE" : {},
127131 "gov.irs.social_security.taxability.threshold.base.main.SEPARATE" : {},
128-
129132 "gov.irs.social_security.taxability.threshold.adjusted_base.main.SINGLE" : {},
130133 "gov.irs.social_security.taxability.threshold.adjusted_base.main.JOINT" : {},
131134 "gov.irs.social_security.taxability.threshold.adjusted_base.main.HEAD_OF_HOUSEHOLD" : {},
132135 "gov.irs.social_security.taxability.threshold.adjusted_base.main.SURVIVING_SPOUSE" : {},
133136 "gov.irs.social_security.taxability.threshold.adjusted_base.main.SEPARATE" : {},
134-
135137 # Rates - Base (Tier 1)
136138 "gov.irs.social_security.taxability.rate.base.benefit_cap" : {},
137139 "gov.irs.social_security.taxability.rate.base.excess" : {},
138-
139140 # Rates - Additional (Tier 2 - HI)
140141 "gov.irs.social_security.taxability.rate.additional.benefit_cap" : {},
141142 "gov.irs.social_security.taxability.rate.additional.excess" : {},
@@ -174,29 +175,49 @@ def create_h6_reform():
174175 # The swapped rate error is 14x smaller and aligns with tax-cutting intent.
175176
176177 # Tier 1 (Base): HI ONLY (35%)
177- reform_payload ["gov.irs.social_security.taxability.rate.base.benefit_cap" ][period ] = 0.35
178- reform_payload ["gov.irs.social_security.taxability.rate.base.excess" ][period ] = 0.35
178+ reform_payload [
179+ "gov.irs.social_security.taxability.rate.base.benefit_cap"
180+ ][period ] = 0.35
181+ reform_payload ["gov.irs.social_security.taxability.rate.base.excess" ][
182+ period
183+ ] = 0.35
179184
180185 # Tier 2 (Additional): HI + OASDI Combined (85%)
181- reform_payload ["gov.irs.social_security.taxability.rate.additional.benefit_cap" ][period ] = 0.85
182- reform_payload ["gov.irs.social_security.taxability.rate.additional.excess" ][period ] = 0.85
186+ reform_payload [
187+ "gov.irs.social_security.taxability.rate.additional.benefit_cap"
188+ ][period ] = 0.85
189+ reform_payload [
190+ "gov.irs.social_security.taxability.rate.additional.excess"
191+ ][period ] = 0.85
183192
184193 # --- SET THRESHOLDS (MIN/MAX SWAP) ---
185194 # Always put the smaller number in 'base' and larger in 'adjusted_base'
186195
187196 # Single
188- reform_payload ["gov.irs.social_security.taxability.threshold.base.main.SINGLE" ][period ] = min (oasdi_target_single , HI_SINGLE )
189- reform_payload ["gov.irs.social_security.taxability.threshold.adjusted_base.main.SINGLE" ][period ] = max (oasdi_target_single , HI_SINGLE )
197+ reform_payload [
198+ "gov.irs.social_security.taxability.threshold.base.main.SINGLE"
199+ ][period ] = min (oasdi_target_single , HI_SINGLE )
200+ reform_payload [
201+ "gov.irs.social_security.taxability.threshold.adjusted_base.main.SINGLE"
202+ ][period ] = max (oasdi_target_single , HI_SINGLE )
190203
191204 # Joint
192- reform_payload ["gov.irs.social_security.taxability.threshold.base.main.JOINT" ][period ] = min (oasdi_target_joint , HI_JOINT )
193- reform_payload ["gov.irs.social_security.taxability.threshold.adjusted_base.main.JOINT" ][period ] = max (oasdi_target_joint , HI_JOINT )
205+ reform_payload [
206+ "gov.irs.social_security.taxability.threshold.base.main.JOINT"
207+ ][period ] = min (oasdi_target_joint , HI_JOINT )
208+ reform_payload [
209+ "gov.irs.social_security.taxability.threshold.adjusted_base.main.JOINT"
210+ ][period ] = max (oasdi_target_joint , HI_JOINT )
194211
195212 # Map other statuses (Head/Surviving Spouse -> Single logic, Separate -> Single logic usually)
196213 # Note: Separate is usually 0, but for H6 strictness we map to Single logic here
197214 for status in ["HEAD_OF_HOUSEHOLD" , "SURVIVING_SPOUSE" , "SEPARATE" ]:
198- reform_payload [f"gov.irs.social_security.taxability.threshold.base.main.{ status } " ][period ] = min (oasdi_target_single , HI_SINGLE )
199- reform_payload [f"gov.irs.social_security.taxability.threshold.adjusted_base.main.{ status } " ][period ] = max (oasdi_target_single , HI_SINGLE )
215+ reform_payload [
216+ f"gov.irs.social_security.taxability.threshold.base.main.{ status } "
217+ ][period ] = min (oasdi_target_single , HI_SINGLE )
218+ reform_payload [
219+ f"gov.irs.social_security.taxability.threshold.adjusted_base.main.{ status } "
220+ ][period ] = max (oasdi_target_single , HI_SINGLE )
200221
201222 # --- PHASE 2: ELIMINATION (2054+) ---
202223 # OASDI is gone. We only collect HI.
@@ -207,26 +228,46 @@ def create_h6_reform():
207228
208229 # 1. Set Thresholds to "HI Only" mode
209230 # Base = $34k / $44k
210- reform_payload ["gov.irs.social_security.taxability.threshold.base.main.SINGLE" ][elim_period ] = HI_SINGLE
211- reform_payload ["gov.irs.social_security.taxability.threshold.base.main.JOINT" ][elim_period ] = HI_JOINT
231+ reform_payload [
232+ "gov.irs.social_security.taxability.threshold.base.main.SINGLE"
233+ ][elim_period ] = HI_SINGLE
234+ reform_payload [
235+ "gov.irs.social_security.taxability.threshold.base.main.JOINT"
236+ ][elim_period ] = HI_JOINT
212237
213238 # Adjusted = Infinity (Disable the second tier effectively)
214- reform_payload ["gov.irs.social_security.taxability.threshold.adjusted_base.main.SINGLE" ][elim_period ] = 9_999_999
215- reform_payload ["gov.irs.social_security.taxability.threshold.adjusted_base.main.JOINT" ][elim_period ] = 9_999_999
239+ reform_payload [
240+ "gov.irs.social_security.taxability.threshold.adjusted_base.main.SINGLE"
241+ ][elim_period ] = 9_999_999
242+ reform_payload [
243+ "gov.irs.social_security.taxability.threshold.adjusted_base.main.JOINT"
244+ ][elim_period ] = 9_999_999
216245
217246 # Map others
218247 for status in ["HEAD_OF_HOUSEHOLD" , "SURVIVING_SPOUSE" , "SEPARATE" ]:
219- reform_payload [f"gov.irs.social_security.taxability.threshold.base.main.{ status } " ][elim_period ] = HI_SINGLE
220- reform_payload [f"gov.irs.social_security.taxability.threshold.adjusted_base.main.{ status } " ][elim_period ] = 9_999_999
248+ reform_payload [
249+ f"gov.irs.social_security.taxability.threshold.base.main.{ status } "
250+ ][elim_period ] = HI_SINGLE
251+ reform_payload [
252+ f"gov.irs.social_security.taxability.threshold.adjusted_base.main.{ status } "
253+ ][elim_period ] = 9_999_999
221254
222255 # 2. Set Rates for HI Only Revenue
223256 # Tier 1 (Now the ONLY tier) = 35% (HI Share)
224- reform_payload ["gov.irs.social_security.taxability.rate.base.benefit_cap" ][elim_period ] = 0.35
225- reform_payload ["gov.irs.social_security.taxability.rate.base.excess" ][elim_period ] = 0.35
257+ reform_payload ["gov.irs.social_security.taxability.rate.base.benefit_cap" ][
258+ elim_period
259+ ] = 0.35
260+ reform_payload ["gov.irs.social_security.taxability.rate.base.excess" ][
261+ elim_period
262+ ] = 0.35
226263
227264 # Tier 2 (Disabled via threshold, but zero out for safety)
228- reform_payload ["gov.irs.social_security.taxability.rate.additional.benefit_cap" ][elim_period ] = 0.35
229- reform_payload ["gov.irs.social_security.taxability.rate.additional.excess" ][elim_period ] = 0.35
265+ reform_payload [
266+ "gov.irs.social_security.taxability.rate.additional.benefit_cap"
267+ ][elim_period ] = 0.35
268+ reform_payload [
269+ "gov.irs.social_security.taxability.rate.additional.excess"
270+ ][elim_period ] = 0.35
230271
231272 return reform_payload
232273
@@ -236,8 +277,8 @@ def create_h6_reform():
236277h6_reform = Reform .from_dict (h6_reform_payload , country_id = "us" )
237278
238279year = 2052
239- dataset_path = f' /home/baogorek/devl/sep/policyengine-us-data/policyengine_us_data/datasets/cps/long_term/projected_datasets/{ year } .h5'
240- #dataset_path = f'hf://policyengine/test/{year}.h5'
280+ dataset_path = f" /home/baogorek/devl/sep/policyengine-us-data/policyengine_us_data/datasets/cps/long_term/projected_datasets/{ year } .h5"
281+ # dataset_path = f'hf://policyengine/test/{year}.h5'
241282
242283# Baseline simulation
243284baseline = Microsimulation (dataset = dataset_path )
@@ -257,18 +298,29 @@ def create_h6_reform():
257298print (f"revenue_impact (B): { revenue_impact / 1E9 :.2f} " )
258299
259300# Calculate taxable payroll
260- taxable_ss_earnings = baseline .calculate ("taxable_earnings_for_social_security" )
261- taxable_self_employment = baseline .calculate ("social_security_taxable_self_employment_income" )
262- total_taxable_payroll = taxable_ss_earnings .sum () + taxable_self_employment .sum ()
301+ taxable_ss_earnings = baseline .calculate (
302+ "taxable_earnings_for_social_security"
303+ )
304+ taxable_self_employment = baseline .calculate (
305+ "social_security_taxable_self_employment_income"
306+ )
307+ total_taxable_payroll = (
308+ taxable_ss_earnings .sum () + taxable_self_employment .sum ()
309+ )
263310
264311# Calculate SS benefits
265312ss_benefits = baseline .calculate ("social_security" )
266313total_ss_benefits = ss_benefits .sum ()
267314
268- est_rev_as_pct_of_taxable_payroll = 100 * revenue_impact / total_taxable_payroll
315+ est_rev_as_pct_of_taxable_payroll = (
316+ 100 * revenue_impact / total_taxable_payroll
317+ )
269318
270319# From https://www.ssa.gov/oact/solvency/provisions/tables/table_run133.html:
271320target_rev_as_pct_of_taxable_payroll = - 1.12
272321
273- assert np .allclose (est_rev_as_pct_of_taxable_payroll , target_rev_as_pct_of_taxable_payroll , atol = .01 )
274-
322+ assert np .allclose (
323+ est_rev_as_pct_of_taxable_payroll ,
324+ target_rev_as_pct_of_taxable_payroll ,
325+ atol = 0.01 ,
326+ )
0 commit comments