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.
- policyengine_us/parameters/gov/contrib/aca/ptc_700_fpl_cliff/brackets.yaml +52 -0
- policyengine_us/parameters/gov/contrib/aca/ptc_700_fpl_cliff/in_effect.yaml +9 -0
- policyengine_us/parameters/gov/contrib/aca/ptc_700_fpl_cliff/income_eligibility.yaml +27 -0
- policyengine_us/parameters/gov/hhs/medicare/savings_programs/eligibility/asset/applies.yaml +115 -0
- policyengine_us/parameters/gov/hhs/medicare/savings_programs/eligibility/asset/couple.yaml +14 -0
- policyengine_us/parameters/gov/hhs/medicare/savings_programs/eligibility/asset/individual.yaml +14 -0
- policyengine_us/parameters/gov/hhs/medicare/savings_programs/eligibility/income/qi/fpl_limit.yaml +14 -0
- policyengine_us/parameters/gov/hhs/medicare/savings_programs/eligibility/income/qmb/fpl_limit.yaml +18 -0
- policyengine_us/parameters/gov/hhs/medicare/savings_programs/eligibility/income/slmb/fpl_limit.yaml +15 -0
- policyengine_us/parameters/gov/states/az/tax/income/credits/property_tax/income_sources.yaml +17 -9
- policyengine_us/parameters/gov/states/hi/tax/income/credits/food_excise_tax/amount/head_of_household.yaml +1 -1
- policyengine_us/parameters/gov/states/hi/tax/income/credits/food_excise_tax/amount/joint.yaml +1 -1
- policyengine_us/parameters/gov/states/hi/tax/income/credits/food_excise_tax/amount/separate.yaml +1 -1
- policyengine_us/parameters/gov/states/hi/tax/income/credits/food_excise_tax/amount/single.yaml +1 -1
- policyengine_us/parameters/gov/states/hi/tax/income/credits/food_excise_tax/amount/surviving_spouse.yaml +1 -1
- policyengine_us/parameters/gov/states/ia/tax/income/credits/child_care/fraction.yaml +1 -1
- policyengine_us/parameters/gov/states/il/dhs/aabd/asset/sources.yaml +0 -1
- policyengine_us/parameters/gov/states/mi/tax/income/household_resources.yaml +1 -1
- policyengine_us/parameters/gov/states/mo/dss/tanf/child_care_deduction/amount.yaml +27 -0
- policyengine_us/parameters/gov/states/mo/dss/tanf/earned_income_disregard/amount.yaml +14 -0
- policyengine_us/parameters/gov/states/mo/dss/tanf/earned_income_disregard/thirty_only/amount.yaml +14 -0
- policyengine_us/parameters/gov/states/mo/dss/tanf/earned_income_disregard/thirty_plus_one_third/flat_amount.yaml +14 -0
- policyengine_us/parameters/gov/states/mo/dss/tanf/earned_income_disregard/thirty_plus_one_third/percentage.yaml +14 -0
- policyengine_us/parameters/gov/states/mo/dss/tanf/earned_income_disregard/two_thirds_disregard/percentage.yaml +14 -0
- policyengine_us/parameters/gov/states/mo/dss/tanf/income_limit/max_table_size.yaml +12 -0
- policyengine_us/parameters/gov/states/mo/dss/tanf/income_limit/rate.yaml +14 -0
- policyengine_us/parameters/gov/states/mo/dss/tanf/maximum_benefit/percentage.yaml +14 -0
- policyengine_us/parameters/gov/states/mo/dss/tanf/minimum_payment.yaml +12 -0
- policyengine_us/parameters/gov/states/mo/dss/tanf/resource_limit/amount.yaml +14 -0
- policyengine_us/parameters/gov/states/mo/dss/tanf/standard_of_need/additional_person_increment.yaml +12 -0
- policyengine_us/parameters/gov/states/mo/dss/tanf/standard_of_need/amount.yaml +38 -0
- policyengine_us/parameters/gov/states/mo/dss/tanf/standard_of_need/base_table_max_size.yaml +12 -0
- policyengine_us/parameters/gov/states/pa/dhs/tanf/county_group/group_1.yaml +19 -0
- policyengine_us/parameters/gov/states/pa/dhs/tanf/county_group/group_2.yaml +44 -0
- policyengine_us/parameters/gov/states/pa/dhs/tanf/county_group/group_3.yaml +31 -0
- policyengine_us/parameters/gov/states/pa/dhs/tanf/county_group/group_4.yaml +29 -0
- policyengine_us/parameters/gov/states/pa/dhs/tanf/family_size_allowance/additional_person.yaml +14 -0
- policyengine_us/parameters/gov/states/pa/dhs/tanf/family_size_allowance/amount.yaml +69 -0
- policyengine_us/parameters/gov/states/pa/dhs/tanf/income/deductions/earned_income_disregard/percentage.yaml +14 -0
- policyengine_us/parameters/gov/states/pa/dhs/tanf/income/deductions/work_expense/additional.yaml +15 -0
- policyengine_us/parameters/gov/states/pa/dhs/tanf/income/deductions/work_expense/initial.yaml +14 -0
- policyengine_us/parameters/gov/states/pa/dhs/tanf/max_family_size_in_table.yaml +12 -0
- policyengine_us/parameters/gov/states/pa/dhs/tanf/resource_limit.yaml +7 -6
- policyengine_us/parameters/gov/states/pa/dhs/tanf/standard_of_need/additional_person.yaml +14 -0
- policyengine_us/parameters/gov/states/pa/dhs/tanf/standard_of_need/amount.yaml +69 -0
- policyengine_us/parameters/gov/states/wi/dcf/README.md +1 -0
- policyengine_us/parameters/gov/states/wi/dcf/works/README.md +1 -0
- policyengine_us/parameters/gov/states/wi/dcf/works/asset/limit.yaml +16 -0
- policyengine_us/parameters/gov/states/wi/dcf/works/asset/vehicle_exclusion.yaml +14 -0
- policyengine_us/parameters/gov/states/wi/dcf/works/income_limit/rate.yaml +16 -0
- policyengine_us/parameters/gov/states/wi/dcf/works/placement/amount.yaml +30 -0
- policyengine_us/parameters/gov/states/wi/dcf/works/placement/arp_pregnancy_month_threshold.yaml +14 -0
- policyengine_us/parameters/gov/states/wi/dcf/works/placement/cmc_infant_age_limit.yaml +15 -0
- policyengine_us/reforms/aca/__init__.py +3 -0
- policyengine_us/reforms/aca/aca_ptc_700_fpl_cliff.py +125 -0
- policyengine_us/reforms/reforms.py +5 -0
- policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/category/msp_category.yaml +69 -0
- policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/eligibility/msp_eligible.yaml +62 -0
- policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/income/msp_fpg.yaml +22 -0
- policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/integration.yaml +84 -0
- policyengine_us/tests/policy/baseline/gov/hhs/medicare/savings_programs/msp_benefit_value.yaml +62 -0
- 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
- 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
- policyengine_us/tests/policy/baseline/gov/ssa/revenue/tob_revenue_medicare_hi.yaml +105 -0
- policyengine_us/tests/policy/baseline/gov/ssa/revenue/tob_revenue_oasdi.yaml +86 -0
- policyengine_us/tests/policy/baseline/gov/ssa/revenue/tob_revenue_total.yaml +19 -0
- policyengine_us/tests/policy/baseline/gov/ssa/revenue/tob_tier_split.yaml +90 -0
- policyengine_us/tests/policy/baseline/gov/states/az/tax/income/az_property_tax_credit_agi.yaml +58 -0
- policyengine_us/tests/policy/baseline/gov/states/az/tax/income/integration.yaml +28 -0
- policyengine_us/tests/policy/baseline/gov/states/dc/tax/income/dc_ptc.yaml +27 -0
- policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/credits/food_excise/hi_food_excise_credit.yaml +29 -1
- policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/ia_cdcc.yaml +3 -3
- policyengine_us/tests/policy/baseline/gov/states/ia/tax/income/ia_integration.yaml +31 -1
- policyengine_us/tests/policy/baseline/gov/states/il/dhs/aabd/eligibility/il_aabd_non_financial_eligible_person.yaml +6 -6
- policyengine_us/tests/policy/baseline/gov/states/il/hfs/fpp/integration.yaml +2 -2
- policyengine_us/tests/policy/baseline/gov/states/il/hfs/hbwd/eligibility/il_hbwd_disability_eligible.yaml +18 -5
- policyengine_us/tests/policy/baseline/gov/states/il/hfs/hbwd/eligibility/il_hbwd_eligible.yaml +5 -5
- policyengine_us/tests/policy/baseline/gov/states/il/hfs/hbwd/integration.yaml +8 -8
- policyengine_us/tests/policy/baseline/gov/states/ma/tax/income/gross_income/integration.yaml +28 -0
- policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/integration.yaml +87 -0
- policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/me_dependent_exemption_credit_amount_person.yaml +3 -2
- policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/credits/home_heating/mi_home_heating_credit.yaml +87 -0
- policyengine_us/tests/policy/baseline/gov/states/mi/tax/income/mi_household_resources.yaml +57 -0
- policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/integration.yaml +275 -0
- policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf.yaml +60 -0
- policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_child_care_deduction.yaml +187 -0
- policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_countable_income.yaml +49 -0
- policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_earned_income_deductions.yaml +53 -0
- policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_eligible.yaml +59 -0
- policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_gross_income_eligible.yaml +29 -0
- policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_income_eligible.yaml +49 -0
- policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_maximum_benefit.yaml +47 -0
- policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_percentage_of_need_test.yaml +53 -0
- policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_resources_eligible.yaml +23 -0
- policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_standard_of_need.yaml +71 -0
- policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_standard_of_need_test.yaml +44 -0
- policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/integration.yaml +29 -0
- policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/eligibility/pa_tanf_disregard_eligible.yaml +114 -0
- policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/eligibility/pa_tanf_eligible.yaml +65 -0
- policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/eligibility/pa_tanf_income_eligible.yaml +62 -0
- policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/eligibility/pa_tanf_resources_eligible.yaml +47 -0
- policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/income/pa_tanf_earned_income_after_deductions_person.yaml +81 -0
- policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/integration.yaml +386 -0
- policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/pa_tanf.yaml +53 -0
- policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/pa_tanf_county_group.yaml +63 -0
- policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/pa_tanf_maximum_benefit.yaml +92 -0
- policyengine_us/tests/policy/baseline/gov/states/pa/dhs/tanf/pa_tanf_standard_of_need.yaml +73 -0
- policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/integration.yaml +282 -0
- policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/wi_works.yaml +50 -0
- policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/wi_works_countable_income.yaml +49 -0
- policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/wi_works_countable_resources.yaml +54 -0
- policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/wi_works_eligible.yaml +61 -0
- policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/wi_works_income_eligible.yaml +43 -0
- policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/wi_works_placement.yaml +111 -0
- policyengine_us/tests/policy/baseline/gov/states/wi/dcf/works/wi_works_resources_eligible.yaml +38 -0
- policyengine_us/tests/policy/baseline/gov/states/wv/tax/income/credits/heptc/wv_homestead_excess_property_tax_credit.yaml +31 -0
- policyengine_us/tests/policy/contrib/aca/ptc_700_fpl_cliff.yaml +136 -0
- policyengine_us/tests/test_batched.py +39 -68
- policyengine_us/variables/gov/hhs/medicare/savings_programs/category/is_qi_eligible.py +33 -0
- policyengine_us/variables/gov/hhs/medicare/savings_programs/category/is_qmb_eligible.py +28 -0
- policyengine_us/variables/gov/hhs/medicare/savings_programs/category/is_slmb_eligible.py +33 -0
- policyengine_us/variables/gov/hhs/medicare/savings_programs/category/msp_category.py +33 -0
- policyengine_us/variables/gov/hhs/medicare/savings_programs/eligibility/msp_asset_eligible.py +26 -0
- policyengine_us/variables/gov/hhs/medicare/savings_programs/eligibility/msp_eligible.py +20 -0
- policyengine_us/variables/gov/hhs/medicare/savings_programs/eligibility/msp_income_eligible.py +26 -0
- policyengine_us/variables/gov/hhs/medicare/savings_programs/income/msp_countable_income.py +35 -0
- policyengine_us/variables/gov/hhs/medicare/savings_programs/income/msp_fpg.py +40 -0
- policyengine_us/variables/gov/hhs/medicare/savings_programs/msp.py +15 -0
- policyengine_us/variables/gov/hhs/medicare/savings_programs/msp_benefit_value.py +37 -0
- policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/social_security/taxable_social_security_tier_1.py +58 -0
- policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/irs_gross_income/social_security/taxable_social_security_tier_2.py +17 -0
- policyengine_us/variables/gov/simulation/labor_supply_response/labor_supply_behavioral_response.py +57 -42
- policyengine_us/variables/gov/ssa/revenue/tob_revenue_medicare_hi.py +31 -0
- policyengine_us/variables/gov/ssa/revenue/tob_revenue_oasdi.py +31 -0
- policyengine_us/variables/gov/ssa/revenue/tob_revenue_total.py +44 -0
- policyengine_us/variables/gov/states/az/tax/income/credits/property_tax_credit/az_property_tax_credit_agi.py +53 -0
- policyengine_us/variables/gov/states/dc/tax/income/credits/dc_ptc.py +7 -3
- policyengine_us/variables/gov/states/ia/tax/income/credits/ia_cdcc.py +4 -2
- policyengine_us/variables/gov/states/il/dhs/aabd/eligibility/il_aabd_non_financial_eligible_person.py +23 -5
- policyengine_us/variables/gov/states/il/hfs/fpp/eligibility/il_fpp_eligible.py +1 -1
- policyengine_us/variables/gov/states/il/hfs/hbwd/eligibility/il_hbwd_disability_eligible.py +7 -3
- policyengine_us/variables/gov/states/ma/tax/income/gross_income/ma_part_c_gross_income.py +7 -1
- policyengine_us/variables/gov/states/me/tax/income/credits/dependent_exemption/me_dependent_exemption_credit_amount_person.py +1 -1
- policyengine_us/variables/gov/states/mi/tax/income/mi_household_resources.py +34 -5
- policyengine_us/variables/gov/states/mo/dss/tanf/eligibility/mo_tanf_eligible.py +23 -0
- policyengine_us/variables/gov/states/mo/dss/tanf/eligibility/mo_tanf_gross_income_eligible.py +24 -0
- policyengine_us/variables/gov/states/mo/dss/tanf/eligibility/mo_tanf_income_eligible.py +18 -0
- policyengine_us/variables/gov/states/mo/dss/tanf/eligibility/mo_tanf_percentage_of_need_test.py +20 -0
- policyengine_us/variables/gov/states/mo/dss/tanf/eligibility/mo_tanf_resources_eligible.py +18 -0
- policyengine_us/variables/gov/states/mo/dss/tanf/eligibility/mo_tanf_standard_of_need_test.py +17 -0
- policyengine_us/variables/gov/states/mo/dss/tanf/income/deductions/mo_tanf_child_care_deduction.py +24 -0
- policyengine_us/variables/gov/states/mo/dss/tanf/income/deductions/mo_tanf_earned_income_deductions.py +36 -0
- policyengine_us/variables/gov/states/mo/dss/tanf/income/mo_tanf_countable_income.py +21 -0
- policyengine_us/variables/gov/states/mo/dss/tanf/income/mo_tanf_income_for_need_test.py +23 -0
- policyengine_us/variables/gov/states/mo/dss/tanf/mo_tanf.py +21 -0
- policyengine_us/variables/gov/states/mo/dss/tanf/mo_tanf_maximum_benefit.py +19 -0
- policyengine_us/variables/gov/states/mo/dss/tanf/mo_tanf_standard_of_need.py +23 -0
- policyengine_us/variables/gov/states/mt/tax/income/capital_gains/mt_capital_gains_tax_indiv.py +3 -1
- policyengine_us/variables/gov/states/mt/tax/income/capital_gains/mt_capital_gains_tax_joint.py +3 -1
- policyengine_us/variables/gov/states/mt/tax/income/tax_calculation/mt_regular_income_tax_indiv.py +3 -0
- policyengine_us/variables/gov/states/mt/tax/income/tax_calculation/mt_regular_income_tax_joint.py +3 -0
- policyengine_us/variables/gov/states/pa/dhs/tanf/eligibility/pa_tanf_disregard_eligible.py +31 -0
- policyengine_us/variables/gov/states/pa/dhs/tanf/eligibility/pa_tanf_eligible.py +29 -0
- policyengine_us/variables/gov/states/pa/dhs/tanf/eligibility/pa_tanf_income_eligible.py +16 -0
- policyengine_us/variables/gov/states/pa/dhs/tanf/eligibility/pa_tanf_resources_eligible.py +7 -5
- policyengine_us/variables/gov/states/pa/dhs/tanf/income/pa_tanf_countable_earned_income.py +15 -0
- policyengine_us/variables/gov/states/pa/dhs/tanf/income/pa_tanf_countable_income.py +16 -0
- policyengine_us/variables/gov/states/pa/dhs/tanf/income/pa_tanf_earned_income_after_deductions_person.py +27 -0
- policyengine_us/variables/gov/states/pa/dhs/tanf/pa_tanf.py +19 -0
- policyengine_us/variables/gov/states/pa/dhs/tanf/pa_tanf_county_group.py +38 -0
- policyengine_us/variables/gov/states/pa/dhs/tanf/pa_tanf_maximum_benefit.py +30 -0
- policyengine_us/variables/gov/states/pa/dhs/tanf/pa_tanf_standard_of_need.py +30 -0
- policyengine_us/variables/gov/states/wi/dcf/works/eligibility/wi_works_eligible.py +22 -0
- policyengine_us/variables/gov/states/wi/dcf/works/eligibility/wi_works_income_eligible.py +20 -0
- policyengine_us/variables/gov/states/wi/dcf/works/eligibility/wi_works_resources_eligible.py +18 -0
- policyengine_us/variables/gov/states/wi/dcf/works/income/wi_works_countable_income.py +18 -0
- policyengine_us/variables/gov/states/wi/dcf/works/resources/wi_works_countable_resources.py +21 -0
- policyengine_us/variables/gov/states/wi/dcf/works/wi_works.py +19 -0
- policyengine_us/variables/gov/states/wi/dcf/works/wi_works_placement.py +45 -0
- policyengine_us/variables/gov/states/wv/tax/income/credits/heptc/wv_homestead_excess_property_tax_credit.py +3 -3
- policyengine_us/variables/gov/states/wv/tax/income/credits/heptc/wv_homestead_excess_property_tax_credit_eligible.py +5 -2
- {policyengine_us-1.458.0.dist-info → policyengine_us-1.465.0.dist-info}/METADATA +1 -1
- {policyengine_us-1.458.0.dist-info → policyengine_us-1.465.0.dist-info}/RECORD +186 -62
- policyengine_us/parameters/gov/states/il/dhs/aabd/aged_age_threshold.yaml +0 -11
- policyengine_us/parameters/gov/states/mo/dss/tanf/income_limit.yaml +0 -26
- policyengine_us/parameters/gov/states/pa/dhs/tanf/cash_assistance/age_limit.yaml +0 -11
- policyengine_us/parameters/gov/states/pa/dhs/tanf/pregnancy_eligibility/age_limit.yaml +0 -9
- policyengine_us/tests/policy/baseline/gov/states/il/dhs/aabd/eligibility/il_aabd_aged_blind_disabled_person.yaml +0 -39
- policyengine_us/tests/policy/baseline/gov/states/mo/dss/tanf/mo_tanf_income_limit.yaml +0 -23
- policyengine_us/tests/policy/baseline/gov/states/pa/tanf/cash_assistance/pa_tanf_age_eligible.yaml +0 -44
- policyengine_us/tests/policy/baseline/gov/states/pa/tanf/pregnancy_eligibility/pa_tanf_pregnancy_eligibility.yaml +0 -59
- policyengine_us/tests/policy/baseline/gov/states/pa/tax/income/dhs/tanf/eligibility/pa_tanf_resources_eligible.yaml +0 -24
- policyengine_us/variables/gov/states/il/dhs/aabd/eligibility/il_aabd_aged_blind_disabled_person.py +0 -22
- policyengine_us/variables/gov/states/mo/dss/tanf/mo_tanf_income_limit.py +0 -18
- policyengine_us/variables/gov/states/pa/dhs/tanf/cash_assistance/pa_tanf_age_eligible.py +0 -22
- policyengine_us/variables/gov/states/pa/dhs/tanf/eligibility/pa_tanf_countable_resources.py +0 -10
- policyengine_us/variables/gov/states/pa/dhs/tanf/eligibility/pregnancy_eligibility/age_eligibility.py +0 -22
- {policyengine_us-1.458.0.dist-info → policyengine_us-1.465.0.dist-info}/WHEEL +0 -0
- {policyengine_us-1.458.0.dist-info → policyengine_us-1.465.0.dist-info}/entry_points.txt +0 -0
- {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
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
[
|
|
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
|
|
77
|
-
if "baseline" in str(base_path) and
|
|
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
|
-
|
|
84
|
-
|
|
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
|
-
|
|
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
|
-
|
|
94
|
+
batch.append(str(gov_item))
|
|
101
95
|
elif gov_item.suffix == ".yaml":
|
|
102
|
-
|
|
96
|
+
batch.append(str(gov_item))
|
|
103
97
|
else:
|
|
104
98
|
# Other non-gov directories
|
|
105
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
142
|
-
return [
|
|
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
|
policyengine_us/variables/gov/hhs/medicare/savings_programs/eligibility/msp_income_eligible.py
ADDED
|
@@ -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
|
+
)
|