Skip to content

Commit

Permalink
Merge pull request #2677 from MattHJensen/ctc_odc_fix
Browse files Browse the repository at this point in the history
Fixes 2021 child and other dependent credits
  • Loading branch information
jdebacker authored Mar 30, 2023
2 parents 3fb66e3 + fea471b commit d51a1e9
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 44 deletions.
20 changes: 12 additions & 8 deletions taxcalc/calcfunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2508,7 +2508,7 @@ def ChildDepTaxCredit(age_head, age_spouse, nu18, n24, MARS, c00100, XTOT, num,
line15 = max(0., line13 - line14)
if CTC_refundable:
c07220 = line10 * line1 / line3
odc = min(max(0., line10 - c07220), line15)
odc = max(0., line10 - c07220)
codtc_limited = max(0., line10 - c07220 - odc)
else:
line16 = min(line10, line15) # credit is capped by tax liability
Expand Down Expand Up @@ -2987,9 +2987,9 @@ def NonrefundableCredits(c05800, e07240, e07260, e07300, e07400,
if not CTC_refundable:
c07220 = min(c07220, avail)
avail = avail - c07220
# Other dependent credit
odc = min(odc, avail)
avail = avail - odc
# Other dependent credit
odc = min(odc, avail)
avail = avail - odc
# Residential energy credit - Form 5695
c07260 = min(e07260 * (1. - CR_ResidentialEnergy_hc), avail)
avail = avail - c07260
Expand Down Expand Up @@ -3018,7 +3018,7 @@ def NonrefundableCredits(c05800, e07240, e07260, e07300, e07400,
@iterate_jit(nopython=True)
def AdditionalCTC(codtc_limited, ACTC_c, n24, earned, ACTC_Income_thd,
ACTC_rt, nu06, ACTC_rt_bonus_under6family, ACTC_ChildNum,
CTC_refundable, CTC_include17, XTOT, n21, n1820, num,
CTC_refundable, CTC_include17, age_head, age_spouse, MARS, nu18,
ptax_was, c03260, e09800, c59660, e11200,
c11070):
"""
Expand Down Expand Up @@ -3070,7 +3070,9 @@ def AdditionalCTC(codtc_limited, ACTC_c, n24, earned, ACTC_Income_thd,
line4 = 0.
else:
if CTC_include17:
childnum = n24 + max(0, XTOT - n21 - n1820 - n24 - num)
tu18 = int(age_head < 18) # taxpayer is under age 18
su18 = int(MARS == 2 and age_spouse < 18) # spouse is under age 18
childnum = n24 + max(0, nu18 - tu18 - su18 - n24)
else:
childnum = n24
line4 = ACTC_c * childnum
Expand Down Expand Up @@ -3182,7 +3184,7 @@ def CTC_new(CTC_new_c, CTC_new_rt, CTC_new_c_under6_bonus,
CTC_new_ps, CTC_new_prt, CTC_new_for_all, CTC_include17,
CTC_new_refund_limited, CTC_new_refund_limit_payroll_rt,
CTC_new_refund_limited_all_payroll, payrolltax,
n24, nu06, XTOT, n21, n1820, num, c00100, MARS, ptax_oasdi,
n24, nu06, age_head, age_spouse, nu18, c00100, MARS, ptax_oasdi,
c09200, ctc_new):
"""
Computes new refundable child tax credit using specified parameters.
Expand Down Expand Up @@ -3231,7 +3233,9 @@ def CTC_new(CTC_new_c, CTC_new_rt, CTC_new_c_under6_bonus,
New refundable child tax credit
"""
if CTC_include17:
childnum = n24 + max(0, XTOT - n21 - n1820 - n24 - num)
tu18 = int(age_head < 18) # taxpayer is under age 18
su18 = int(MARS == 2 and age_spouse < 18) # spouse is under age 18
childnum = n24 + max(0, nu18 - tu18 - su18 - n24)
else:
childnum = n24
if childnum > 0:
Expand Down
12 changes: 6 additions & 6 deletions taxcalc/tests/cpscsv_agg_expect.csv
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ AMT Income ($b),8319.8,10262.1,10680.1,10960.7,12145.1,12934.9,13548.0,13998.9,1
AMT Liability ($b),8.1,0.8,0.7,0.6,1.1,1.1,1.1,1.0,1.0,16.5
AMT Filers (#m),2.6,0.2,0.2,0.1,0.2,0.2,0.2,0.2,0.2,4.0
Tax before Credits ($b),1116.0,1380.6,1449.4,1491.9,1701.9,1844.3,1912.5,1976.5,2050.4,2248.8
Refundable Credits ($b),70.8,102.4,102.7,655.6,821.5,97.5,103.6,106.0,107.9,94.0
Nonrefundable Credits ($b),32.7,97.2,99.1,99.3,2.2,108.2,108.8,109.9,111.3,31.0
Refundable Credits ($b),70.8,102.4,102.7,655.6,825.7,97.5,103.6,106.0,107.9,94.0
Nonrefundable Credits ($b),32.7,97.2,99.1,99.3,3.3,108.2,108.8,109.9,111.3,31.0
Reform Surtaxes ($b),0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
Other Taxes ($b),5.5,10.7,11.3,11.4,11.7,12.6,14.0,15.2,16.3,17.3
Ind Income Tax ($b),1018.1,1191.7,1258.9,748.3,890.0,1651.2,1714.1,1775.8,1847.5,2141.1
Ind Income Tax ($b),1018.1,1191.7,1258.9,748.3,885.8,1651.2,1714.1,1775.8,1847.5,2141.1
Payroll Taxes ($b),1040.8,1141.6,1194.9,1217.1,1325.3,1430.9,1502.4,1556.3,1609.9,1669.5
Combined Liability ($b),2059.0,2333.2,2453.8,1965.4,2215.3,3082.2,3216.5,3332.1,3457.4,3810.6
With Income Tax <= 0 (#m),88.1,96.2,97.0,135.3,127.8,96.0,97.8,98.8,99.8,97.9
With Combined Tax <= 0 (#m),62.8,65.4,66.4,98.3,97.8,67.9,69.3,70.3,71.4,70.9
Combined Liability ($b),2059.0,2333.2,2453.8,1965.4,2211.1,3082.2,3216.5,3332.1,3457.4,3810.6
With Income Tax <= 0 (#m),88.1,96.2,97.0,135.3,127.9,96.0,97.8,98.8,99.8,97.9
With Combined Tax <= 0 (#m),62.8,65.4,66.4,98.3,98.0,67.9,69.3,70.3,71.4,70.9
UBI Benefits ($b),0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
"Total Benefits, Consumption Value ($b)",2790.7,3225.5,3428.6,3617.9,4011.6,4069.6,4332.7,4602.1,4879.9,5163.2
Total Benefits Cost ($b),2790.7,3225.5,3428.6,3617.9,4011.6,4069.6,4332.7,4602.1,4879.9,5163.2
228 changes: 199 additions & 29 deletions taxcalc/tests/test_calcfunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -617,37 +617,206 @@ def test_TaxInc(test_tuple, expected_value, skip_jit):
assert np.allclose(test_value, expected_value)


# parameterization represents 2021 law
age_head = 45
age_spouse = 0
nu18 = 0
n24 = 0
MARS = 4
c00100 = 1000
XTOT = 3
num = 1
c05800 = 0
e07260 = 0
CR_ResidentialEnergy_hc = 0.0
e07300 = 0
CR_ForeignTax_hc = 0.0
c07180 = 0
c07230 = 0
e07240 = 0
CR_RetirementSavings_hc = 0.0
c07200 = 0
CTC_c = 2000
CTC_ps = [200000.0, 400000.0, 200000.0, 200000.0, 400000.0]
CTC_prt = 0.05
exact = False
ODC_c = 500
CTC_c_under6_bonus = 0.0
nu06 = 0
CTC_refundable = True
CTC_include17 = True
c07220 = 0 # actual value will be returned from function
odc = 0 # actual value will be returned from function
codtc_limited = 0 # actual value will be returned from function
tuple0 = (
age_head, age_spouse, nu18, n24, MARS, c00100, XTOT, num,
c05800, e07260, CR_ResidentialEnergy_hc,
e07300, CR_ForeignTax_hc,
c07180,
c07230,
e07240, CR_RetirementSavings_hc,
c07200,
CTC_c, CTC_ps, CTC_prt, exact, ODC_c,
CTC_c_under6_bonus, nu06,
CTC_refundable, CTC_include17,
c07220, odc, codtc_limited)
# output tuple is : (c07220, odc, codtc_limited)
expected0 = (0, 1000, 0)


@pytest.mark.parametrize(
'test_tuple,expected_value', [
(tuple0, expected0)])
def test_ChildDepTaxCredit_2021(test_tuple, expected_value, skip_jit):
"""
Tests the ChildDepTaxCredit function
"""
test_value = calcfunctions.ChildDepTaxCredit(*test_tuple)
assert np.allclose(test_value, expected_value)

# parameterization represents 2022 law
age_head = 45
age_spouse = 0
nu18 = 0
n24 = 0
MARS = 4
DSI = 0
EIC = 3
c00100 = 19330
e00300 = 0
e00400 = 0
e00600 = 0
c01000 = 0
e02000 = 0
e26270 = 0
age_head = 0
c00100 = 1000
XTOT = 3
num = 1
c05800 = 0
e07260 = 0
CR_ResidentialEnergy_hc = 0.0
e07300 = 0
CR_ForeignTax_hc = 0.0
c07180 = 0
c07230 = 0
e07240 = 0
CR_RetirementSavings_hc = 0.0
c07200 = 0
CTC_c = 2000
CTC_ps = [200000.0, 400000.0, 200000.0, 200000.0, 400000.0]
CTC_prt = 0.05
exact = False
ODC_c = 500
CTC_c_under6_bonus = 0.0
nu06 = 0
CTC_refundable = False
CTC_include17 = False
c07220 = 0 # actual value will be returned from function
odc = 0 # actual value will be returned from function
codtc_limited = 0 # actual value will be returned from function
tuple0 = (
age_head, age_spouse, nu18, n24, MARS, c00100, XTOT, num,
c05800, e07260, CR_ResidentialEnergy_hc,
e07300, CR_ForeignTax_hc,
c07180,
c07230,
e07240, CR_RetirementSavings_hc,
c07200,
CTC_c, CTC_ps, CTC_prt, exact, ODC_c,
CTC_c_under6_bonus, nu06,
CTC_refundable, CTC_include17,
c07220, odc, codtc_limited)
# output tuple is : (c07220, odc, codtc_limited)
expected0 = (0, 0, 1000)


@pytest.mark.parametrize(
'test_tuple,expected_value', [
(tuple0, expected0)])
def test_ChildDepTaxCredit_2022(test_tuple, expected_value, skip_jit):
"""
Tests the ChildDepTaxCredit function
"""
test_value = calcfunctions.ChildDepTaxCredit(*test_tuple)
assert np.allclose(test_value, expected_value)

# parameterization represents 2021 law
CTC_new_c = 1000
CTC_new_rt = 0
CTC_new_c_under6_bonus = 600
CTC_new_ps = [75000, 150000, 75000, 125000, 150000]
CTC_new_prt = 0.05
CTC_new_for_all = True
CTC_include17 = True
CTC_new_refund_limited = False
CTC_new_refund_limit_payroll_rt = 0.0
CTC_new_refund_limited_all_payroll = False
payrolltax = 0
n24 = 0
nu06 = 0
age_head = 45
age_spouse = 0
earned = 19330
earned_p = 19330
earned_s = 0
EITC_ps = [8790, 19330, 19330, 19330]
EITC_MinEligAge = 25
EITC_MaxEligAge = 64
EITC_ps_MarriedJ = [5980, 5980, 5980, 6250]
EITC_rt = [0.0765, 0.34, 0.4, 0.45]
EITC_c = [538, 3584, 5920, 6660]
EITC_prt = [0.0765, 0.1598, 0.2106, 0.2106]
EITC_basic_frac = 0.0
EITC_InvestIncome_c = 3650
EITC_excess_InvestIncome_rt = 9e+99
EITC_indiv = False
EITC_sep_filers_elig = False
e02300 = 10200
UI_thd = [150000, 150000, 150000, 150000, 150000]
UI_em = 10200
nu18 = 0
num = 1
c00100 = 1000
MARS = 4
ptax_oasdi = 0
c09200 = 0
ctc_new = 0 # actual value will be returned from function
tuple0 = (
CTC_new_c, CTC_new_rt, CTC_new_c_under6_bonus,
CTC_new_ps, CTC_new_prt, CTC_new_for_all, CTC_include17,
CTC_new_refund_limited, CTC_new_refund_limit_payroll_rt,
CTC_new_refund_limited_all_payroll, payrolltax,
n24, nu06, age_head, age_spouse, nu18, c00100, MARS, ptax_oasdi,
c09200, ctc_new)
# output tuple is : (ctc_new)
expected0 = (0)

@pytest.mark.parametrize(
'test_tuple,expected_value', [
(tuple0, expected0)])
def test_CTCnew_2021(test_tuple, expected_value, skip_jit):
"""
Tests the CTCnew function
"""
test_value = calcfunctions.CTC_new(*test_tuple)
assert np.allclose(test_value, expected_value)

# parameterization represents 2022 law
CTC_new_c = 0
CTC_new_rt = 0
CTC_new_c_under6_bonus = 0
CTC_new_ps = [0, 0, 0, 0, 0]
CTC_new_prt = 0
CTC_new_for_all = False
CTC_include17 = False
CTC_new_refund_limited = False
CTC_new_refund_limit_payroll_rt = 0.0
CTC_new_refund_limited_all_payroll = False
payrolltax = 0
n24 = 0
nu06 = 0
age_head = 45
age_spouse = 0
nu18 = 0
num = 1
c00100 = 1000
MARS = 4
ptax_oasdi = 0
c09200 = 0
ctc_new = 0 # actual value will be returned from function
tuple0 = (
CTC_new_c, CTC_new_rt, CTC_new_c_under6_bonus,
CTC_new_ps, CTC_new_prt, CTC_new_for_all, CTC_include17,
CTC_new_refund_limited, CTC_new_refund_limit_payroll_rt,
CTC_new_refund_limited_all_payroll, payrolltax,
n24, nu06, age_head, age_spouse, nu18, c00100, MARS, ptax_oasdi,
c09200, ctc_new)
# output tuple is : (ctc_new)
expected0 = (0)

@pytest.mark.parametrize(
'test_tuple,expected_value', [
(tuple0, expected0)])
def test_CTCnew_2022(test_tuple, expected_value, skip_jit):
"""
Tests the CTCnew function
"""
test_value = calcfunctions.CTC_new(*test_tuple)
assert np.allclose(test_value, expected_value)



ymod1 = 19330 + 10200
Expand Down Expand Up @@ -688,4 +857,5 @@ def test_AGI(test_tuple, expected_value, skip_jit):
"""
test_value = calcfunctions.AGI(*test_tuple)
print('Returned from agi function: ', test_value)
assert np.allclose(test_value, expected_value)
assert np.allclose(test_value, expected_value)

2 changes: 1 addition & 1 deletion taxcalc/tests/test_cpscsv.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def test_agg(tests_path, cps_fullsample):
if cyr == calc_start_year:
reltol = 0.0232
else:
reltol = 0.0442
reltol = 0.0444
if not np.allclose(taxes_subsample[cyr], taxes_fullsample[cyr],
atol=0.0, rtol=reltol):
reldiff = (taxes_subsample[cyr] / taxes_fullsample[cyr]) - 1.
Expand Down

0 comments on commit d51a1e9

Please sign in to comment.