Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test that shows bug in GainsTax function and fix bug #981

Merged
merged 5 commits into from
Oct 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 52 additions & 16 deletions taxcalc/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,25 +440,28 @@ def TaxInc(c00100, _standard, c21060, c21040, c04600, c04800):
return c04800


@iterate_jit(nopython=True)
def SchXYZTax(c04800, MARS, e00900, e26270,
PT_rt1, PT_rt2, PT_rt3, PT_rt4, PT_rt5, PT_rt6, PT_rt7,
PT_rt8, PT_brk1, PT_brk2, PT_brk3, PT_brk4, PT_brk5, PT_brk6,
PT_brk7, II_rt1, II_rt2, II_rt3, II_rt4, II_rt5, II_rt6, II_rt7,
II_rt8, II_brk1, II_brk2, II_brk3, II_brk4, II_brk5, II_brk6,
II_brk7, c05200):
@jit(nopython=True)
def SchXYZ(taxable_income, MARS, e00900, e26270,
PT_rt1, PT_rt2, PT_rt3, PT_rt4, PT_rt5,
PT_rt6, PT_rt7, PT_rt8,
PT_brk1, PT_brk2, PT_brk3, PT_brk4, PT_brk5,
PT_brk6, PT_brk7,
II_rt1, II_rt2, II_rt3, II_rt4, II_rt5,
II_rt6, II_rt7, II_rt8,
II_brk1, II_brk2, II_brk3, II_brk4, II_brk5,
II_brk6, II_brk7):
"""
SchXYZTax uses the tax rates in Schedule X, Y, or Z, to compute tax.
Return Schedule X, Y, Z tax amount for specified taxable_income.
"""
# separate non-negative taxable income into two non-negative components,
# doing this in a way so that the components add up to taxable income
pt_taxinc = max(0., e00900 + e26270) # non-negative pass-through income
if pt_taxinc >= c04800:
pt_taxinc = c04800
if pt_taxinc >= taxable_income:
pt_taxinc = taxable_income
reg_taxinc = 0.
else:
# pt_taxinc is unchanged
reg_taxinc = c04800 - pt_taxinc
reg_taxinc = taxable_income - pt_taxinc
# compute Schedule X,Y,Z tax using the two components of taxable income,
# stacking pass-through taxable income on top of regular taxable income
if reg_taxinc > 0.:
Expand All @@ -475,15 +478,42 @@ def SchXYZTax(c04800, MARS, e00900, e26270,
PT_brk3, PT_brk4, PT_brk5, PT_brk6, PT_brk7)
else:
pt_tax = 0.
c05200 = reg_tax + pt_tax
return reg_tax + pt_tax


@iterate_jit(nopython=True)
def SchXYZTax(c04800, MARS, e00900, e26270,
PT_rt1, PT_rt2, PT_rt3, PT_rt4, PT_rt5,
PT_rt6, PT_rt7, PT_rt8,
PT_brk1, PT_brk2, PT_brk3, PT_brk4, PT_brk5,
PT_brk6, PT_brk7,
II_rt1, II_rt2, II_rt3, II_rt4, II_rt5,
II_rt6, II_rt7, II_rt8,
II_brk1, II_brk2, II_brk3, II_brk4, II_brk5,
II_brk6, II_brk7,
c05200):
"""
SchXYZTax calls SchXYZ function and sets c05200 to returned amount.
"""
c05200 = SchXYZ(c04800, MARS, e00900, e26270,
PT_rt1, PT_rt2, PT_rt3, PT_rt4, PT_rt5,
PT_rt6, PT_rt7, PT_rt8,
PT_brk1, PT_brk2, PT_brk3, PT_brk4, PT_brk5,
PT_brk6, PT_brk7,
II_rt1, II_rt2, II_rt3, II_rt4, II_rt5,
II_rt6, II_rt7, II_rt8,
II_brk1, II_brk2, II_brk3, II_brk4, II_brk5,
II_brk6, II_brk7)
return c05200


@iterate_jit(nopython=True)
def GainsTax(e00650, c01000, c23650, p23250, e01100, e58990,
e24515, e24518, MARS, c04800, c05200,
e24515, e24518, MARS, c04800, c05200, e00900, e26270,
II_rt1, II_rt2, II_rt3, II_rt4, II_rt5, II_rt6, II_rt7, II_rt8,
II_brk1, II_brk2, II_brk3, II_brk4, II_brk5, II_brk6, II_brk7,
PT_rt1, PT_rt2, PT_rt3, PT_rt4, PT_rt5, PT_rt6, PT_rt7, PT_rt8,
PT_brk1, PT_brk2, PT_brk3, PT_brk4, PT_brk5, PT_brk6, PT_brk7,
CG_as_II,
CG_rt1, CG_rt2, CG_rt3, CG_rt4, CG_thd1, CG_thd2, CG_thd3,
c24516, c24517, c24520, c05700, _taxbc):
Expand Down Expand Up @@ -555,9 +585,15 @@ def GainsTax(e00650, c01000, c23650, p23250, e01100, e58990,
dwks39 = dwks19 + dwks20 + dwks28 + dwks31 + dwks37
dwks40 = dwks1 - dwks39
dwks41 = 0.28 * dwks40
dwks42 = Taxes(dwks19, MARS, 0.0, II_rt1, II_rt2, II_rt3, II_rt4,
II_rt5, II_rt6, II_rt7, II_rt8, II_brk1, II_brk2,
II_brk3, II_brk4, II_brk5, II_brk6, II_brk7)
dwks42 = SchXYZ(dwks19, MARS, e00900, e26270,
PT_rt1, PT_rt2, PT_rt3, PT_rt4, PT_rt5,
PT_rt6, PT_rt7, PT_rt8,
PT_brk1, PT_brk2, PT_brk3, PT_brk4, PT_brk5,
PT_brk6, PT_brk7,
II_rt1, II_rt2, II_rt3, II_rt4, II_rt5,
II_rt6, II_rt7, II_rt8,
II_brk1, II_brk2, II_brk3, II_brk4, II_brk5,
II_brk6, II_brk7)
dwks43 = (dwks29 + dwks32 + dwks38 + dwks41 + dwks42 +
lowest_rate_tax + highest_rate_incremental_tax)
dwks44 = c05200
Expand Down
58 changes: 43 additions & 15 deletions taxcalc/tests/test_calculate.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import os
import json
import numpy as np
import pandas as pd
from io import StringIO
import tempfile
import copy
import pytest
import numpy as np
import pandas as pd
from taxcalc import Policy, Records, Calculator, Behavior, Consumption
from taxcalc import create_distribution_table
from taxcalc import create_difference_table
Expand Down Expand Up @@ -276,6 +277,37 @@ def test_Calculator_mtr(records_2009):
assert type(mtr_combined) == np.ndarray


def test_Calculator_mtr_when_PT_rates_differ():
reform = {2013: {'_II_rt1': [0.40],
'_II_rt2': [0.40],
'_II_rt3': [0.40],
'_II_rt4': [0.40],
'_II_rt5': [0.40],
'_II_rt6': [0.40],
'_II_rt7': [0.40],
'_PT_rt1': [0.30],
'_PT_rt2': [0.30],
'_PT_rt3': [0.30],
'_PT_rt4': [0.30],
'_PT_rt5': [0.30],
'_PT_rt6': [0.30],
'_PT_rt7': [0.30]}}
funit = (
u'RECID,MARS,FLPDYR,e00200,e00200p,e00900,e00900p\n'
u'1, 1, 2015, 200000,200000, 100000,100000\n'
)
pol1 = Policy()
rec1 = Records(pd.read_csv(StringIO(funit)))
calc1 = Calculator(policy=pol1, records=rec1)
(_, mtr1, _) = calc1.mtr(variable_str='p23250')
pol2 = Policy()
pol2.implement_reform(reform)
rec2 = Records(pd.read_csv(StringIO(funit)))
calc2 = Calculator(policy=pol2, records=rec2)
(_, mtr2, _) = calc2.mtr(variable_str='p23250')
assert np.allclose(mtr1, mtr2, rtol=0.0, atol=1e-06)


def test_Calculator_create_difference_table(puf_1991, weights_1991):
# create current-law Policy object and use to create Calculator calc1
policy1 = Policy()
Expand Down Expand Up @@ -332,24 +364,20 @@ def test_ID_HC_vs_BS(puf_1991, weights_1991):
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_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=puf_1991, weights=weights_1991, 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_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=puf_1991, weights=weights_1991, start_year=2009)
Expand Down