policyengine-us 1.458.0__py3-none-any.whl → 1.465.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. policyengine_us/parameters/gov/contrib/aca/ptc_700_fpl_cliff/brackets.yaml +52 -0
  2. policyengine_us/parameters/gov/contrib/aca/ptc_700_fpl_cliff/in_effect.yaml +9 -0
  3. policyengine_us/parameters/gov/contrib/aca/ptc_700_fpl_cliff/income_eligibility.yaml +27 -0
  4. policyengine_us/parameters/gov/hhs/medicare/savings_programs/eligibility/asset/applies.yaml +115 -0
  5. policyengine_us/parameters/gov/hhs/medicare/savings_programs/eligibility/asset/couple.yaml +14 -0
  6. policyengine_us/parameters/gov/hhs/medicare/savings_programs/eligibility/asset/individual.yaml +14 -0
  7. policyengine_us/parameters/gov/hhs/medicare/savings_programs/eligibility/income/qi/fpl_limit.yaml +14 -0
  8. policyengine_us/parameters/gov/hhs/medicare/savings_programs/eligibility/income/qmb/fpl_limit.yaml +18 -0
  9. policyengine_us/parameters/gov/hhs/medicare/savings_programs/eligibility/income/slmb/fpl_limit.yaml +15 -0
  10. policyengine_us/parameters/gov/states/az/tax/income/credits/property_tax/income_sources.yaml +17 -9
  11. policyengine_us/parameters/gov/states/hi/tax/income/credits/food_excise_tax/amount/head_of_household.yaml +1 -1
  12. policyengine_us/parameters/gov/states/hi/tax/income/credits/food_excise_tax/amount/joint.yaml +1 -1
  13. policyengine_us/parameters/gov/states/hi/tax/income/credits/food_excise_tax/amount/separate.yaml +1 -1
  14. policyengine_us/parameters/gov/states/hi/tax/income/credits/food_excise_tax/amount/single.yaml +1 -1
  15. policyengine_us/parameters/gov/states/hi/tax/income/credits/food_excise_tax/amount/surviving_spouse.yaml +1 -1
  16. policyengine_us/parameters/gov/states/ia/tax/income/credits/child_care/fraction.yaml +1 -1
  17. policyengine_us/parameters/gov/states/il/dhs/aabd/asset/sources.yaml +0 -1
  18. policyengine_us/parameters/gov/states/mi/tax/income/household_resources.yaml +1 -1
  19. policyengine_us/parameters/gov/states/mo/dss/tanf/child_care_deduction/amount.yaml +27 -0
  20. policyengine_us/parameters/gov/states/mo/dss/tanf/earned_income_disregard/amount.yaml +14 -0
  21. policyengine_us/parameters/gov/states/mo/dss/tanf/earned_income_disregard/thirty_only/amount.yaml +14 -0
  22. policyengine_us/parameters/gov/states/mo/dss/tanf/earned_income_disregard/thirty_plus_one_third/flat_amount.yaml +14 -0
  23. policyengine_us/parameters/gov/states/mo/dss/tanf/earned_income_disregard/thirty_plus_one_third/percentage.yaml +14 -0
  24. policyengine_us/parameters/gov/states/mo/dss/tanf/earned_income_disregard/two_thirds_disregard/percentage.yaml +14 -0
  25. policyengine_us/parameters/gov/states/mo/dss/tanf/income_limit/max_table_size.yaml +12 -0
  26. policyengine_us/parameters/gov/states/mo/dss/tanf/income_limit/rate.yaml +14 -0
  27. policyengine_us/parameters/gov/states/mo/dss/tanf/maximum_benefit/percentage.yaml +14 -0
  28. policyengine_us/parameters/gov/states/mo/dss/tanf/minimum_payment.yaml +12 -0
  29. policyengine_us/parameters/gov/states/mo/dss/tanf/resource_limit/amount.yaml +14 -0
  30. policyengine_us/parameters/gov/states/mo/dss/tanf/standard_of_need/additional_person_increment.yaml +12 -0
  31. policyengine_us/parameters/gov/states/mo/dss/tanf/standard_of_need/amount.yaml +38 -0
  32. policyengine_us/parameters/gov/states/mo/dss/tanf/standard_of_need/base_table_max_size.yaml +12 -0
  33. policyengine_us/parameters/gov/states/pa/dhs/tanf/county_group/group_1.yaml +19 -0
  34. policyengine_us/parameters/gov/states/pa/dhs/tanf/county_group/group_2.yaml +44 -0
  35. policyengine_us/parameters/gov/states/pa/dhs/tanf/county_group/group_3.yaml +31 -0
  36. policyengine_us/parameters/gov/states/pa/dhs/tanf/county_group/group_4.yaml +29 -0
  37. policyengine_us/parameters/gov/states/pa/dhs/tanf/family_size_allowance/additional_person.yaml +14 -0
  38. policyengine_us/parameters/gov/states/pa/dhs/tanf/family_size_allowance/amount.yaml +69 -0
  39. policyengine_us/parameters/gov/states/pa/dhs/tanf/income/deductions/earned_income_disregard/percentage.yaml +14 -0
  40. policyengine_us/parameters/gov/states/pa/dhs/tanf/income/deductions/work_expense/additional.yaml +15 -0
  41. policyengine_us/parameters/gov/states/pa/dhs/tanf/income/deductions/work_expense/initial.yaml +14 -0
  42. policyengine_us/parameters/gov/states/pa/dhs/tanf/max_family_size_in_table.yaml +12 -0
  43. policyengine_us/parameters/gov/states/pa/dhs/tanf/resource_limit.yaml +7 -6
  44. policyengine_us/parameters/gov/states/pa/dhs/tanf/standard_of_need/additional_person.yaml +14 -0
  45. policyengine_us/parameters/gov/states/pa/dhs/tanf/standard_of_need/amount.yaml +69 -0
  46. policyengine_us/parameters/gov/states/wi/dcf/README.md +1 -0
  47. policyengine_us/parameters/gov/states/wi/dcf/works/README.md +1 -0
  48. policyengine_us/parameters/gov/states/wi/dcf/works/asset/limit.yaml +16 -0
  49. policyengine_us/parameters/gov/states/wi/dcf/works/asset/vehicle_exclusion.yaml +14 -0
  50. policyengine_us/parameters/gov/states/wi/dcf/works/income_limit/rate.yaml +16 -0
  51. policyengine_us/parameters/gov/states/wi/dcf/works/placement/amount.yaml +30 -0
  52. policyengine_us/parameters/gov/states/wi/dcf/works/placement/arp_pregnancy_month_threshold.yaml +14 -0
  53. policyengine_us/parameters/gov/states/wi/dcf/works/placement/cmc_infant_age_limit.yaml +15 -0
  54. policyengine_us/reforms/aca/__init__.py +3 -0
  55. policyengine_us/reforms/aca/aca_ptc_700_fpl_cliff.py +125 -0
  56. policyengine_us/reforms/reforms.py +5 -0
  57. policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/category/msp_category.yaml +69 -0
  58. policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/eligibility/msp_eligible.yaml +62 -0
  59. policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/income/msp_fpg.yaml +22 -0
  60. policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/integration.yaml +84 -0
  61. policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/msp_benefit_value.yaml +62 -0
  62. policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/social_security/taxable_social_security_tier_1.yaml +157 -0
  63. policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/social_security/taxable_social_security_tier_2.yaml +106 -0
  64. policyengine_us/tests/policy/baseline/gov/ssa/revenue/tob_revenue_medicare_hi.yaml +105 -0
  65. policyengine_us/tests/policy/baseline/gov/ssa/revenue/tob_revenue_oasdi.yaml +86 -0
  66. policyengine_us/tests/policy/baseline/gov/ssa/revenue/tob_revenue_total.yaml +19 -0
  67. policyengine_us/tests/policy/baseline/gov/ssa/revenue/tob_tier_split.yaml +90 -0
  68. policyengine_us/tests/policy/baseline/gov/states/az/tax/income/az_property_tax_credit_agi.yaml +58 -0
  69. policyengine_us/tests/policy/baseline/gov/states/az/tax/income/integration.yaml +28 -0
  70. policyengine_us/tests/policy/baseline/gov/states/dc/tax/income/dc_ptc.yaml +27 -0
  71. policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/credits/food_excise/hi_food_excise_credit.yaml +29 -1
  72. policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/ia_cdcc.yaml +3 -3
  73. policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/ia_integration.yaml +31 -1
  74. policyengine_us/tests/policy/baseline/gov/states/il/dhs/aabd/eligibility/il_aabd_non_financial_eligible_person.yaml +6 -6
  75. policyengine_us/tests/policy/baseline/gov/states/il/hfs/fpp/integration.yaml +2 -2
  76. policyengine_us/tests/policy/baseline/gov/states/il/hfs/hbwd/eligibility/il_hbwd_disability_eligible.yaml +18 -5
  77. policyengine_us/tests/policy/baseline/gov/states/il/hfs/hbwd/eligibility/il_hbwd_eligible.yaml +5 -5
  78. policyengine_us/tests/policy/baseline/gov/states/il/hfs/hbwd/integration.yaml +8 -8
  79. policyengine_us/tests/policy/baseline/gov/states/ma/tax/income/gross_income/integration.yaml +28 -0
  80. policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/integration.yaml +87 -0
  81. policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/me_dependent_exemption_credit_amount_person.yaml +3 -2
  82. policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/credits/home_heating/mi_home_heating_credit.yaml +87 -0
  83. policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/mi_household_resources.yaml +57 -0
  84. policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/integration.yaml +275 -0
  85. policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf.yaml +60 -0
  86. policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_child_care_deduction.yaml +187 -0
  87. policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_countable_income.yaml +49 -0
  88. policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_earned_income_deductions.yaml +53 -0
  89. policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_eligible.yaml +59 -0
  90. policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_gross_income_eligible.yaml +29 -0
  91. policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_income_eligible.yaml +49 -0
  92. policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_maximum_benefit.yaml +47 -0
  93. policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_percentage_of_need_test.yaml +53 -0
  94. policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_resources_eligible.yaml +23 -0
  95. policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_standard_of_need.yaml +71 -0
  96. policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_standard_of_need_test.yaml +44 -0
  97. policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/integration.yaml +29 -0
  98. policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/eligibility/pa_tanf_disregard_eligible.yaml +114 -0
  99. policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/eligibility/pa_tanf_eligible.yaml +65 -0
  100. policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/eligibility/pa_tanf_income_eligible.yaml +62 -0
  101. policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/eligibility/pa_tanf_resources_eligible.yaml +47 -0
  102. policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/income/pa_tanf_earned_income_after_deductions_person.yaml +81 -0
  103. policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/integration.yaml +386 -0
  104. policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/pa_tanf.yaml +53 -0
  105. policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/pa_tanf_county_group.yaml +63 -0
  106. policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/pa_tanf_maximum_benefit.yaml +92 -0
  107. policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/pa_tanf_standard_of_need.yaml +73 -0
  108. policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/integration.yaml +282 -0
  109. policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/wi_works.yaml +50 -0
  110. policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/wi_works_countable_income.yaml +49 -0
  111. policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/wi_works_countable_resources.yaml +54 -0
  112. policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/wi_works_eligible.yaml +61 -0
  113. policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/wi_works_income_eligible.yaml +43 -0
  114. policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/wi_works_placement.yaml +111 -0
  115. policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/wi_works_resources_eligible.yaml +38 -0
  116. policyengine_us/tests/policy/baseline/gov/states/wv/tax/income/credits/heptc/wv_homestead_excess_property_tax_credit.yaml +31 -0
  117. policyengine_us/tests/policy/contrib/aca/ptc_700_fpl_cliff.yaml +136 -0
  118. policyengine_us/tests/test_batched.py +39 -68
  119. policyengine_us/variables/gov/hhs/medicare/savings_programs/category/is_qi_eligible.py +33 -0
  120. policyengine_us/variables/gov/hhs/medicare/savings_programs/category/is_qmb_eligible.py +28 -0
  121. policyengine_us/variables/gov/hhs/medicare/savings_programs/category/is_slmb_eligible.py +33 -0
  122. policyengine_us/variables/gov/hhs/medicare/savings_programs/category/msp_category.py +33 -0
  123. policyengine_us/variables/gov/hhs/medicare/savings_programs/eligibility/msp_asset_eligible.py +26 -0
  124. policyengine_us/variables/gov/hhs/medicare/savings_programs/eligibility/msp_eligible.py +20 -0
  125. policyengine_us/variables/gov/hhs/medicare/savings_programs/eligibility/msp_income_eligible.py +26 -0
  126. policyengine_us/variables/gov/hhs/medicare/savings_programs/income/msp_countable_income.py +35 -0
  127. policyengine_us/variables/gov/hhs/medicare/savings_programs/income/msp_fpg.py +40 -0
  128. policyengine_us/variables/gov/hhs/medicare/savings_programs/msp.py +15 -0
  129. policyengine_us/variables/gov/hhs/medicare/savings_programs/msp_benefit_value.py +37 -0
  130. policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/social_security/taxable_social_security_tier_1.py +58 -0
  131. policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/social_security/taxable_social_security_tier_2.py +17 -0
  132. policyengine_us/variables/gov/simulation/labor_supply_response/labor_supply_behavioral_response.py +57 -42
  133. policyengine_us/variables/gov/ssa/revenue/tob_revenue_medicare_hi.py +31 -0
  134. policyengine_us/variables/gov/ssa/revenue/tob_revenue_oasdi.py +31 -0
  135. policyengine_us/variables/gov/ssa/revenue/tob_revenue_total.py +44 -0
  136. policyengine_us/variables/gov/states/az/tax/income/credits/property_tax_credit/az_property_tax_credit_agi.py +53 -0
  137. policyengine_us/variables/gov/states/dc/tax/income/credits/dc_ptc.py +7 -3
  138. policyengine_us/variables/gov/states/ia/tax/income/credits/ia_cdcc.py +4 -2
  139. policyengine_us/variables/gov/states/il/dhs/aabd/eligibility/il_aabd_non_financial_eligible_person.py +23 -5
  140. policyengine_us/variables/gov/states/il/hfs/fpp/eligibility/il_fpp_eligible.py +1 -1
  141. policyengine_us/variables/gov/states/il/hfs/hbwd/eligibility/il_hbwd_disability_eligible.py +7 -3
  142. policyengine_us/variables/gov/states/ma/tax/income/gross_income/ma_part_c_gross_income.py +7 -1
  143. policyengine_us/variables/gov/states/me/tax/income/credits/dependent_exemption/me_dependent_exemption_credit_amount_person.py +1 -1
  144. policyengine_us/variables/gov/states/mi/tax/income/mi_household_resources.py +34 -5
  145. policyengine_us/variables/gov/states/mo/dss/tanf/eligibility/mo_tanf_eligible.py +23 -0
  146. policyengine_us/variables/gov/states/mo/dss/tanf/eligibility/mo_tanf_gross_income_eligible.py +24 -0
  147. policyengine_us/variables/gov/states/mo/dss/tanf/eligibility/mo_tanf_income_eligible.py +18 -0
  148. policyengine_us/variables/gov/states/mo/dss/tanf/eligibility/mo_tanf_percentage_of_need_test.py +20 -0
  149. policyengine_us/variables/gov/states/mo/dss/tanf/eligibility/mo_tanf_resources_eligible.py +18 -0
  150. policyengine_us/variables/gov/states/mo/dss/tanf/eligibility/mo_tanf_standard_of_need_test.py +17 -0
  151. policyengine_us/variables/gov/states/mo/dss/tanf/income/deductions/mo_tanf_child_care_deduction.py +24 -0
  152. policyengine_us/variables/gov/states/mo/dss/tanf/income/deductions/mo_tanf_earned_income_deductions.py +36 -0
  153. policyengine_us/variables/gov/states/mo/dss/tanf/income/mo_tanf_countable_income.py +21 -0
  154. policyengine_us/variables/gov/states/mo/dss/tanf/income/mo_tanf_income_for_need_test.py +23 -0
  155. policyengine_us/variables/gov/states/mo/dss/tanf/mo_tanf.py +21 -0
  156. policyengine_us/variables/gov/states/mo/dss/tanf/mo_tanf_maximum_benefit.py +19 -0
  157. policyengine_us/variables/gov/states/mo/dss/tanf/mo_tanf_standard_of_need.py +23 -0
  158. policyengine_us/variables/gov/states/mt/tax/income/capital_gains/mt_capital_gains_tax_indiv.py +3 -1
  159. policyengine_us/variables/gov/states/mt/tax/income/capital_gains/mt_capital_gains_tax_joint.py +3 -1
  160. policyengine_us/variables/gov/states/mt/tax/income/tax_calculation/mt_regular_income_tax_indiv.py +3 -0
  161. policyengine_us/variables/gov/states/mt/tax/income/tax_calculation/mt_regular_income_tax_joint.py +3 -0
  162. policyengine_us/variables/gov/states/pa/dhs/tanf/eligibility/pa_tanf_disregard_eligible.py +31 -0
  163. policyengine_us/variables/gov/states/pa/dhs/tanf/eligibility/pa_tanf_eligible.py +29 -0
  164. policyengine_us/variables/gov/states/pa/dhs/tanf/eligibility/pa_tanf_income_eligible.py +16 -0
  165. policyengine_us/variables/gov/states/pa/dhs/tanf/eligibility/pa_tanf_resources_eligible.py +7 -5
  166. policyengine_us/variables/gov/states/pa/dhs/tanf/income/pa_tanf_countable_earned_income.py +15 -0
  167. policyengine_us/variables/gov/states/pa/dhs/tanf/income/pa_tanf_countable_income.py +16 -0
  168. policyengine_us/variables/gov/states/pa/dhs/tanf/income/pa_tanf_earned_income_after_deductions_person.py +27 -0
  169. policyengine_us/variables/gov/states/pa/dhs/tanf/pa_tanf.py +19 -0
  170. policyengine_us/variables/gov/states/pa/dhs/tanf/pa_tanf_county_group.py +38 -0
  171. policyengine_us/variables/gov/states/pa/dhs/tanf/pa_tanf_maximum_benefit.py +30 -0
  172. policyengine_us/variables/gov/states/pa/dhs/tanf/pa_tanf_standard_of_need.py +30 -0
  173. policyengine_us/variables/gov/states/wi/dcf/works/eligibility/wi_works_eligible.py +22 -0
  174. policyengine_us/variables/gov/states/wi/dcf/works/eligibility/wi_works_income_eligible.py +20 -0
  175. policyengine_us/variables/gov/states/wi/dcf/works/eligibility/wi_works_resources_eligible.py +18 -0
  176. policyengine_us/variables/gov/states/wi/dcf/works/income/wi_works_countable_income.py +18 -0
  177. policyengine_us/variables/gov/states/wi/dcf/works/resources/wi_works_countable_resources.py +21 -0
  178. policyengine_us/variables/gov/states/wi/dcf/works/wi_works.py +19 -0
  179. policyengine_us/variables/gov/states/wi/dcf/works/wi_works_placement.py +45 -0
  180. policyengine_us/variables/gov/states/wv/tax/income/credits/heptc/wv_homestead_excess_property_tax_credit.py +3 -3
  181. policyengine_us/variables/gov/states/wv/tax/income/credits/heptc/wv_homestead_excess_property_tax_credit_eligible.py +5 -2
  182. {policyengine_us-1.458.0.dist-info → policyengine_us-1.465.0.dist-info}/METADATA +1 -1
  183. {policyengine_us-1.458.0.dist-info → policyengine_us-1.465.0.dist-info}/RECORD +186 -62
  184. policyengine_us/parameters/gov/states/il/dhs/aabd/aged_age_threshold.yaml +0 -11
  185. policyengine_us/parameters/gov/states/mo/dss/tanf/income_limit.yaml +0 -26
  186. policyengine_us/parameters/gov/states/pa/dhs/tanf/cash_assistance/age_limit.yaml +0 -11
  187. policyengine_us/parameters/gov/states/pa/dhs/tanf/pregnancy_eligibility/age_limit.yaml +0 -9
  188. policyengine_us/tests/policy/baseline/gov/states/il/dhs/aabd/eligibility/il_aabd_aged_blind_disabled_person.yaml +0 -39
  189. policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_income_limit.yaml +0 -23
  190. policyengine_us/tests/policy/baseline/gov/states/pa/tanf/cash_assistance/pa_tanf_age_eligible.yaml +0 -44
  191. policyengine_us/tests/policy/baseline/gov/states/pa/tanf/pregnancy_eligibility/pa_tanf_pregnancy_eligibility.yaml +0 -59
  192. policyengine_us/tests/policy/baseline/gov/states/pa/tax/income/dhs/tanf/eligibility/pa_tanf_resources_eligible.yaml +0 -24
  193. policyengine_us/variables/gov/states/il/dhs/aabd/eligibility/il_aabd_aged_blind_disabled_person.py +0 -22
  194. policyengine_us/variables/gov/states/mo/dss/tanf/mo_tanf_income_limit.py +0 -18
  195. policyengine_us/variables/gov/states/pa/dhs/tanf/cash_assistance/pa_tanf_age_eligible.py +0 -22
  196. policyengine_us/variables/gov/states/pa/dhs/tanf/eligibility/pa_tanf_countable_resources.py +0 -10
  197. policyengine_us/variables/gov/states/pa/dhs/tanf/eligibility/pregnancy_eligibility/age_eligibility.py +0 -22
  198. {policyengine_us-1.458.0.dist-info → policyengine_us-1.465.0.dist-info}/WHEEL +0 -0
  199. {policyengine_us-1.458.0.dist-info → policyengine_us-1.465.0.dist-info}/entry_points.txt +0 -0
  200. {policyengine_us-1.458.0.dist-info → policyengine_us-1.465.0.dist-info}/licenses/LICENSE +0 -0
@@ -41,3 +41,34 @@
41
41
  # heptc_amount = property_tax - wv_sctc - p.ghi_percentage * wv_ghi = 20000-10000-800 = 8200
42
42
  output:
43
43
  wv_homestead_excess_property_tax_credit: 0
44
+
45
+ - name: WV no HEPTC credit with negative income and zero property taxes
46
+ absolute_error_margin: 2
47
+ period: 2024
48
+ input:
49
+ people:
50
+ person1:
51
+ is_tax_unit_head: true
52
+ age: 40
53
+ short_term_capital_gains: -896_056.95
54
+ partnership_s_corp_income: -727_887.75
55
+ taxable_interest_income: 0.012324943
56
+ person2:
57
+ is_tax_unit_spouse: true
58
+ age: 40
59
+ short_term_capital_gains: -896_056.95
60
+ partnership_s_corp_income: -727_887.75
61
+ taxable_interest_income: 0.012324943
62
+ tax_units:
63
+ tax_unit:
64
+ members: [person1, person2]
65
+ spm_units:
66
+ spm_unit:
67
+ members: [person1, person2]
68
+ households:
69
+ household:
70
+ members: [person1, person2]
71
+ state_fips: 54
72
+ output:
73
+ adjusted_gross_income: -3_000
74
+ wv_homestead_excess_property_tax_credit: 0
@@ -0,0 +1,136 @@
1
+ - name: Single filer at 0% FPL - zero contribution
2
+ period: 2026
3
+ reforms: policyengine_us.reforms.aca.aca_ptc_700_fpl_cliff.aca_ptc_700_fpl_cliff
4
+ absolute_error_margin: 0.00001
5
+ input:
6
+ gov.contrib.aca.ptc_700_fpl_cliff.in_effect: true
7
+ aca_magi_fraction: 0.0
8
+ output:
9
+ aca_required_contribution_percentage: 0.0
10
+
11
+ - name: Single filer at 150% FPL - zero contribution
12
+ period: 2026
13
+ reforms: policyengine_us.reforms.aca.aca_ptc_700_fpl_cliff.aca_ptc_700_fpl_cliff
14
+ absolute_error_margin: 0.00001
15
+ input:
16
+ gov.contrib.aca.ptc_700_fpl_cliff.in_effect: true
17
+ aca_magi_fraction: 1.5
18
+ output:
19
+ aca_required_contribution_percentage: 0.0
20
+
21
+ - name: Single filer at 200% FPL - 2% contribution
22
+ period: 2026
23
+ reforms: policyengine_us.reforms.aca.aca_ptc_700_fpl_cliff.aca_ptc_700_fpl_cliff
24
+ absolute_error_margin: 0.00001
25
+ input:
26
+ gov.contrib.aca.ptc_700_fpl_cliff.in_effect: true
27
+ aca_magi_fraction: 2.0
28
+ output:
29
+ aca_required_contribution_percentage: 0.02
30
+
31
+ - name: Single filer at 250% FPL - 4% contribution
32
+ period: 2026
33
+ reforms: policyengine_us.reforms.aca.aca_ptc_700_fpl_cliff.aca_ptc_700_fpl_cliff
34
+ absolute_error_margin: 0.00001
35
+ input:
36
+ gov.contrib.aca.ptc_700_fpl_cliff.in_effect: true
37
+ aca_magi_fraction: 2.5
38
+ output:
39
+ aca_required_contribution_percentage: 0.04
40
+
41
+ - name: Single filer at 300% FPL - 6% contribution
42
+ period: 2026
43
+ reforms: policyengine_us.reforms.aca.aca_ptc_700_fpl_cliff.aca_ptc_700_fpl_cliff
44
+ absolute_error_margin: 0.00001
45
+ input:
46
+ gov.contrib.aca.ptc_700_fpl_cliff.in_effect: true
47
+ aca_magi_fraction: 3.0
48
+ output:
49
+ aca_required_contribution_percentage: 0.06
50
+
51
+ - name: Single filer at 400% FPL - 8.5% contribution (old cliff point)
52
+ period: 2026
53
+ reforms: policyengine_us.reforms.aca.aca_ptc_700_fpl_cliff.aca_ptc_700_fpl_cliff
54
+ absolute_error_margin: 0.00001
55
+ input:
56
+ gov.contrib.aca.ptc_700_fpl_cliff.in_effect: true
57
+ aca_magi_fraction: 4.0
58
+ output:
59
+ aca_required_contribution_percentage: 0.085
60
+
61
+ - name: Single filer at 500% FPL - 8.5% contribution (flat rate)
62
+ period: 2026
63
+ reforms: policyengine_us.reforms.aca.aca_ptc_700_fpl_cliff.aca_ptc_700_fpl_cliff
64
+ absolute_error_margin: 0.00001
65
+ input:
66
+ gov.contrib.aca.ptc_700_fpl_cliff.in_effect: true
67
+ aca_magi_fraction: 5.0
68
+ output:
69
+ aca_required_contribution_percentage: 0.085
70
+
71
+ - name: Single filer at 600% FPL - 8.5% contribution (flat rate continues)
72
+ period: 2026
73
+ reforms: policyengine_us.reforms.aca.aca_ptc_700_fpl_cliff.aca_ptc_700_fpl_cliff
74
+ absolute_error_margin: 0.00001
75
+ input:
76
+ gov.contrib.aca.ptc_700_fpl_cliff.in_effect: true
77
+ aca_magi_fraction: 6.0
78
+ output:
79
+ aca_required_contribution_percentage: 0.085
80
+
81
+ - name: Single filer at 700% FPL - 9.25% contribution (new cliff point)
82
+ period: 2026
83
+ reforms: policyengine_us.reforms.aca.aca_ptc_700_fpl_cliff.aca_ptc_700_fpl_cliff
84
+ absolute_error_margin: 0.00001
85
+ input:
86
+ gov.contrib.aca.ptc_700_fpl_cliff.in_effect: true
87
+ aca_magi_fraction: 7.0
88
+ output:
89
+ aca_required_contribution_percentage: 0.0925
90
+
91
+ - name: Single filer at 175% FPL - interpolated 1% contribution
92
+ period: 2026
93
+ reforms: policyengine_us.reforms.aca.aca_ptc_700_fpl_cliff.aca_ptc_700_fpl_cliff
94
+ absolute_error_margin: 0.00001
95
+ input:
96
+ gov.contrib.aca.ptc_700_fpl_cliff.in_effect: true
97
+ aca_magi_fraction: 1.75
98
+ output:
99
+ aca_required_contribution_percentage: 0.01
100
+
101
+ - name: Single filer at 350% FPL - interpolated 7.25% contribution
102
+ period: 2026
103
+ reforms: policyengine_us.reforms.aca.aca_ptc_700_fpl_cliff.aca_ptc_700_fpl_cliff
104
+ absolute_error_margin: 0.00001
105
+ input:
106
+ gov.contrib.aca.ptc_700_fpl_cliff.in_effect: true
107
+ aca_magi_fraction: 3.5
108
+ output:
109
+ aca_required_contribution_percentage: 0.0725
110
+
111
+ - name: Single filer at 650% FPL - interpolated 8.875% contribution
112
+ period: 2026
113
+ reforms: policyengine_us.reforms.aca.aca_ptc_700_fpl_cliff.aca_ptc_700_fpl_cliff
114
+ absolute_error_margin: 0.00001
115
+ input:
116
+ gov.contrib.aca.ptc_700_fpl_cliff.in_effect: true
117
+ aca_magi_fraction: 6.5
118
+ output:
119
+ # 8.5% + (9.25% - 8.5%) * 0.5 = 8.5% + 0.375% = 8.875%
120
+ aca_required_contribution_percentage: 0.08875
121
+
122
+ - name: Baseline comparison at 400% FPL - shows elimination of cliff
123
+ period: 2026
124
+ absolute_error_margin: 0.00001
125
+ input:
126
+ aca_magi_fraction: 4.0
127
+ output:
128
+ aca_required_contribution_percentage: 0.0996
129
+
130
+ - name: Baseline comparison at 500% FPL - shows new eligibility
131
+ period: 2026
132
+ absolute_error_margin: 0.00001
133
+ input:
134
+ aca_magi_fraction: 5.0
135
+ output:
136
+ aca_required_contribution_percentage: 0.0996
@@ -21,37 +21,33 @@ def count_yaml_files(directory: Path) -> int:
21
21
  return len(list(directory.rglob("*.yaml")))
22
22
 
23
23
 
24
- def get_test_directories(base_path: Path) -> Dict[str, int]:
25
- """Get all subdirectories and their test counts."""
26
- dir_counts = {}
27
-
28
- # Check for yaml files directly in base directory
29
- root_count = len(list(base_path.glob("*.yaml")))
30
- if root_count > 0:
31
- dir_counts["."] = root_count
32
-
33
- # Get all subdirectories with their test counts
34
- for item in base_path.iterdir():
35
- if item.is_dir():
36
- yaml_count = count_yaml_files(item)
37
- if yaml_count > 0:
38
- dir_counts[item.name] = yaml_count
39
-
40
- return dir_counts
41
-
42
-
43
- def split_into_batches(base_path: Path, num_batches: int) -> List[List[str]]:
24
+ def split_into_batches(
25
+ base_path: Path, num_batches: int, exclude: List[str] = None
26
+ ) -> List[List[str]]:
44
27
  """
45
28
  Split test directories into specified number of batches.
46
29
  Special handling for baseline tests to separate states.
47
30
  Special handling for contrib tests to divide by folder count.
31
+
32
+ Args:
33
+ base_path: Path to the test directory
34
+ num_batches: Number of batches to split into
35
+ exclude: List of directory names to exclude (for contrib tests)
48
36
  """
37
+ if exclude is None:
38
+ exclude = []
39
+
49
40
  # Special handling for contrib tests - each folder is its own batch
50
41
  # Only apply to policy/contrib (structural tests), not baseline/contrib
51
42
  if str(base_path).endswith("policy/contrib"):
52
43
  # Get all subdirectories and sort them alphabetically
44
+ # Exclude specified directories
53
45
  subdirs = sorted(
54
- [item for item in base_path.iterdir() if item.is_dir()]
46
+ [
47
+ item
48
+ for item in base_path.iterdir()
49
+ if item.is_dir() and item.name not in exclude
50
+ ]
55
51
  )
56
52
 
57
53
  # Get root level YAML files and sort them
@@ -73,19 +69,17 @@ def split_into_batches(base_path: Path, num_batches: int) -> List[List[str]]:
73
69
  if "reform" in str(base_path):
74
70
  return [[str(base_path)]]
75
71
 
76
- # Special handling for baseline tests with 2 batches
77
- if "baseline" in str(base_path) and num_batches == 2:
72
+ # Special handling for baseline tests
73
+ if "baseline" in str(base_path) and str(base_path).endswith("baseline"):
78
74
  states_path = base_path / "gov" / "states"
79
- if states_path.exists() and count_yaml_files(states_path) > 0:
80
- # Batch 1: Only states
81
- batch1 = [str(states_path)]
82
75
 
83
- # Batch 2: Everything else (excluding states, household, and contrib)
84
- batch2 = []
76
+ # If --exclude states, skip states and run everything else
77
+ if "states" in exclude:
78
+ batch = []
85
79
 
86
80
  # Add root level files if any
87
81
  for yaml_file in base_path.glob("*.yaml"):
88
- batch2.append(str(yaml_file))
82
+ batch.append(str(yaml_file))
89
83
 
90
84
  # Add all directories except gov/states, household, and contrib
91
85
  for item in base_path.iterdir():
@@ -97,49 +91,17 @@ def split_into_batches(base_path: Path, num_batches: int) -> List[List[str]]:
97
91
  # Add gov subdirectories except states
98
92
  for gov_item in item.iterdir():
99
93
  if gov_item.is_dir() and gov_item.name != "states":
100
- batch2.append(str(gov_item))
94
+ batch.append(str(gov_item))
101
95
  elif gov_item.suffix == ".yaml":
102
- batch2.append(str(gov_item))
96
+ batch.append(str(gov_item))
103
97
  else:
104
98
  # Other non-gov directories
105
- batch2.append(str(item))
106
-
107
- return [batch1, batch2] if batch2 else [batch1]
108
-
109
- # Default behavior for non-baseline or different batch counts
110
- dir_counts = get_test_directories(base_path)
111
-
112
- if num_batches <= 0:
113
- num_batches = 1
99
+ batch.append(str(item))
114
100
 
115
- # If only 1 batch, return everything
116
- if num_batches == 1:
117
- return [[str(base_path)]]
118
-
119
- # Sort directories by test count (largest first)
120
- sorted_dirs = sorted(dir_counts.items(), key=lambda x: x[1], reverse=True)
121
-
122
- # Initialize batches
123
- batches = [[] for _ in range(num_batches)]
124
- batch_counts = [0] * num_batches
125
-
126
- # Distribute directories to batches (greedy algorithm - add to smallest batch)
127
- for dir_name, count in sorted_dirs:
128
- # Find batch with fewest tests
129
- min_batch_idx = batch_counts.index(min(batch_counts))
130
-
131
- # Add directory to that batch
132
- if dir_name == ".":
133
- # Root level files - add individually
134
- for yaml_file in base_path.glob("*.yaml"):
135
- batches[min_batch_idx].append(str(yaml_file))
136
- else:
137
- batches[min_batch_idx].append(str(base_path / dir_name))
138
-
139
- batch_counts[min_batch_idx] += count
101
+ return [batch] if batch else []
140
102
 
141
- # Filter out empty batches
142
- return [batch for batch in batches if batch]
103
+ # Default: return the entire path as a single batch
104
+ return [[str(base_path)]]
143
105
 
144
106
 
145
107
  def run_batch(test_paths: List[str], batch_name: str) -> Dict:
@@ -298,8 +260,15 @@ def main():
298
260
  default=2,
299
261
  help="Number of batches to split tests into (default: 2)",
300
262
  )
263
+ parser.add_argument(
264
+ "--exclude",
265
+ type=str,
266
+ default="",
267
+ help="Comma-separated list of directory names to exclude (for contrib tests)",
268
+ )
301
269
 
302
270
  args = parser.parse_args()
271
+ exclude_list = [x.strip() for x in args.exclude.split(",") if x.strip()]
303
272
 
304
273
  if not os.path.exists("policyengine_us"):
305
274
  print("Error: Must run from PolicyEngine US root directory")
@@ -314,13 +283,15 @@ def main():
314
283
  print("=" * 60)
315
284
  print(f"Test path: {test_path}")
316
285
  print(f"Requested batches: {args.batches}")
286
+ if exclude_list:
287
+ print(f"Excluding: {', '.join(exclude_list)}")
317
288
 
318
289
  # Count total tests
319
290
  total_tests = count_yaml_files(test_path)
320
291
  print(f"Total test files: {total_tests}")
321
292
 
322
293
  # Split into batches
323
- batches = split_into_batches(test_path, args.batches)
294
+ batches = split_into_batches(test_path, args.batches, exclude_list)
324
295
  if len(batches) != args.batches:
325
296
  print(
326
297
  f"Actual batches: {len(batches)} (optimized for {total_tests} files)"
@@ -0,0 +1,33 @@
1
+ from policyengine_us.model_api import *
2
+
3
+
4
+ class is_qi_eligible(Variable):
5
+ value_type = bool
6
+ entity = Person
7
+ label = "Qualifying Individual (QI) eligible"
8
+ definition_period = MONTH
9
+ reference = (
10
+ "https://www.law.cornell.edu/cfr/text/42/435.123",
11
+ "https://www.medicare.gov/basics/costs/help/medicare-savings-programs",
12
+ )
13
+
14
+ def formula(person, period, parameters):
15
+ # QI requires income above 120% FPL but at or below 135% FPL
16
+ p = parameters(
17
+ period
18
+ ).gov.hhs.medicare.savings_programs.eligibility.income
19
+
20
+ medicare_eligible = person("is_medicare_eligible", period.this_year)
21
+ asset_eligible = person("msp_asset_eligible", period)
22
+
23
+ fpg = person("msp_fpg", period)
24
+ countable_income = person("msp_countable_income", period)
25
+
26
+ slmb_income_limit = fpg * p.slmb.fpl_limit
27
+ qi_income_limit = fpg * p.qi.fpl_limit
28
+
29
+ income_above_slmb = countable_income > slmb_income_limit
30
+ income_at_or_below_qi = countable_income <= qi_income_limit
31
+ income_eligible = income_above_slmb & income_at_or_below_qi
32
+
33
+ return medicare_eligible & income_eligible & asset_eligible
@@ -0,0 +1,28 @@
1
+ from policyengine_us.model_api import *
2
+
3
+
4
+ class is_qmb_eligible(Variable):
5
+ value_type = bool
6
+ entity = Person
7
+ label = "Qualified Medicare Beneficiary (QMB) eligible"
8
+ definition_period = MONTH
9
+ reference = (
10
+ "https://www.law.cornell.edu/cfr/text/42/435.121",
11
+ "https://www.medicare.gov/basics/costs/help/medicare-savings-programs",
12
+ )
13
+
14
+ def formula(person, period, parameters):
15
+ # QMB requires income at or below 100% FPL
16
+ p = parameters(
17
+ period
18
+ ).gov.hhs.medicare.savings_programs.eligibility.income
19
+
20
+ medicare_eligible = person("is_medicare_eligible", period.this_year)
21
+ asset_eligible = person("msp_asset_eligible", period)
22
+
23
+ fpg = person("msp_fpg", period)
24
+ countable_income = person("msp_countable_income", period)
25
+ qmb_income_limit = fpg * p.qmb.fpl_limit
26
+ income_eligible = countable_income <= qmb_income_limit
27
+
28
+ return medicare_eligible & income_eligible & asset_eligible
@@ -0,0 +1,33 @@
1
+ from policyengine_us.model_api import *
2
+
3
+
4
+ class is_slmb_eligible(Variable):
5
+ value_type = bool
6
+ entity = Person
7
+ label = "Specified Low-Income Medicare Beneficiary (SLMB) eligible"
8
+ definition_period = MONTH
9
+ reference = (
10
+ "https://www.law.cornell.edu/cfr/text/42/435.122",
11
+ "https://www.medicare.gov/basics/costs/help/medicare-savings-programs",
12
+ )
13
+
14
+ def formula(person, period, parameters):
15
+ # SLMB requires income above 100% FPL but at or below 120% FPL
16
+ p = parameters(
17
+ period
18
+ ).gov.hhs.medicare.savings_programs.eligibility.income
19
+
20
+ medicare_eligible = person("is_medicare_eligible", period.this_year)
21
+ asset_eligible = person("msp_asset_eligible", period)
22
+
23
+ fpg = person("msp_fpg", period)
24
+ countable_income = person("msp_countable_income", period)
25
+
26
+ qmb_income_limit = fpg * p.qmb.fpl_limit
27
+ slmb_income_limit = fpg * p.slmb.fpl_limit
28
+
29
+ income_above_qmb = countable_income > qmb_income_limit
30
+ income_at_or_below_slmb = countable_income <= slmb_income_limit
31
+ income_eligible = income_above_qmb & income_at_or_below_slmb
32
+
33
+ return medicare_eligible & income_eligible & asset_eligible
@@ -0,0 +1,33 @@
1
+ from policyengine_us.model_api import *
2
+
3
+
4
+ class MSPCategory(Enum):
5
+ NONE = "None"
6
+ QMB = "Qualified Medicare Beneficiary"
7
+ SLMB = "Specified Low-Income Medicare Beneficiary"
8
+ QI = "Qualifying Individual"
9
+
10
+
11
+ class msp_category(Variable):
12
+ value_type = Enum
13
+ possible_values = MSPCategory
14
+ default_value = MSPCategory.NONE
15
+ entity = Person
16
+ label = "Medicare Savings Program category"
17
+ definition_period = MONTH
18
+ reference = (
19
+ "https://www.medicare.gov/basics/costs/help/medicare-savings-programs",
20
+ "https://www.law.cornell.edu/cfr/text/42/435.121",
21
+ )
22
+
23
+ def formula(person, period, parameters):
24
+ qmb = person("is_qmb_eligible", period)
25
+ slmb = person("is_slmb_eligible", period)
26
+ qi = person("is_qi_eligible", period)
27
+
28
+ # Priority: QMB > SLMB > QI (QMB is most comprehensive)
29
+ return select(
30
+ [qmb, slmb, qi],
31
+ [MSPCategory.QMB, MSPCategory.SLMB, MSPCategory.QI],
32
+ default=MSPCategory.NONE,
33
+ )
@@ -0,0 +1,26 @@
1
+ from policyengine_us.model_api import *
2
+
3
+
4
+ class msp_asset_eligible(Variable):
5
+ value_type = bool
6
+ entity = Person
7
+ label = "Medicare Savings Program asset eligible"
8
+ definition_period = MONTH
9
+ reference = (
10
+ "https://www.medicare.gov/basics/costs/help/medicare-savings-programs",
11
+ "https://www.medicareinteractive.org/understanding-medicare/"
12
+ "cost-saving-programs/medicare-savings-programs-qmb-slmb-qi/"
13
+ "medicare-savings-program-income-and-asset-limits",
14
+ )
15
+
16
+ def formula(person, period, parameters):
17
+ p = parameters(period).gov.hhs.medicare.savings_programs.eligibility
18
+ state_code = person.household("state_code_str", period)
19
+ # Check if asset test applies (some states have eliminated it)
20
+ asset_test_applies = p.asset.applies[state_code]
21
+ # If asset test doesn't apply, everyone is asset-eligible
22
+ cash_assets = person.spm_unit("spm_unit_cash_assets", period.this_year)
23
+ married = person.spm_unit("spm_unit_is_married", period)
24
+ asset_limit = where(married, p.asset.couple, p.asset.individual)
25
+ meets_asset_test = cash_assets <= asset_limit
26
+ return where(asset_test_applies, meets_asset_test, True)
@@ -0,0 +1,20 @@
1
+ from policyengine_us.model_api import *
2
+
3
+
4
+ class msp_eligible(Variable):
5
+ value_type = bool
6
+ entity = Person
7
+ label = "Medicare Savings Program eligible"
8
+ definition_period = MONTH
9
+ reference = (
10
+ "https://www.medicare.gov/basics/costs/help/medicare-savings-programs",
11
+ "https://www.law.cornell.edu/cfr/text/42/435.121",
12
+ )
13
+
14
+ def formula(person, period, parameters):
15
+ # Must be Medicare eligible
16
+ medicare_eligible = person("is_medicare_eligible", period.this_year)
17
+ income_eligible = person("msp_income_eligible", period)
18
+ asset_eligible = person("msp_asset_eligible", period)
19
+
20
+ return medicare_eligible & income_eligible & asset_eligible
@@ -0,0 +1,26 @@
1
+ from policyengine_us.model_api import *
2
+
3
+
4
+ class msp_income_eligible(Variable):
5
+ value_type = bool
6
+ entity = Person
7
+ label = "Medicare Savings Program income eligible"
8
+ definition_period = MONTH
9
+ reference = (
10
+ "https://www.medicare.gov/basics/costs/help/medicare-savings-programs",
11
+ "https://www.law.cornell.edu/cfr/text/42/435.121",
12
+ )
13
+
14
+ def formula(person, period, parameters):
15
+ # Income eligible if under the QI threshold (135% FPL)
16
+ # which is the highest threshold for standard MSP levels
17
+ p = parameters(
18
+ period
19
+ ).gov.hhs.medicare.savings_programs.eligibility.income.qi
20
+ fpg = person("msp_fpg", period)
21
+ countable_income = person("msp_countable_income", period)
22
+
23
+ # Use QI threshold (135% FPL) as the outer bound
24
+ qi_income_limit = fpg * p.fpl_limit
25
+
26
+ return countable_income <= qi_income_limit
@@ -0,0 +1,35 @@
1
+ from policyengine_us.model_api import *
2
+ from policyengine_us.variables.gov.ssa.ssi.eligibility.income._apply_ssi_exclusions import (
3
+ _apply_ssi_exclusions,
4
+ )
5
+
6
+
7
+ class msp_countable_income(Variable):
8
+ value_type = float
9
+ entity = Person
10
+ unit = USD
11
+ label = "Medicare Savings Program countable monthly income"
12
+ definition_period = MONTH
13
+ reference = (
14
+ "https://www.law.cornell.edu/uscode/text/42/1396d#p",
15
+ "https://secure.ssa.gov/apps10/poms.nsf/lnx/0501715010",
16
+ "https://www.medicare.gov/basics/costs/help/medicare-savings-programs",
17
+ )
18
+ documentation = """
19
+ MSP countable income uses SSI methodology per 42 U.S.C. 1396d(p)(1)(B),
20
+ which specifies income "determined under section 1382a" (SSI rules).
21
+ This applies the standard SSI exclusions:
22
+ 1. $20 general income exclusion (from unearned first)
23
+ 2. $65 earned income exclusion
24
+ 3. 50% of remaining earned income excluded
25
+ """
26
+
27
+ def formula(person, period, parameters):
28
+ # MSP uses SSI income methodology per 42 U.S.C. 1396d(p)(1)(B)
29
+ earned = person("ssi_earned_income", period.this_year)
30
+ unearned = person("ssi_unearned_income", period.this_year)
31
+ # Apply SSI exclusions ($20 general, $65 earned, 50% remaining)
32
+ annual_countable = _apply_ssi_exclusions(
33
+ earned, unearned, parameters, period.this_year
34
+ )
35
+ return annual_countable / MONTHS_IN_YEAR
@@ -0,0 +1,40 @@
1
+ from policyengine_us.model_api import *
2
+
3
+
4
+ class msp_fpg(Variable):
5
+ value_type = float
6
+ entity = Person
7
+ unit = USD
8
+ label = "MSP Federal Poverty Guideline"
9
+ definition_period = YEAR
10
+ reference = (
11
+ "https://www.law.cornell.edu/uscode/text/42/1396d#p",
12
+ "https://www.medicare.gov/basics/costs/help/medicare-savings-programs",
13
+ )
14
+ documentation = """
15
+ The Federal Poverty Guideline used for MSP eligibility is based on
16
+ individual or couple status, not the full household/SPM unit size.
17
+ Per 42 U.S.C. 1396d(p), MSP income limits are based on the federal
18
+ poverty line for a family of the size involved.
19
+
20
+ Note: Published Medicare.gov limits are $20/month higher than raw FPL
21
+ because they include the $20 general income exclusion in the threshold.
22
+ Our implementation applies the $20 exclusion to income instead, which
23
+ is mathematically equivalent: (income - $20) <= FPL == income <= (FPL + $20)
24
+ """
25
+
26
+ def formula(person, period, parameters):
27
+ # MSP uses individual (1 person) or couple (2 persons) FPG,
28
+ # not the full SPM unit size.
29
+ # Note: These are raw FPL values. Published limits are $20 higher
30
+ # because we apply the $20 exclusion to income (msp_countable_income)
31
+ # rather than adding it to the threshold.
32
+ married = person.spm_unit("spm_unit_is_married", period)
33
+ state_group = person.household("state_group_str", period)
34
+ p = parameters(period).gov.hhs.fpg
35
+ p1 = p.first_person[state_group]
36
+ pn = p.additional_person[state_group]
37
+ # 1 person if single, 2 persons if married
38
+ individual_fpg = p1
39
+ couple_fpg = p1 + pn
40
+ return where(married, couple_fpg, individual_fpg)
@@ -0,0 +1,15 @@
1
+ from policyengine_us.model_api import *
2
+
3
+
4
+ class msp(Variable):
5
+ value_type = float
6
+ entity = Person
7
+ unit = USD
8
+ label = "Medicare Savings Program benefit"
9
+ definition_period = MONTH
10
+ reference = (
11
+ "https://www.medicare.gov/basics/costs/help/medicare-savings-programs",
12
+ )
13
+ defined_for = "msp_eligible"
14
+
15
+ adds = ["msp_benefit_value"]
@@ -0,0 +1,37 @@
1
+ from policyengine_us.model_api import *
2
+ from policyengine_us.variables.gov.hhs.medicare.savings_programs.category.msp_category import (
3
+ MSPCategory,
4
+ )
5
+
6
+
7
+ class msp_benefit_value(Variable):
8
+ value_type = float
9
+ entity = Person
10
+ unit = USD
11
+ label = "Medicare Savings Program estimated monthly benefit value"
12
+ definition_period = MONTH
13
+ reference = (
14
+ "https://www.medicare.gov/basics/costs/help/medicare-savings-programs",
15
+ )
16
+ defined_for = "msp_eligible"
17
+
18
+ def formula(person, period, parameters):
19
+ category = person("msp_category", period)
20
+
21
+ # Get premiums (automatically disaggregated from annual to monthly)
22
+ part_a_premium = person("base_part_a_premium", period)
23
+ part_b_premium = person("base_part_b_premium", period)
24
+
25
+ # Benefit depends on category:
26
+ # QMB: Part A + Part B premiums (plus deductibles/copays, not modeled)
27
+ # SLMB: Part B premium only
28
+ # QI: Part B premium only
29
+ is_qmb = category == MSPCategory.QMB
30
+ is_slmb = category == MSPCategory.SLMB
31
+ is_qi = category == MSPCategory.QI
32
+
33
+ return (
34
+ is_qmb * (part_a_premium + part_b_premium)
35
+ + is_slmb * part_b_premium
36
+ + is_qi * part_b_premium
37
+ )