diff --git a/taxcalc/calcfunctions.py b/taxcalc/calcfunctions.py index e348235be..200031c79 100644 --- a/taxcalc/calcfunctions.py +++ b/taxcalc/calcfunctions.py @@ -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 @@ -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 @@ -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): """ @@ -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 @@ -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. @@ -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: diff --git a/taxcalc/tests/cpscsv_agg_expect.csv b/taxcalc/tests/cpscsv_agg_expect.csv index d13adeae2..77f97745f 100644 --- a/taxcalc/tests/cpscsv_agg_expect.csv +++ b/taxcalc/tests/cpscsv_agg_expect.csv @@ -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 diff --git a/taxcalc/tests/test_calcfunctions.py b/taxcalc/tests/test_calcfunctions.py index 619923a0c..8a22a3df3 100644 --- a/taxcalc/tests/test_calcfunctions.py +++ b/taxcalc/tests/test_calcfunctions.py @@ -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 @@ -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) \ No newline at end of file + assert np.allclose(test_value, expected_value) + diff --git a/taxcalc/tests/test_cpscsv.py b/taxcalc/tests/test_cpscsv.py index f9893392d..bb4b85e6e 100644 --- a/taxcalc/tests/test_cpscsv.py +++ b/taxcalc/tests/test_cpscsv.py @@ -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.