From 7517aecddeeb6d43e53cebf6a4c6c75b3593725a Mon Sep 17 00:00:00 2001 From: martinholmer Date: Tue, 26 Jul 2016 10:13:01 -0400 Subject: [PATCH] Fix typo in BenefitSurtax function & add test_ID_HC_vs_BS. --- taxcalc/comparison/reform_results.txt | 2 +- taxcalc/functions.py | 51 ++++++++++++++------------- taxcalc/tests/test_calculate.py | 39 ++++++++++++++++++++ 3 files changed, 66 insertions(+), 26 deletions(-) diff --git a/taxcalc/comparison/reform_results.txt b/taxcalc/comparison/reform_results.txt index 02d3db926..494c358e4 100644 --- a/taxcalc/comparison/reform_results.txt +++ b/taxcalc/comparison/reform_results.txt @@ -109,7 +109,7 @@ Increase Itemized Deduction phaseout rate by 1 pts Tax-Calculator,3.6,3.8,4.0,4.1 "" limit the tax value of ID to 6% of AGI -Tax-Calculator,19.3,20.6,22.0,23.5 +Tax-Calculator,19.5,20.8,22.2,23.7 Budget Options,11,9,8,7 "" CAPITAL GAIN diff --git a/taxcalc/functions.py b/taxcalc/functions.py index 288ce5327..27c6ddfc7 100644 --- a/taxcalc/functions.py +++ b/taxcalc/functions.py @@ -1152,31 +1152,32 @@ def BenefitSurtax(calc): BenefitSurtax function: ... """ if calc.policy.ID_BenefitSurtax_crt != 1.: - nobenefits_calc = copy.deepcopy(calc) - # hard code the reform - nobenefits_calc.policy.ID_Medical_HC = \ - int(nobenefits_calc.policy.ID_BenefitSurtax_Switch[0]) - nobenefits_calc.policy.ID_StateLocalTax_HC = \ - int(nobenefits_calc.policy.ID_BenefitSurtax_Switch[1]) - nobenefits_calc.policy.ID_RealEstate_HC = \ - int(nobenefits_calc.policy.ID_BenefitSurtax_Switch[2]) - nobenefits_calc.policy.ID_casualty_HC = \ - int(nobenefits_calc.policy.ID_BenefitSurtax_Switch[3]) - nobenefits_calc.policy.ID_Miscellaneous_HC = \ - int(nobenefits_calc.policy.ID_BenefitSurtax_Switch[4]) - nobenefits_calc.policy.ID_InterestPaid_HC = \ - int(nobenefits_calc.policy.ID_BenefitSurtax_Switch[5]) - nobenefits_calc.policy.ID_Charity_HC = \ - int(nobenefits_calc.policy.ID_BenefitSurtax_Switch[6]) - nobenefits_calc.calc_one_year() + # compute income tax liability with no itemized deductions allowed for + # the types of itemized deductions covered under the BenefitSurtax + no_ID_calc = copy.deepcopy(calc) + if calc.policy.ID_BenefitSurtax_Switch[0]: + no_ID_calc.policy.ID_Medical_HC = 1. + if calc.policy.ID_BenefitSurtax_Switch[1]: + no_ID_calc.policy.ID_StateLocalTax_HC = 1. + if calc.policy.ID_BenefitSurtax_Switch[2]: + no_ID_calc.policy.ID_RealEstate_HC = 1. + if calc.policy.ID_BenefitSurtax_Switch[3]: + no_ID_calc.policy.ID_Casualty_HC = 1. + if calc.policy.ID_BenefitSurtax_Switch[4]: + no_ID_calc.policy.ID_Miscellaneous_HC = 1. + if calc.policy.ID_BenefitSurtax_Switch[5]: + no_ID_calc.policy.ID_InterestPaid_HC = 1. + if calc.policy.ID_BenefitSurtax_Switch[6]: + no_ID_calc.policy.ID_Charity_HC = 1. + no_ID_calc.calc_one_year() # pylint: disable=protected-access - tax_diff = np.where( - nobenefits_calc.records._iitax - calc.records._iitax > 0., - nobenefits_calc.records._iitax - calc.records._iitax, - 0.) - surtax_cap = nobenefits_calc.policy.ID_BenefitSurtax_crt *\ - nobenefits_calc.records.c00100 + benefit_amount = np.where( + no_ID_calc.records._iitax - calc.records._iitax > 0., + no_ID_calc.records._iitax - calc.records._iitax, 0.) + benefit_deduction = (calc.policy.ID_BenefitSurtax_crt * + calc.records.c00100) calc.records._surtax[:] = calc.policy.ID_BenefitSurtax_trt * np.where( - tax_diff > surtax_cap, tax_diff - surtax_cap, 0.) + benefit_amount > benefit_deduction, + benefit_amount - benefit_deduction, 0.) calc.records._iitax += calc.records._surtax - calc.records._combined = calc.records._iitax + calc.records._fica + calc.records._combined += calc.records._surtax diff --git a/taxcalc/tests/test_calculate.py b/taxcalc/tests/test_calculate.py index 3ff8c86cb..bad31dc67 100644 --- a/taxcalc/tests/test_calculate.py +++ b/taxcalc/tests/test_calculate.py @@ -355,6 +355,45 @@ def test_make_Calculator_increment_years_first(): assert_allclose(calc.policy._II_em, exp_II_em, atol=0.5, rtol=0.0) +def test_ID_HC_vs_BS(): + """ + Test that complete haircut of itemized deductions produces same + results as a 100% benefit surtax with no benefit deduction. + """ + # specify complete-haircut reform policy and Calculator object + hc_reform = {2013: { + '_ID_Medical_HC': [1.0], + '_ID_StateLocalTax_HC': [1.0], + '_ID_RealEstate_HC': [1.0], + '_ID_Casualty_HC': [1.0], + '_ID_Miscellaneous_HC': [1.0], + '_ID_InterestPaid_HC': [1.0], + '_ID_Charity_HC': [1.0]} + } + hc_policy = Policy() + hc_policy.implement_reform(hc_reform) + hc_records = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009) + hc_calc = Calculator(policy=hc_policy, records=hc_records) + # specify benefit-surtax reform policy and Calculator object + bs_reform = {2013: { + '_ID_BenefitSurtax_crt': [0.0], + '_ID_BenefitSurtax_trt': [1.0]} + } + bs_policy = Policy() + bs_policy.implement_reform(bs_reform) + bs_records = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009) + bs_calc = Calculator(policy=bs_policy, records=bs_records) + # compare calculated tax results generated by the two reforms + hc_calc.calc_all() + bs_calc.calc_all() + assert_allclose(hc_calc.records._fica, + bs_calc.records._fica, + atol=0.01, rtol=0.0) + assert_allclose(hc_calc.records._iitax, + bs_calc.records._iitax, + atol=0.01, rtol=0.0) + + def test_Calculator_using_nonstd_input(rawinputfile): # check Calculator handling of raw, non-standard input data with no aging policy = Policy()