diff --git a/changelog.d/ky-hb13-hb152-graduated-income-tax.added.md b/changelog.d/ky-hb13-hb152-graduated-income-tax.added.md new file mode 100644 index 00000000000..fb7303785c2 --- /dev/null +++ b/changelog.d/ky-hb13-hb152-graduated-income-tax.added.md @@ -0,0 +1 @@ +Added Kentucky HB 13 and HB 152 graduated income tax reforms with cliff design. diff --git a/policyengine_us/parameters/gov/contrib/states/ky/hb13/brackets.yaml b/policyengine_us/parameters/gov/contrib/states/ky/hb13/brackets.yaml new file mode 100644 index 00000000000..063bc2876b2 --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/ky/hb13/brackets.yaml @@ -0,0 +1,21 @@ +description: Kentucky HB 13 graduated income tax brackets for income at or below the cliff threshold. + +metadata: + type: marginal_rate + threshold_unit: currency-USD + rate_unit: /1 + period: year + label: Kentucky HB 13 graduated income tax brackets + reference: + - title: Kentucky HB 13 (2026 Session), Section 1, KRS 141.020(2) + href: https://apps.legislature.ky.gov/recorddocuments/bill/26RS/hb13/orig_bill.pdf#page=1 + +brackets: + - threshold: + 2027-01-01: 0 + rate: + 2027-01-01: 0.035 + - threshold: + 2027-01-01: 250_000 + rate: + 2027-01-01: 0.06 diff --git a/policyengine_us/parameters/gov/contrib/states/ky/hb13/cliff_threshold.yaml b/policyengine_us/parameters/gov/contrib/states/ky/hb13/cliff_threshold.yaml new file mode 100644 index 00000000000..42ab7c9252d --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/ky/hb13/cliff_threshold.yaml @@ -0,0 +1,12 @@ +description: Kentucky House Bill 13 sets this as the income threshold above which the flat rate applies to the entire income. + +values: + 2027-01-01: 300_000 + +metadata: + unit: currency-USD + period: year + label: Kentucky HB 13 cliff threshold + reference: + - title: Kentucky HB 13 (2026 Session), Section 1, KRS 141.020(2) + href: https://apps.legislature.ky.gov/recorddocuments/bill/26RS/hb13/orig_bill.pdf#page=1 diff --git a/policyengine_us/parameters/gov/contrib/states/ky/hb13/flat_rate.yaml b/policyengine_us/parameters/gov/contrib/states/ky/hb13/flat_rate.yaml new file mode 100644 index 00000000000..565d34adbf8 --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/ky/hb13/flat_rate.yaml @@ -0,0 +1,12 @@ +description: Kentucky HB 13 flat rate applied to entire income when income exceeds the cliff threshold. + +values: + 2027-01-01: 0.06 + +metadata: + unit: /1 + period: year + label: Kentucky HB 13 flat rate for high earners + reference: + - title: Kentucky HB 13 (2026 Session), Section 1, KRS 141.020(2) + href: https://apps.legislature.ky.gov/recorddocuments/bill/26RS/hb13/orig_bill.pdf#page=1 diff --git a/policyengine_us/parameters/gov/contrib/states/ky/hb13/in_effect.yaml b/policyengine_us/parameters/gov/contrib/states/ky/hb13/in_effect.yaml new file mode 100644 index 00000000000..a611f80d1eb --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/ky/hb13/in_effect.yaml @@ -0,0 +1,14 @@ +description: Whether Kentucky HB 13 graduated income tax reform is in effect. + +values: + 0000-01-01: false + +metadata: + unit: bool + label: Kentucky HB 13 graduated income tax reform in effect + period: year + reference: + - title: Kentucky HB 13 (2026 Session), Section 1, KRS 141.020(2) + href: https://apps.legislature.ky.gov/recorddocuments/bill/26RS/hb13/orig_bill.pdf#page=1 + - title: Kentucky Legislature - HB 13 (bill status) + href: https://apps.legislature.ky.gov/record/26RS/hb13.html diff --git a/policyengine_us/parameters/gov/contrib/states/ky/hb152/brackets.yaml b/policyengine_us/parameters/gov/contrib/states/ky/hb152/brackets.yaml new file mode 100644 index 00000000000..d9ec745e6c1 --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/ky/hb152/brackets.yaml @@ -0,0 +1,25 @@ +description: Kentucky HB 152 graduated income tax brackets for income at or below the cliff threshold. + +metadata: + type: marginal_rate + threshold_unit: currency-USD + rate_unit: /1 + period: year + label: Kentucky HB 152 graduated income tax brackets + reference: + - title: Kentucky HB 152 (2026 Session), Section 1, KRS 141.020(2) + href: https://apps.legislature.ky.gov/recorddocuments/bill/26RS/hb152/orig_bill.pdf#page=1 + +brackets: + - threshold: + 2027-01-01: 0 + rate: + 2027-01-01: 0.04 + - threshold: + 2027-01-01: 100_000 + rate: + 2027-01-01: 0.05 + - threshold: + 2027-01-01: 125_000 + rate: + 2027-01-01: 0.06 diff --git a/policyengine_us/parameters/gov/contrib/states/ky/hb152/cliff_threshold.yaml b/policyengine_us/parameters/gov/contrib/states/ky/hb152/cliff_threshold.yaml new file mode 100644 index 00000000000..f745143fbb0 --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/ky/hb152/cliff_threshold.yaml @@ -0,0 +1,12 @@ +description: Kentucky House Bill 152 sets this as the income threshold at or above which the flat rate applies to the entire income. + +values: + 2027-01-01: 150_000 + +metadata: + unit: currency-USD + period: year + label: Kentucky HB 152 cliff threshold + reference: + - title: Kentucky HB 152 (2026 Session), Section 1, KRS 141.020(2) + href: https://apps.legislature.ky.gov/recorddocuments/bill/26RS/hb152/orig_bill.pdf#page=1 diff --git a/policyengine_us/parameters/gov/contrib/states/ky/hb152/flat_rate.yaml b/policyengine_us/parameters/gov/contrib/states/ky/hb152/flat_rate.yaml new file mode 100644 index 00000000000..c972cd3356b --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/ky/hb152/flat_rate.yaml @@ -0,0 +1,12 @@ +description: Kentucky HB 152 flat rate applied to entire income when income exceeds the cliff threshold. + +values: + 2027-01-01: 0.06 + +metadata: + unit: /1 + period: year + label: Kentucky HB 152 flat rate for high earners + reference: + - title: Kentucky HB 152 (2026 Session), Section 1, KRS 141.020(2) + href: https://apps.legislature.ky.gov/recorddocuments/bill/26RS/hb152/orig_bill.pdf#page=1 diff --git a/policyengine_us/parameters/gov/contrib/states/ky/hb152/in_effect.yaml b/policyengine_us/parameters/gov/contrib/states/ky/hb152/in_effect.yaml new file mode 100644 index 00000000000..fe86c43e10e --- /dev/null +++ b/policyengine_us/parameters/gov/contrib/states/ky/hb152/in_effect.yaml @@ -0,0 +1,14 @@ +description: Whether Kentucky HB 152 graduated income tax reform is in effect. + +values: + 0000-01-01: false + +metadata: + unit: bool + label: Kentucky HB 152 graduated income tax reform in effect + period: year + reference: + - title: Kentucky HB 152 (2026 Session), Section 1, KRS 141.020(2) + href: https://apps.legislature.ky.gov/recorddocuments/bill/26RS/hb152/orig_bill.pdf#page=1 + - title: Kentucky Legislature - HB 152 (bill status) + href: https://apps.legislature.ky.gov/record/26RS/hb152.html diff --git a/policyengine_us/reforms/reforms.py b/policyengine_us/reforms/reforms.py index 8cf12ebddbc..31a4b214efc 100644 --- a/policyengine_us/reforms/reforms.py +++ b/policyengine_us/reforms/reforms.py @@ -151,6 +151,9 @@ from .cdcc import ( create_cdcc_single_parent_work_requirement_reform, ) +from .states.ky.graduated_income_tax import ( + create_ky_graduated_income_tax_reform, +) from .states.pa.ctc import ( create_pa_ctc_flat_amount_reform, create_pa_ctc_match_reform, @@ -355,6 +358,9 @@ def create_structural_reforms_from_parameters(parameters, period): cdcc_single_parent_work_requirement = ( create_cdcc_single_parent_work_requirement_reform(parameters, period) ) + ky_graduated_income_tax = create_ky_graduated_income_tax_reform( + parameters, period + ) pa_ctc_flat_amount = create_pa_ctc_flat_amount_reform(parameters, period) pa_ctc_match = create_pa_ctc_match_reform(parameters, period) ct_sb100 = create_ct_sb100_reform(parameters, period) @@ -431,6 +437,7 @@ def create_structural_reforms_from_parameters(parameters, period): aca_ptc_simplified_bracket, aca_ptc_700_fpl_cliff, cdcc_single_parent_work_requirement, + ky_graduated_income_tax, pa_ctc_flat_amount, pa_ctc_match, ct_hb5009, diff --git a/policyengine_us/reforms/states/ky/__init__.py b/policyengine_us/reforms/states/ky/__init__.py new file mode 100644 index 00000000000..78ded887d71 --- /dev/null +++ b/policyengine_us/reforms/states/ky/__init__.py @@ -0,0 +1,4 @@ +from policyengine_us.reforms.states.ky.graduated_income_tax import ( + create_ky_graduated_income_tax_reform, + ky_graduated_income_tax, +) diff --git a/policyengine_us/reforms/states/ky/graduated_income_tax/__init__.py b/policyengine_us/reforms/states/ky/graduated_income_tax/__init__.py new file mode 100644 index 00000000000..a035175d9df --- /dev/null +++ b/policyengine_us/reforms/states/ky/graduated_income_tax/__init__.py @@ -0,0 +1,4 @@ +from policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform import ( + create_ky_graduated_income_tax_reform, + ky_graduated_income_tax, +) diff --git a/policyengine_us/reforms/states/ky/graduated_income_tax/ky_graduated_income_tax_reform.py b/policyengine_us/reforms/states/ky/graduated_income_tax/ky_graduated_income_tax_reform.py new file mode 100644 index 00000000000..5996b03bc57 --- /dev/null +++ b/policyengine_us/reforms/states/ky/graduated_income_tax/ky_graduated_income_tax_reform.py @@ -0,0 +1,141 @@ +from policyengine_us.model_api import * +from policyengine_core.periods import period as period_ + + +def create_ky_graduated_income_tax() -> Reform: + """ + Creates reform for Kentucky HB 13 and HB 152 graduated income tax. + + Both bills amend KRS 141.020(2) to implement graduated brackets + with a "cliff" design where above a threshold, the flat rate + applies to the ENTIRE income (not just marginal). + + See parameter files under gov/contrib/states/ky/hb13/ and hb152/ + for specific rates, thresholds, and effective dates. + """ + + def calculate_graduated_tax_with_cliff( + taxable_income, p_hb13, p_hb152, p_baseline + ): + """ + Calculate tax using graduated brackets with cliff design. + + HB 13 takes precedence if both are active. Each bill applies + its flat rate to the entire income when the cliff threshold + is exceeded; otherwise graduated brackets apply. + """ + hb13_active = p_hb13.in_effect + hb152_active = p_hb152.in_effect + + # HB 13 calculation + hb13_above_cliff = taxable_income > p_hb13.cliff_threshold + hb13_graduated_tax = p_hb13.brackets.calc(taxable_income) + hb13_flat_tax = taxable_income * p_hb13.flat_rate + hb13_tax = where(hb13_above_cliff, hb13_flat_tax, hb13_graduated_tax) + + # HB 152 calculation + hb152_above_cliff = taxable_income >= p_hb152.cliff_threshold + hb152_graduated_tax = p_hb152.brackets.calc(taxable_income) + hb152_flat_tax = taxable_income * p_hb152.flat_rate + hb152_tax = where( + hb152_above_cliff, hb152_flat_tax, hb152_graduated_tax + ) + + # Baseline calculation + baseline_tax = taxable_income * p_baseline.rate + + # Apply appropriate calculation based on which reform is active + # HB 13 takes precedence if both are somehow active + return where( + hb13_active, + hb13_tax, + where(hb152_active, hb152_tax, baseline_tax), + ) + + class ky_income_tax_before_non_refundable_credits_indiv(Variable): + value_type = float + entity = Person + label = "Kentucky income tax before non-refundable credits when married couples are filing separately" + unit = USD + definition_period = YEAR + defined_for = StateCode.KY + reference = ( + "https://apps.legislature.ky.gov/recorddocuments/bill/26RS/hb13/orig_bill.pdf#page=1", + "https://apps.legislature.ky.gov/recorddocuments/bill/26RS/hb152/orig_bill.pdf#page=1", + ) + + def formula(person, period, parameters): + taxable_income = person("ky_taxable_income_indiv", period) + p_hb13 = parameters(period).gov.contrib.states.ky.hb13 + p_hb152 = parameters(period).gov.contrib.states.ky.hb152 + p_baseline = parameters(period).gov.states.ky.tax.income + + return calculate_graduated_tax_with_cliff( + taxable_income, p_hb13, p_hb152, p_baseline + ) + + class ky_income_tax_before_non_refundable_credits_joint(Variable): + value_type = float + entity = Person + label = "Kentucky income tax before non-refundable credits when married filing jointly" + unit = USD + definition_period = YEAR + defined_for = StateCode.KY + reference = ( + "https://apps.legislature.ky.gov/recorddocuments/bill/26RS/hb13/orig_bill.pdf#page=1", + "https://apps.legislature.ky.gov/recorddocuments/bill/26RS/hb152/orig_bill.pdf#page=1", + ) + + def formula(person, period, parameters): + taxable_income = person("ky_taxable_income_joint", period) + p_hb13 = parameters(period).gov.contrib.states.ky.hb13 + p_hb152 = parameters(period).gov.contrib.states.ky.hb152 + p_baseline = parameters(period).gov.states.ky.tax.income + + return calculate_graduated_tax_with_cliff( + taxable_income, p_hb13, p_hb152, p_baseline + ) + + class reform(Reform): + def apply(self): + self.update_variable( + ky_income_tax_before_non_refundable_credits_indiv + ) + self.update_variable( + ky_income_tax_before_non_refundable_credits_joint + ) + + return reform + + +def create_ky_graduated_income_tax_reform( + parameters, period, bypass: bool = False +): + if bypass: + return create_ky_graduated_income_tax() + + p_hb13 = parameters.gov.contrib.states.ky.hb13 + p_hb152 = parameters.gov.contrib.states.ky.hb152 + + reform_active = False + current_period = period_(period) + + # Check if either reform will be active in the next 5 years + for i in range(5): + if ( + p_hb13(current_period).in_effect + or p_hb152(current_period).in_effect + ): + reform_active = True + break + current_period = current_period.offset(1, "year") + + if reform_active: + return create_ky_graduated_income_tax() + else: + return None + + +ky_graduated_income_tax = create_ky_graduated_income_tax_reform( + None, None, bypass=True +) diff --git a/policyengine_us/tests/policy/contrib/states/ky/hb13/ky_hb13.yaml b/policyengine_us/tests/policy/contrib/states/ky/hb13/ky_hb13.yaml new file mode 100644 index 00000000000..8c5b544db1b --- /dev/null +++ b/policyengine_us/tests/policy/contrib/states/ky/hb13/ky_hb13.yaml @@ -0,0 +1,415 @@ +# Test Kentucky HB 13 Graduated Income Tax Reform +# For 2027+: 3.5% up to $250k, 6% $250k-$300k, flat 6% on ALL income if >$300k + +- name: KY HB 13 - income below $250k threshold (single filing) + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 100_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # 100000 * 0.035 = 3500 + ky_income_tax_before_non_refundable_credits_indiv: 3500 + +- name: KY HB 13 - income between $250k and $300k (graduated rates) + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 280_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # 250000 * 0.035 + 30000 * 0.06 = 8750 + 1800 = 10550 + ky_income_tax_before_non_refundable_credits_indiv: 10550 + +- name: KY HB 13 - income at exactly $300k threshold (still graduated) + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 300_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # 250000 * 0.035 + 50000 * 0.06 = 8750 + 3000 = 11750 + ky_income_tax_before_non_refundable_credits_indiv: 11750 + +- name: KY HB 13 - income above $300k (cliff - flat 6% on ENTIRE income) + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 300_001 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # CLIFF: 300001 * 0.06 = 18000.06 + ky_income_tax_before_non_refundable_credits_indiv: 18000.06 + +- name: KY HB 13 - high income above cliff + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 500_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # CLIFF: 500000 * 0.06 = 30000 + ky_income_tax_before_non_refundable_credits_indiv: 30000 + +- name: KY HB 13 - joint filing above cliff + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_joint: 400_000 + person2: + age: 43 + ky_taxable_income_joint: 0 + tax_units: + tax_unit: + members: [person1, person2] + filing_status: JOINT + households: + household: + members: [person1, person2] + state_code: KY + output: + # CLIFF: 400000 * 0.06 = 24000 (on person1 who has the income) + ky_income_tax_before_non_refundable_credits_joint: + - 24000 + - 0 + +- name: KY HB 13 - reform not in effect uses baseline + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: false + people: + person1: + age: 45 + ky_taxable_income_indiv: 500_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # Baseline 2027 rate: 3.5% -> 500000 * 0.035 = 17500 + ky_income_tax_before_non_refundable_credits_indiv: 17500 + +- name: KY HB 13 - zero income + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 0 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + ky_income_tax_before_non_refundable_credits_indiv: 0 + +- name: KY HB 13 - income at exactly $250k bracket boundary + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 250_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # 250000 * 0.035 = 8750 + ky_income_tax_before_non_refundable_credits_indiv: 8750 + +- name: KY HB 13 - cliff notch just below $300k + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 299_999 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # Just below cliff: 250000*0.035 + 49999*0.06 = 8750 + 2999.94 = 11749.94 + ky_income_tax_before_non_refundable_credits_indiv: 11749.94 + +- name: KY HB 13 - both reforms active (HB 13 takes precedence) + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 200_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # HB 13 takes precedence: 200000 * 0.035 = 7000 + # (HB 152 would give: 100000*0.04 + 25000*0.05 + 25000*0.06 + 50000*0.06 = 4000+1250+1500+3000 = 9750) + ky_income_tax_before_non_refundable_credits_indiv: 7000 + +- name: KY HB 13 - non-KY resident gets zero + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 500_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: CA + output: + ky_income_tax_before_non_refundable_credits_indiv: 0 + +- name: KY HB 13 - joint filing with graduated rates + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_joint: 280_000 + person2: + age: 43 + ky_taxable_income_joint: 0 + tax_units: + tax_unit: + members: [person1, person2] + filing_status: JOINT + households: + household: + members: [person1, person2] + state_code: KY + output: + # 250000*0.035 + 30000*0.06 = 8750 + 1800 = 10550 + ky_income_tax_before_non_refundable_credits_joint: + - 10550 + - 0 + +- name: KY HB 13 - joint filing at exactly $300k cliff (still graduated) + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_joint: 300_000 + person2: + age: 43 + ky_taxable_income_joint: 0 + tax_units: + tax_unit: + members: [person1, person2] + filing_status: JOINT + households: + household: + members: [person1, person2] + state_code: KY + output: + # At $300k exactly, strict > means graduated rates apply + # 250000*0.035 + 50000*0.06 = 8750 + 3000 = 11750 + ky_income_tax_before_non_refundable_credits_joint: + - 11750 + - 0 + +- name: KY HB 13 - joint filing $1 above cliff (flat 6% on entire income) + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_joint: 300_001 + person2: + age: 43 + ky_taxable_income_joint: 0 + tax_units: + tax_unit: + members: [person1, person2] + filing_status: JOINT + households: + household: + members: [person1, person2] + state_code: KY + output: + # CLIFF: 300001 * 0.06 = 18000.06 + ky_income_tax_before_non_refundable_credits_joint: + - 18000.06 + - 0 + +- name: KY HB 13 - end-to-end high earner through ky_income_tax + period: 2027 + absolute_error_margin: 1 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 500_000 + ky_taxable_income_joint: 500_000 + person2: + age: 43 + ky_taxable_income_indiv: 0 + ky_taxable_income_joint: 0 + tax_units: + tax_unit: + members: [person1, person2] + filing_status: JOINT + adjusted_gross_income: 500_000 + households: + household: + members: [person1, person2] + state_code: KY + output: + # CLIFF: 500000 * 0.06 = 30000 + ky_income_tax_before_non_refundable_credits_joint: + - 30000 + - 0 + # High earner: family size credit rate is 0%, so no credit reduction + # Verify reform flows through to final ky_income_tax + ky_income_tax: 30000 + +- name: KY HB 13 - filing optimization chooses separate filing + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 280_000 + ky_taxable_income_joint: 300_000 + person2: + age: 43 + ky_taxable_income_indiv: 20_000 + ky_taxable_income_joint: 0 + tax_units: + tax_unit: + members: [person1, person2] + filing_status: JOINT + households: + household: + members: [person1, person2] + state_code: KY + output: + # Separate: p1=250k*3.5%+30k*6%=10550, p2=20k*3.5%=700, total=11250 + # Joint: p1=250k*3.5%+50k*6%=11750, p2=0, total=11750 + # ky_files_separately = (11250 < 11750) = True + ky_files_separately: true diff --git a/policyengine_us/tests/policy/contrib/states/ky/hb152/ky_hb152.yaml b/policyengine_us/tests/policy/contrib/states/ky/hb152/ky_hb152.yaml new file mode 100644 index 00000000000..7fb8909709a --- /dev/null +++ b/policyengine_us/tests/policy/contrib/states/ky/hb152/ky_hb152.yaml @@ -0,0 +1,429 @@ +# Test Kentucky HB 152 Graduated Income Tax Reform +# For 2027+: 4% up to $100k, 5% $100k-$125k, 6% $125k-$150k, +# flat 6% on ALL income if >= $150k + +- name: KY HB 152 - income below $100k threshold + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 50_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # 50000 * 0.04 = 2000 + ky_income_tax_before_non_refundable_credits_indiv: 2000 + +- name: KY HB 152 - income between $100k and $125k + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 110_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # 100000 * 0.04 + 10000 * 0.05 = 4000 + 500 = 4500 + ky_income_tax_before_non_refundable_credits_indiv: 4500 + +- name: KY HB 152 - income between $125k and $150k + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 140_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # 100000 * 0.04 + 25000 * 0.05 + 15000 * 0.06 = 4000 + 1250 + 900 = 6150 + ky_income_tax_before_non_refundable_credits_indiv: 6150 + +- name: KY HB 152 - income at exactly $150k threshold (cliff - flat 6%) + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 150_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # Bill says "$150,000 or more" triggers flat rate: 150000 * 0.06 = 9000 + ky_income_tax_before_non_refundable_credits_indiv: 9000 + +- name: KY HB 152 - income above $150k (cliff - flat 6% on ENTIRE income) + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 150_001 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # CLIFF: 150001 * 0.06 = 9000.06 + ky_income_tax_before_non_refundable_credits_indiv: 9000.06 + +- name: KY HB 152 - high income above cliff + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 300_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # CLIFF: 300000 * 0.06 = 18000 + ky_income_tax_before_non_refundable_credits_indiv: 18000 + +- name: KY HB 152 - joint filing above cliff + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_joint: 200_000 + person2: + age: 43 + ky_taxable_income_joint: 0 + tax_units: + tax_unit: + members: [person1, person2] + filing_status: JOINT + households: + household: + members: [person1, person2] + state_code: KY + output: + # CLIFF: 200000 * 0.06 = 12000 (on person1) + ky_income_tax_before_non_refundable_credits_joint: + - 12000 + - 0 + +- name: KY HB 152 - reform not in effect uses baseline + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: false + people: + person1: + age: 45 + ky_taxable_income_indiv: 200_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # Baseline 2027 rate: 3.5% -> 200000 * 0.035 = 7000 + ky_income_tax_before_non_refundable_credits_indiv: 7000 + +- name: KY HB 152 - cliff notch effect demonstration + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 149_999 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # Just below cliff: 100000*0.04 + 25000*0.05 + 24999*0.06 = 4000+1250+1499.94 = 6749.94 + ky_income_tax_before_non_refundable_credits_indiv: 6749.94 + +- name: KY HB 152 - zero income + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 0 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + ky_income_tax_before_non_refundable_credits_indiv: 0 + +- name: KY HB 152 - income at exactly $100k bracket boundary + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 100_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # 100000 * 0.04 = 4000 + ky_income_tax_before_non_refundable_credits_indiv: 4000 + +- name: KY HB 152 - income at exactly $125k bracket boundary + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 125_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # 100000 * 0.04 + 25000 * 0.05 = 4000 + 1250 = 5250 + ky_income_tax_before_non_refundable_credits_indiv: 5250 + +- name: KY HB 152 - non-KY resident gets zero + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 300_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: CA + output: + ky_income_tax_before_non_refundable_credits_indiv: 0 + +- name: KY HB 152 - joint filing with graduated rates + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_joint: 140_000 + person2: + age: 43 + ky_taxable_income_joint: 0 + tax_units: + tax_unit: + members: [person1, person2] + filing_status: JOINT + households: + household: + members: [person1, person2] + state_code: KY + output: + # 100000*0.04 + 25000*0.05 + 15000*0.06 = 4000 + 1250 + 900 = 6150 + ky_income_tax_before_non_refundable_credits_joint: + - 6150 + - 0 + +- name: KY HB 152 - joint filing $1 below cliff (graduated) + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_joint: 149_999 + person2: + age: 43 + ky_taxable_income_joint: 0 + tax_units: + tax_unit: + members: [person1, person2] + filing_status: JOINT + households: + household: + members: [person1, person2] + state_code: KY + output: + # Just below cliff: 100000*0.04 + 25000*0.05 + 24999*0.06 = 4000+1250+1499.94 = 6749.94 + ky_income_tax_before_non_refundable_credits_joint: + - 6749.94 + - 0 + +- name: KY HB 152 - joint filing at exactly $150k cliff (flat 6%) + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_joint: 150_000 + person2: + age: 43 + ky_taxable_income_joint: 0 + tax_units: + tax_unit: + members: [person1, person2] + filing_status: JOINT + households: + household: + members: [person1, person2] + state_code: KY + output: + # Bill says "$150,000 or more" triggers flat rate: 150000 * 0.06 = 9000 + ky_income_tax_before_non_refundable_credits_joint: + - 9000 + - 0 + +- name: KY HB 152 - end-to-end high earner through ky_income_tax + period: 2027 + absolute_error_margin: 1 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 300_000 + ky_taxable_income_joint: 300_000 + person2: + age: 43 + ky_taxable_income_indiv: 0 + ky_taxable_income_joint: 0 + tax_units: + tax_unit: + members: [person1, person2] + filing_status: JOINT + adjusted_gross_income: 300_000 + households: + household: + members: [person1, person2] + state_code: KY + output: + # CLIFF: 300000 * 0.06 = 18000 + ky_income_tax_before_non_refundable_credits_joint: + - 18000 + - 0 + # High earner: family size credit rate is 0%, so no credit reduction + # Verify reform flows through to final ky_income_tax + ky_income_tax: 18000 + +- name: KY HB 152 - both reforms active (HB 13 takes precedence) + period: 2027 + absolute_error_margin: 0.01 + reforms: policyengine_us.reforms.states.ky.graduated_income_tax.ky_graduated_income_tax_reform.ky_graduated_income_tax + input: + gov.contrib.states.ky.hb13.in_effect: true + gov.contrib.states.ky.hb152.in_effect: true + people: + person1: + age: 45 + ky_taxable_income_indiv: 200_000 + tax_units: + tax_unit: + members: [person1] + filing_status: SINGLE + households: + household: + members: [person1] + state_code: KY + output: + # HB 13 takes precedence: 200000 * 0.035 = 7000 + ky_income_tax_before_non_refundable_credits_indiv: 7000