From ce1acac7b9ed5e66c685605cf8ce8b92028b239b Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 13 Oct 2026 08:49:26 -0400 Subject: [PATCH 1/2] Date Hawaii's EITC from 2018 and confine the Act 115 refund to 2021 backdate_parameters copies each parameter's first value back to 2015, so the 2021-dated credit lists and the 2017-dated EITC match paid the Act 115 refund in 2015-2020 and the EITC in 2015-2017. Add 2000-01-01 sentinels, start the nonrefundable EITC list and match in 2018 (Act 107, SLH 2017), and zero the Act 115 amounts outside 2021. Also replace the military reserve pay exclusion cap, which used the 2022 amount for 2015-2021, with each year's N-11 instruction value for 2015-2025. Co-Authored-By: Claude Opus 5.5 --- changelog.d/hi-credit-start-dates.fixed.md | 1 + .../income/credits/act_115_rebate/joint.yaml | 6 +++ .../income/credits/act_115_rebate/single.yaml | 6 +++ .../hi/tax/income/credits/eitc/match.yaml | 9 +++- .../hi/tax/income/credits/non_refundable.yaml | 9 +++- .../hi/tax/income/credits/refundable.yaml | 11 ++++ .../income/subtractions/military_pay/cap.yaml | 50 ++++++++++++------- 7 files changed, 73 insertions(+), 19 deletions(-) create mode 100644 changelog.d/hi-credit-start-dates.fixed.md diff --git a/changelog.d/hi-credit-start-dates.fixed.md b/changelog.d/hi-credit-start-dates.fixed.md new file mode 100644 index 00000000000..9e306adbc1b --- /dev/null +++ b/changelog.d/hi-credit-start-dates.fixed.md @@ -0,0 +1 @@ +Stop paying the Hawaii earned income tax credit before 2018 and the Act 115 refund outside 2021, and use each year's Hawaii military reserve pay exclusion cap for 2015-2025. diff --git a/policyengine_us/parameters/gov/states/hi/tax/income/credits/act_115_rebate/joint.yaml b/policyengine_us/parameters/gov/states/hi/tax/income/credits/act_115_rebate/joint.yaml index 7b320be909d..22ae1b468b4 100644 --- a/policyengine_us/parameters/gov/states/hi/tax/income/credits/act_115_rebate/joint.yaml +++ b/policyengine_us/parameters/gov/states/hi/tax/income/credits/act_115_rebate/joint.yaml @@ -15,8 +15,14 @@ brackets: - threshold: 2021-01-01: -.inf amount: + # Model years start in 2015. Act 115 paid a one-time refund to filers + # of a 2021 Form N-11. + 2000-01-01: 0 2021-01-01: 300 + 2022-01-01: 0 - threshold: 2021-01-01: 200_000 amount: + 2000-01-01: 0 2021-01-01: 100 + 2022-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/hi/tax/income/credits/act_115_rebate/single.yaml b/policyengine_us/parameters/gov/states/hi/tax/income/credits/act_115_rebate/single.yaml index f002f2aff5b..089e4a1d9bc 100644 --- a/policyengine_us/parameters/gov/states/hi/tax/income/credits/act_115_rebate/single.yaml +++ b/policyengine_us/parameters/gov/states/hi/tax/income/credits/act_115_rebate/single.yaml @@ -15,8 +15,14 @@ brackets: - threshold: 2021-01-01: -.inf amount: + # Model years start in 2015. Act 115 paid a one-time refund to filers + # of a 2021 Form N-11. + 2000-01-01: 0 2021-01-01: 300 + 2022-01-01: 0 - threshold: 2021-01-01: 100_000 amount: + 2000-01-01: 0 2021-01-01: 100 + 2022-01-01: 0 diff --git a/policyengine_us/parameters/gov/states/hi/tax/income/credits/eitc/match.yaml b/policyengine_us/parameters/gov/states/hi/tax/income/credits/eitc/match.yaml index fb8d3cad97b..321364fe888 100644 --- a/policyengine_us/parameters/gov/states/hi/tax/income/credits/eitc/match.yaml +++ b/policyengine_us/parameters/gov/states/hi/tax/income/credits/eitc/match.yaml @@ -1,6 +1,9 @@ description: Hawaii matches this percent of the federal EITC. values: - 2017-01-01: 0.2 + # Model years start in 2015. The credit applies to taxable years beginning + # after December 31, 2017. + 2000-01-01: 0 + 2018-01-01: 0.2 2023-01-01: 0.4 2028-01-01: 0.2 metadata: @@ -9,6 +12,10 @@ metadata: reference: - title: Hawaii Income Tax Law, Chapter 235, Section 235-55.75 href: https://files.hawaii.gov/tax/legal/hrs/hrs_235.pdf#page=43 + - title: 2018 Hawaii N-11 Instructions, What's new (Act 107, SLH 2017) + href: https://files.hawaii.gov/tax/forms/2018/n11ins.pdf#page=2 + - title: Hawaii Tax Form N-356 2018 + href: https://web.archive.org/web/20190819110547/http://files.hawaii.gov/tax/forms/2018/n356_i.pdf#page=2 - title: Hawaii Tax Form N-356 2022 href: https://files.hawaii.gov/tax/forms/2022/n356_i.pdf - title: Hawaii Tax Form N-356 2023 diff --git a/policyengine_us/parameters/gov/states/hi/tax/income/credits/non_refundable.yaml b/policyengine_us/parameters/gov/states/hi/tax/income/credits/non_refundable.yaml index 0013368000a..e9c0f7f9ffb 100644 --- a/policyengine_us/parameters/gov/states/hi/tax/income/credits/non_refundable.yaml +++ b/policyengine_us/parameters/gov/states/hi/tax/income/credits/non_refundable.yaml @@ -1,6 +1,9 @@ description: Hawaii provides the following non-refundable tax credits. values: - 2021-01-01: + # Model years start in 2015. Hawaii had no earned income tax credit + # before 2018. + 2000-01-01: [] + 2018-01-01: - hi_eitc 2023-01-01: [] @@ -11,5 +14,9 @@ metadata: reference: - title: Hawaii Revised Statutes Title 14. Taxation 235. Income Tax Law, 235-55.75 Earned income tax credit. # repealed in 2023 href: https://law.justia.com/codes/hawaii/2022/title-14/chapter-235/section-235-55-75/ + - title: 2018 Hawaii N-11 Instructions, What's new (Act 107, SLH 2017) + href: https://files.hawaii.gov/tax/forms/2018/n11ins.pdf#page=2 + - title: 2018 Hawaii Form N-356 Instructions + href: https://web.archive.org/web/20190819110547/http://files.hawaii.gov/tax/forms/2018/n356_i.pdf#page=2 - title: 2025 Hawaii N-11 Instructions href: https://files.hawaii.gov/tax/forms/current/n11ins.pdf diff --git a/policyengine_us/parameters/gov/states/hi/tax/income/credits/refundable.yaml b/policyengine_us/parameters/gov/states/hi/tax/income/credits/refundable.yaml index 264449d0df2..f8b1648881d 100644 --- a/policyengine_us/parameters/gov/states/hi/tax/income/credits/refundable.yaml +++ b/policyengine_us/parameters/gov/states/hi/tax/income/credits/refundable.yaml @@ -1,5 +1,12 @@ description: Hawaii provides the following refundable tax credits. values: + # Model years start in 2015. The Act 115 refund went only to filers of a + # 2021 Form N-11. + 2000-01-01: + - hi_food_excise_credit + - hi_cdcc + - hi_tax_credit_for_low_income_household_renters + 2021-01-01: - hi_food_excise_credit - hi_cdcc @@ -22,6 +29,10 @@ metadata: period: year label: Hawaii refundable tax credits reference: + - title: 2018 Hawaii N-11 Tax Form + href: https://files.hawaii.gov/tax/forms/2018/n11_i.pdf#page=3 + - title: Hawaii Department of Taxation Announcement No. 2022-03, Act 115 Income Tax Refunds + href: https://files.hawaii.gov/tax/news/announce/ann22-03.pdf#page=2 - title: 2022 Hawaii N-11 Tax Form href: https://files.hawaii.gov/tax/forms/2022/n11_i.pdf#page=3 - title: 2021 Hawaii N-11 Tax Form diff --git a/policyengine_us/parameters/gov/states/hi/tax/income/subtractions/military_pay/cap.yaml b/policyengine_us/parameters/gov/states/hi/tax/income/subtractions/military_pay/cap.yaml index 019814a220c..bc3533ef2db 100644 --- a/policyengine_us/parameters/gov/states/hi/tax/income/subtractions/military_pay/cap.yaml +++ b/policyengine_us/parameters/gov/states/hi/tax/income/subtractions/military_pay/cap.yaml @@ -1,8 +1,16 @@ description: Hawaii caps the military reserve or Hawaii national guard duty pay exclusion at this amount. -values: - 2021-01-01: 7_345 +values: + 2015-01-01: 6_198 + 2016-01-01: 6_279 + 2017-01-01: 6_410 + 2018-01-01: 6_564 + 2019-01-01: 6_735 + 2020-01-01: 6_943 + 2021-01-01: 7_152 + 2022-01-01: 7_345 2023-01-01: 7_683 2024-01-01: 8_082 + 2025-01-01: 8_636 metadata: uprating: gov.irs.uprating @@ -10,21 +18,29 @@ metadata: period: year unit: currency-USD reference: - - title: Hawaii Resident Income Tax Instructions N-11 Rev.2022 - href: https://files.hawaii.gov/tax/forms/2022/n11ins.pdf#page=13 - - title: Hawaii 2022 Individual Income Tax Return N-11 From Rev.2022 - href: https://files.hawaii.gov/tax/forms/2022/n11_i.pdf#page=2 - - title: Hawaii Resident Income Tax Instructions N-11 Rev.2021 + # The value of the subtraction is derived from compensation for + # performance of duty, equivalent to pay received for forty-eight drills + - title: Hawaii Income Tax Law, Chapter 235, Section 235-7, (a) (7) + href: https://files.hawaii.gov/tax/legal/hrs/hrs_235.pdf#page=22 + - title: Hawaii Resident Income Tax Instructions N-11 Rev.2015, Line 15 + href: https://web.archive.org/web/20160207173809/http://files.hawaii.gov/tax/forms/2015/n11ins.pdf#page=14 + - title: Hawaii Resident Income Tax Instructions N-11 Rev.2016, Line 15 + href: https://web.archive.org/web/20170214234012/http://files.hawaii.gov/tax/forms/2016/n11ins.pdf#page=15 + - title: Hawaii Resident Income Tax Instructions N-11 Rev.2017, Line 15 + href: https://web.archive.org/web/20180417023253/http://files.hawaii.gov/tax/forms/2017/n11ins.pdf#page=15 + - title: Hawaii Resident Income Tax Instructions N-11 Rev.2018, Line 15 + href: https://files.hawaii.gov/tax/forms/2018/n11ins.pdf#page=15 + - title: Hawaii Resident Income Tax Instructions N-11 Rev.2019, Line 15 + href: https://files.hawaii.gov/tax/forms/2019/n11ins.pdf#page=15 + - title: Hawaii Resident Income Tax Instructions N-11 Rev.2020, Line 15 + href: https://files.hawaii.gov/tax/forms/2020/n11ins.pdf#page=15 + - title: Hawaii Resident Income Tax Instructions N-11 Rev.2021, Line 15 href: https://files.hawaii.gov/tax/forms/2021/n11ins.pdf#page=13 - - title: Hawaii 2021 Individual Income Tax Return N-11 From Rev.2021 - href: https://files.hawaii.gov/tax/forms/2021/n11_i.pdf#page=2 - # The value of the subtraction is derived from compensation for - # performance of duty, equivalent to pay received for forty-eight drills - - title: Hawaii Income Tax Law, Chapter 235, Section 235-7, (a) (7) - href: https://files.hawaii.gov/tax/legal/hrs/hrs_235.pdf#page=22 - - title: Hawaii Resident Income Tax Instructions N-11 Rev.2023 + - title: Hawaii Resident Income Tax Instructions N-11 Rev.2022, Line 15 + href: https://files.hawaii.gov/tax/forms/2022/n11ins.pdf#page=13 + - title: Hawaii Resident Income Tax Instructions N-11 Rev.2023, Line 15 href: https://files.hawaii.gov/tax/forms/2023/n11ins.pdf#page=13 - - title: Hawaii Resident Income Tax Instructions N-11 Rev.2024 + - title: Hawaii Resident Income Tax Instructions N-11 Rev.2024, Line 15 href: https://files.hawaii.gov/tax/forms/2024/n11ins.pdf#page=13 - - title: 2025 Hawaii N-11 Instructions Military Pay Exclusion - href: https://files.hawaii.gov/tax/forms/current/n11ins.pdf#page=13 + - title: Hawaii Resident Income Tax Instructions N-11 Rev.2025, Line 15 + href: https://files.hawaii.gov/tax/forms/2025/n11ins.pdf#page=13 From 4aab609d0fd4da4a73c5543fa0ef10eb279b6144 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 13 Oct 2026 09:21:00 -0400 Subject: [PATCH 2/2] Test Hawaii credit start dates and military pay caps by year YAML cases at 2016, 2017, 2018, 2020, 2021 and 2022 for the Hawaii EITC, the Act 115 refund and the credit lists, and military pay exclusion caps for 2015, 2018, 2020, 2021, 2022 and 2025; the 2021 cap case now expects the 2021 instruction amount ($7,152). A grid and Hypothesis property test checks the date invariants for 2015-2026 and compares the exclusion with each year's published cap. Co-Authored-By: Claude Opus 5.5 --- .../tax/income/credits/hi_act_115_rebate.yaml | 49 ++++ .../income/credits/hi_credit_start_dates.yaml | 146 +++++++++++ .../states/hi/tax/income/credits/hi_eitc.yaml | 59 +++++ .../hi_military_pay_exclusion.yaml | 46 ++++ .../test_hi_credit_start_dates_properties.py | 236 ++++++++++++++++++ 5 files changed, 536 insertions(+) create mode 100644 policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/credits/hi_credit_start_dates.yaml create mode 100644 policyengine_us/tests/unit/test_hi_credit_start_dates_properties.py diff --git a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/credits/hi_act_115_rebate.yaml b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/credits/hi_act_115_rebate.yaml index 13ebfd8d94a..6ca040f88c0 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/credits/hi_act_115_rebate.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/credits/hi_act_115_rebate.yaml @@ -162,3 +162,52 @@ state_code: HI output: hi_act_115_rebate: 0 + +# Act 115 refunds went only to filers of a 2021 Form N-11 (DOTAX +# Announcement 2022-03, p.2). +- name: No refund for 2017 + period: 2017 + input: + adjusted_gross_income: 50_000 + filing_status: SINGLE + state_code: HI + output: + hi_act_115_rebate: 0 + +- name: No refund for 2020 + period: 2020 + input: + adjusted_gross_income: 50_000 + filing_status: SINGLE + state_code: HI + output: + hi_act_115_rebate: 0 + +- name: No refund for 2022 + period: 2022 + input: + adjusted_gross_income: 50_000 + filing_status: SINGLE + state_code: HI + output: + hi_act_115_rebate: 0 + +- name: No refund for joint filers for 2020 + period: 2020 + input: + people: + head: + age: 40 + spouse: + age: 40 + tax_units: + tax_unit: + members: [head, spouse] + adjusted_gross_income: 60_000 + filing_status: JOINT + households: + household: + members: [head, spouse] + state_code: HI + output: + hi_act_115_rebate: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/credits/hi_credit_start_dates.yaml b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/credits/hi_credit_start_dates.yaml new file mode 100644 index 00000000000..f1f3d725874 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/credits/hi_credit_start_dates.yaml @@ -0,0 +1,146 @@ +# A single filer, age 30, with $8,000 of wages in each year around the +# credits' start dates. The federal EITC is on its plateau in each year +# tested (single, no qualifying child), and the Hawaii food/excise credit is +# $100 for federal AGI of $5,000 to $10,000 (Form N-311, 2017-2022). +# Hawaii's EITC applies to taxable years beginning after December 31, 2017 +# (Act 107, SLH 2017; 2018 Form N-356 instructions, p.2). Act 115 (SLH 2022) +# refunds went only to filers of a 2021 Form N-11 (DOTAX Announcement +# 2022-03, p.2). +- name: Case 1, no Hawaii EITC or Act 115 refund in 2017. + period: 2017 + input: + people: + person1: + age: 30 + employment_income: 8_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: HI + output: + eitc: 510 + hi_eitc_potential: 0 + hi_non_refundable_credits: 0 + hi_act_115_rebate: 0 + hi_food_excise_credit: 100 + hi_refundable_credits: 100 + # Taxable income: 8,000 - 2,200 standard deduction - 1,144 exemption + # = 4,656. Tax: 1.4% * 2,400 + 3.2% * 2,256 = 105.792. + # 105.792 - 0 nonrefundable - 100 refundable = 5.792. + hi_income_tax: 5.792 + absolute_error_margin: 0.01 + +- name: Case 2, Hawaii EITC starts in 2018 and no Act 115 refund. + period: 2018 + input: + people: + person1: + age: 30 + employment_income: 8_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: HI + output: + eitc: 519 + # 20% * 519 + hi_eitc_potential: 103.8 + hi_act_115_rebate: 0 + hi_refundable_credits: 100 + absolute_error_margin: 0.01 + +- name: Case 3, Hawaii EITC and no Act 115 refund in 2020. + period: 2020 + input: + people: + person1: + age: 30 + employment_income: 8_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: HI + output: + eitc: 538 + # 20% * 538 + hi_eitc_potential: 107.6 + hi_act_115_rebate: 0 + hi_refundable_credits: 100 + absolute_error_margin: 0.01 + +- name: Case 4, Act 115 refund for 2021. + period: 2021 + input: + people: + person1: + age: 30 + employment_income: 8_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: HI + output: + # 15.3% * 8,000 under the 2021 phase-in. + eitc: 1_224 + # 20% * 1,224 + hi_eitc_potential: 244.8 + # One exemption * $300 for federal AGI under $100,000. + hi_act_115_rebate: 300 + # 100 food/excise + 300 Act 115 + hi_refundable_credits: 400 + absolute_error_margin: 0.01 + +- name: Case 5, no Act 115 refund for 2022. + period: 2022 + input: + people: + person1: + age: 30 + employment_income: 8_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: HI + output: + eitc: 560 + # 20% * 560 + hi_eitc_potential: 112 + hi_act_115_rebate: 0 + hi_refundable_credits: 100 + absolute_error_margin: 0.01 + +- name: Case 6, no Hawaii EITC or Act 115 refund in 2016. + period: 2016 + input: + people: + person1: + age: 30 + employment_income: 8_000 + tax_units: + tax_unit: + members: [person1] + households: + household: + members: [person1] + state_code: HI + output: + hi_eitc_potential: 0 + hi_non_refundable_credits: 0 + hi_act_115_rebate: 0 + hi_refundable_credits: 100 + absolute_error_margin: 0.01 diff --git a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/credits/hi_eitc.yaml b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/credits/hi_eitc.yaml index ad2cfec1980..918a84ddd9a 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/credits/hi_eitc.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/credits/hi_eitc.yaml @@ -43,3 +43,62 @@ state_code: HI output: hi_eitc: 400 + +# Act 107 (SLH 2017) created the credit for taxable years beginning after +# December 31, 2017 (2018 Form N-356 instructions, p.2). +- name: No Hawaii EITC in 2016 + period: 2016 + input: + eitc: 506 + state_code: HI + hi_income_tax_before_non_refundable_credits: 1_000_000 + output: + hi_eitc_potential: 0 + hi_eitc: 0 + hi_non_refundable_credits: 0 + +- name: No Hawaii EITC in 2017 + period: 2017 + input: + eitc: 510 + state_code: HI + hi_income_tax_before_non_refundable_credits: 1_000_000 + output: + hi_eitc_potential: 0 + hi_eitc: 0 + hi_non_refundable_credits: 0 + +- name: 20% nonrefundable match in 2018, the first year + period: 2018 + input: + eitc: 519 + state_code: HI + hi_income_tax_before_non_refundable_credits: 1_000_000 + output: + # 20% * 519 + hi_eitc_potential: 103.8 + hi_eitc: 103.8 + hi_non_refundable_credits: 103.8 + +- name: 20% nonrefundable match in 2020 + period: 2020 + input: + eitc: 538 + state_code: HI + hi_income_tax_before_non_refundable_credits: 1_000_000 + output: + # 20% * 538 + hi_eitc_potential: 107.6 + hi_eitc: 107.6 + hi_non_refundable_credits: 107.6 + +- name: 20% nonrefundable match in 2021 + period: 2021 + input: + eitc: 1_000 + state_code: HI + hi_income_tax_before_non_refundable_credits: 1_000_000 + output: + hi_eitc_potential: 200 + hi_eitc: 200 + hi_non_refundable_credits: 200 diff --git a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/subtractions/hi_military_pay_exclusion.yaml b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/subtractions/hi_military_pay_exclusion.yaml index 8da03d6eab8..413c9a24b50 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/subtractions/hi_military_pay_exclusion.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/subtractions/hi_military_pay_exclusion.yaml @@ -9,9 +9,55 @@ - name: Military reserve or national guard duty pay exceeds the max amount period: 2021 + input: + military_service_income: 8_000 + is_tax_unit_head_or_spouse: true + state_code: HI + output: + # 2021 N-11 instructions, line 15: $7,152. + hi_military_pay_exclusion: 7_152 + +- name: The 2015 cap is $6,198 + period: 2015 + input: + military_service_income: 8_000 + is_tax_unit_head_or_spouse: true + state_code: HI + output: + hi_military_pay_exclusion: 6_198 + +- name: The 2018 cap is $6,564 + period: 2018 + input: + military_service_income: 8_000 + is_tax_unit_head_or_spouse: true + state_code: HI + output: + hi_military_pay_exclusion: 6_564 + +- name: The 2020 cap is $6,943 + period: 2020 + input: + military_service_income: 8_000 + is_tax_unit_head_or_spouse: true + state_code: HI + output: + hi_military_pay_exclusion: 6_943 + +- name: The 2022 cap is $7,345 + period: 2022 input: military_service_income: 8_000 is_tax_unit_head_or_spouse: true state_code: HI output: hi_military_pay_exclusion: 7_345 + +- name: The 2025 cap is $8,636 + period: 2025 + input: + military_service_income: 9_000 + is_tax_unit_head_or_spouse: true + state_code: HI + output: + hi_military_pay_exclusion: 8_636 diff --git a/policyengine_us/tests/unit/test_hi_credit_start_dates_properties.py b/policyengine_us/tests/unit/test_hi_credit_start_dates_properties.py new file mode 100644 index 00000000000..a87bb838c00 --- /dev/null +++ b/policyengine_us/tests/unit/test_hi_credit_start_dates_properties.py @@ -0,0 +1,236 @@ +"""Properties of the years in which Hawaii's EITC and Act 115 refund apply. + +``backdate_parameters`` copies each parameter's first value back to 2015, so +these credits paid in years before they existed until their parameters were +dated. The law: + +- Hawaii's earned income tax credit applies to taxable years beginning after + December 31, 2017 (Act 107, SLH 2017; 2018 Form N-356 instructions, p.2): + 20% of the federal credit, nonrefundable, for 2018-2022, then 40% and + refundable from 2023 (Act 163, SLH 2023). +- Act 115 (SLH 2022) refunds went only to filers of a 2021 Form N-11: $300 + per exemption under the federal AGI threshold ($100,000; $200,000 for joint + filers and surviving spouses) and $100 at or above it (DOTAX Announcement + 2022-03, p.2). +- The military reserve or Hawaii National Guard duty pay exclusion is capped + at each year's N-11 instruction amount (line 15). + +For every grid point, and for Hypothesis-generated batches, in 2015-2026: + +- ``hi_act_115_rebate`` is zero outside 2021 and equals the announcement's + table times the number of people on the return in 2021; +- ``hi_eitc_potential`` is the year's match rate times the federal EITC, so + it is zero before 2018; +- ``hi_non_refundable_credits`` is zero before 2018 and from 2023, and never + exceeds the Hawaii EITC or the tax it offsets in 2018-2022; +- refundable credits beyond the food/excise, dependent care and renters' + credits are the Act 115 refund (2021 only) and the Hawaii EITC (from 2023); +- before 2018, Hawaii income tax is the tax before credits minus the + refundable credits, since no nonrefundable credit applies. +""" + +import itertools + +import numpy as np +import pytest +from hypothesis import given, settings, strategies as st + +from policyengine_us import Simulation + +YEARS = list(range(2015, 2027)) + +# Hawaii EITC match rate by year (HRS 235-55.75, Act 107 SLH 2017, Act 163 +# SLH 2023). +EITC_MATCH = { + year: 0.0 if year < 2018 else 0.2 if year < 2023 else 0.4 for year in YEARS +} +ACT_115_YEAR = 2021 +ACT_115_HIGH, ACT_115_LOW = 300, 100 +JOINT_STATUSES = {"JOINT", "SURVIVING_SPOUSE"} +ACT_115_THRESHOLD = {"joint": 200_000, "other": 100_000} + +# Military reserve or Hawaii National Guard duty pay exclusion cap, from each +# year's N-11 instructions, line 15. +MILITARY_PAY_CAP = { + 2015: 6_198, + 2016: 6_279, + 2017: 6_410, + 2018: 6_564, + 2019: 6_735, + 2020: 6_943, + 2021: 7_152, + 2022: 7_345, + 2023: 7_683, + 2024: 8_082, + 2025: 8_636, +} + +# (adults, children): single, head of household and joint returns. +HOUSEHOLDS = [(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] +WAGES = [0, 4_000, 8_000, 15_000, 40_000, 99_999, 100_000, 150_000, 200_000] +AGES = [30, 70] +GRID = list(itertools.product(HOUSEHOLDS, WAGES, AGES)) + + +def every_year(value): + return {year: value for year in YEARS} + + +def hawaii_simulation(points): + """One Hawaii tax unit per (household, wages, age) point.""" + people, tax_units, households = {}, {}, {} + for i, ((adults, children), wages, age) in enumerate(points): + members = [] + for a in range(adults): + name = f"u{i}_adult{a}" + people[name] = { + "age": every_year(age), + "employment_income": every_year(wages if a == 0 else 0), + } + members.append(name) + for c in range(children): + name = f"u{i}_child{c}" + people[name] = {"age": every_year(8 + c)} + members.append(name) + tax_units[f"u{i}"] = {"members": members} + households[f"u{i}"] = {"members": members, "state_code": every_year("HI")} + return Simulation( + situation={"people": people, "tax_units": tax_units, "households": households} + ) + + +def act_115_reference(sim, year): + """DOTAX Announcement 2022-03 table times exemptions, for 2021 only.""" + if year != ACT_115_YEAR: + return np.zeros(len(sim.calculate("tax_unit_id", year))) + statuses = sim.calculate("filing_status", year).decode_to_str() + agi = sim.calculate("adjusted_gross_income", year) + threshold = np.where( + np.isin(statuses, list(JOINT_STATUSES)), + ACT_115_THRESHOLD["joint"], + ACT_115_THRESHOLD["other"], + ) + per_exemption = np.where(agi < threshold, ACT_115_HIGH, ACT_115_LOW) + people = sim.calculate("tax_unit_size", year) + return per_exemption * people + + +def check_invariants(sim, year): + calc = lambda variable: sim.calculate(variable, year) # noqa: E731 + + rebate = calc("hi_act_115_rebate") + np.testing.assert_allclose(rebate, act_115_reference(sim, year), atol=0.01) + + eitc_potential = calc("hi_eitc_potential") + np.testing.assert_allclose( + eitc_potential, EITC_MATCH[year] * calc("eitc"), atol=0.01 + ) + + non_refundable = calc("hi_non_refundable_credits") + tax_before_credits = calc("hi_income_tax_before_non_refundable_credits") + if year < 2018 or year >= 2023: + assert np.all(non_refundable == 0) + else: + assert np.all(non_refundable >= 0) + assert np.all( + non_refundable <= np.minimum(eitc_potential, tax_before_credits) + 0.01 + ) + + base_refundable = ( + calc("hi_food_excise_credit") + + calc("hi_cdcc") + + calc("hi_tax_credit_for_low_income_household_renters") + ) + expected_extra = rebate if year == ACT_115_YEAR else 0 + if year >= 2023: + expected_extra = expected_extra + calc("hi_eitc") + np.testing.assert_allclose( + calc("hi_refundable_credits") - base_refundable, expected_extra, atol=0.01 + ) + + if year < 2018: + np.testing.assert_allclose( + calc("hi_income_tax"), + tax_before_credits - calc("hi_refundable_credits"), + atol=0.01, + ) + + +@pytest.fixture(scope="module") +def grid_sim(): + return hawaii_simulation(GRID) + + +def test_grid_premises(grid_sim): + # The grid reaches every filing status the Act 115 table distinguishes + # here, both sides of each AGI threshold, and a positive federal EITC. + statuses = set(grid_sim.calculate("filing_status", 2021).decode_to_str()) + assert {"SINGLE", "HEAD_OF_HOUSEHOLD", "JOINT"} <= statuses + agi = grid_sim.calculate("adjusted_gross_income", 2021) + assert (agi < 100_000).any() and (agi >= 200_000).any() + for year in YEARS: + assert (grid_sim.calculate("eitc", year) > 0).any() + + +@pytest.mark.parametrize("year", YEARS) +def test_grid_invariants(grid_sim, year): + check_invariants(grid_sim, year) + + +def test_act_115_refund_is_paid_only_for_2021(grid_sim): + paid = {year: grid_sim.calculate("hi_act_115_rebate", year).sum() for year in YEARS} + assert paid[ACT_115_YEAR] > 0 + assert all(paid[year] == 0 for year in YEARS if year != ACT_115_YEAR) + + +def test_hawaii_eitc_starts_in_2018(grid_sim): + for year in YEARS: + paid = grid_sim.calculate("hi_eitc_potential", year).sum() + assert (paid > 0) == (year >= 2018), year + + +GENERATED_POINTS = st.lists( + st.tuples( + st.sampled_from(HOUSEHOLDS), + st.integers(min_value=0, max_value=300_000), + st.sampled_from(AGES), + ), + min_size=1, + max_size=8, +) + + +@settings(max_examples=8, deadline=None) +@given(points=GENERATED_POINTS, year=st.sampled_from(YEARS)) +def test_generated_invariants(points, year): + # Witnesses on each side of the Act 115 thresholds and on the EITC + # plateau keep every batch from passing vacuously. + witnesses = [((1, 0), 8_000, 30), ((2, 1), 150_000, 30), ((2, 0), 250_000, 70)] + check_invariants(hawaii_simulation(points + witnesses), year) + + +def test_military_pay_exclusion_matches_published_caps(): + """Differential test: the exclusion against each year's N-11 cap.""" + pays = [0, 3_000, 6_000, 7_000, 8_000, 8_636, 9_000, 20_000] + people, tax_units, households = {}, {}, {} + for i, pay in enumerate(pays): + name = f"p{i}" + people[name] = { + "age": {year: 40 for year in MILITARY_PAY_CAP}, + "military_service_income": {year: pay for year in MILITARY_PAY_CAP}, + } + tax_units[name] = {"members": [name]} + households[name] = { + "members": [name], + "state_code": {year: "HI" for year in MILITARY_PAY_CAP}, + } + sim = Simulation( + situation={"people": people, "tax_units": tax_units, "households": households} + ) + for year, cap in MILITARY_PAY_CAP.items(): + np.testing.assert_allclose( + sim.calculate("hi_military_pay_exclusion", year), + np.minimum(pays, cap), + atol=0.01, + err_msg=str(year), + )