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

[WIP] Distributing the Corporate Income Tax #286

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d9f3dfd
starting on documentation
mmessick Jun 2, 2015
7afe995
added variables to allow the calculation of the distribution of the c…
mmessick Jun 10, 2015
6f7c3d3
removed unnecessary files
mmessick Jun 10, 2015
dc4a957
work in progress of implementing corporate income tax
mmessick Jun 15, 2015
5a81635
updated records file
mmessick Jun 15, 2015
cf261a0
updated model to include passthrough income
mmessick Jun 16, 2015
4e19d7b
updated to fix passthrough value
mmessick Jun 16, 2015
30cdfa3
updates to the corp income tax, runs and gets values now
mmessick Jun 22, 2015
d65022f
update to tests
mmessick Jun 22, 2015
79375cf
merge conflicts resolved
mmessick Jun 22, 2015
374dbac
fixing error for travis build
mmessick Jun 22, 2015
ff0477c
added xml file for paper on the model
mmessick Jun 23, 2015
dd4768e
changed how I calculate percent to normal and supernomal by dividing …
mmessick Jun 25, 2015
f3bc51f
reStructuredText file of the paper explaining how to distribute
mmessick Jun 25, 2015
44f4f0c
fixing merge conflicts
mmessick Jun 25, 2015
446747c
fixing layout for reStructuredText
mmessick Jun 25, 2015
0d06e45
figuring out format
mmessick Jun 25, 2015
c4e1151
formatting
mmessick Jun 25, 2015
95bf395
new functionality for a table showing distribution by decile for the …
mmessick Jun 30, 2015
1c4cfb4
fixing test suite to match
mmessick Jun 30, 2015
ad30a1c
minor changes
mmessick Jul 1, 2015
b6070c9
modified descrip of implementation
mmessick Jul 14, 2015
a9c1d07
changed doc location
mmessick Jul 16, 2015
46d2b86
updated docs for this proposal
mmessick Jul 16, 2015
992b44e
fixed typo
mmessick Jul 17, 2015
166be4f
added bibliography to proposal
mmessick Aug 6, 2015
beac958
Merge branch 'master' of https://github.com/mmessick/Tax-Calculator i…
mmessick Aug 6, 2015
1398cb0
merging
mmessick Aug 6, 2015
40204a1
changed calculation of shares to normal and supernormal
mmessick Aug 8, 2015
bd66811
changed proposal to reflect changes in calculation
mmessick Aug 8, 2015
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
56 changes: 56 additions & 0 deletions CorpIncTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""
Testing file for calculate.py
"""

from pandas import DataFrame, concat
from taxcalc.calculate import *
from taxcalc.functions import *
from taxcalc.records import *
from taxcalc.parameters import *
import taxcalc.parameters as parameters
import numpy as np
#from timer.timed_calculate import *


def to_csv(fname, df):
"""
Save this dataframe to a CSV file with name 'fname' and containing
a header with the column names of the dataframe.
"""
df.to_csv(fname, float_format= '%1.3f', sep=',', header=True, index=False)



def run(puf=True):
"""
Run each function defined in calculate.py, saving the ouput to a CSV file.
'puf' set to True by default, to use the 'puf2.csv' as an input

For functions returning an additional non-global variable in addition
to the DataFrame to be printed, one line saves the dataFrame to be printed
first, and then saves the variable to be used by a following function second.
"""

# Create a Parameters object
params = Parameters()

# Create a Public Use File object

tax_dta = pd.read_csv("puf.csv")

blowup_factors = "./taxcalc/StageIFactors.csv"
weights = "./taxcalc/WEIGHTS.csv"

puf = Records(tax_dta, blowup_factors, weights)

# Create a Calculator
calc = Calculator(parameters=params, records=puf)
# Dist_Corp_Inc_Tax(calc.params, calc.records)

calc.corp_inc_tax()

create_corpinctax_table(calc, "weighted_deciles", "weighted_sum")


if __name__ == '__main__':
run()
33 changes: 33 additions & 0 deletions DistributingCorpIncTax.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
=============================================
Distributing the Corporate Income Tax in OSPC
=============================================
-------------
Maria Messick
-------------

The OSPC Tax-Calculator distributes the corporate income tax to individuals, both capital owners and wage earners. In the absence of this corporate income tax, both capital owners and wage earners would receive higher incomes; therefore, the Tax-Calculator imputes how much of the tax is borne by individuals, adding this to each individual’s expanded income measure. The Tax Policy Center allocates 40% to normal returns and 60% to supernormal returns. TPC then says that the burden on owners of capital that have normal returns can be shifted 50% to labor; therefore, TPC assigns 20% to labor, 20% to normal returns, and 60% to supernormal. However, the Joint Committee on Taxation does not distinguish between normal and supernormal returns to capital and thus allocates 75% of the burden to owners of domestic capital and 25% to wage earners. Where many tax calculators decide on a distribution amount to wage earners and capital owners, OSPC leaves this as a parameter open for the user to change to his/her preference. The OSPC allows a user to specify amount of burden allocated to normal and supernormal returns and then the user may allocate, separately, how the burden for normal and supernormal can be shifted to labor. OSPC assumes that these percentages are achieved in the long run and that the long run is completed at the end of the ten-year budget window, if the legislation is enacted in the first year. Since shifting the burden of the corporate income tax to labor is a long-term development, then in the short run, or year one of the budget window, all revenue from the tax is allocated to capital. Over the ten-year budget window, more and more of the burden in shifted to labor until at the end of the budget window, the given percentages are achieved[1]_.

The way OSPC accounts for the share of the corporate income tax borne by labor is first to calculate each individual’s compensation share. This is done by summing the individual’s wages, benefits given by the employer, and the untaxed voluntary contribution to his/her retirement plans[2]_ and dividing it by the aggregate compensation[3]_ people earn in the economy. Next, this compensation share is multiplied by the percent borne by labor and multiplied again by the aggregate revenue from the corporate income tax[4]_.

The way OSPC accounts for the share of the corporate income tax borne by supernormal returns to capital is by taking the percent given to distribute to supernormal returns multiplied by the aggregate revenue collected from the tax multiplied by the sum of the individual’s share of the total of dividends in the market times 0.6 and the individual’s share of the capital gains in the market times 0.6[5]_.

The way OSPC accounts for the share of the corporate income tax borne by normal returns to capital is by taking the percent given to distribute to normal returns multiplied by the aggregate revenue collected from the tax multiplied by the sum of the individual’s share of the total dividends in the domestic market times 0.4 and the individual’s share of the capital gains in the domestic market times 0.4 and the individual’s share of self-employment and pass-through income times 0.4 and the individual’s share of the bonds in the domestic market[6]_.

OSPC’s model for labor is limited by lack of information regarding payroll taxes and benefits given by an individual’s employer. Currently, OSPC uses the sum of wages, employer provided benefit for dependent care, Archer MSA, and retirement savings contribution credit to determine an individual’s compensation, but this leaves many other factors out, such as employer’s contribution to health insurance and other contributions to retirement plans[7]_. Limitations on share to capital come from OSPC’s lack of data regarding IRA holdings, 401(k) account ownership, and other self-employment and pass-through income.

Say the United States collects $100 in corporate tax revenue one year and person 1 receives $60.34 in wages, $20.50 in pass-through income, $2.00 in dividends, $5.50 in net capital gains, and $34.20 in bond revenue in that year. Person 2 receives $82.30 in wages, $15.00 in pass-through income, $20.00 in dividends, $20.25 in net capital gains, and $13.70 in that year. For the purposes of this example, we make the assumption that 20% of the tax is distributed to labor, 20% to normal returns, and 60% to supernormal returns for that year. From this example and using the logic for distributing the corporate income tax outlined above, person 1 will bear 27.29% (8.46% for labor, 9.70% for normal returns, and 9.13% for supernormal returns) and person 2 will bear 72.71% (11.54% for labor, 10.30% for normal returns, and 50.87%) of the burden of the corporate income tax. Thus person 1 pays $27.29 and person 2 pays $72.71 of that $100 revenue.


..[1] Following assumptions made by the Joint Committee on Taxation.

..[2]This sum is calculated in the initialization for a Record object in records.py.

..[3]Aggregate compensation is calculated in the method aggregate_measures in calculate.py (along with all aggregate measures used).

..[4]Calculated in the method Dist_Corp_Inc_Tax in functions.py

..[5]This measure is modeled after that done by the JCT. Calculated in the method Dist_Corp_Inc_Tax in functions.py

..[6]Discernment between assets that have a certain percentage from normal returns and supernormal returns was adapted from the Tax Policy Center.

..[7]This measure is modeled after that done by the JCT. Calculated in the method Dist_Corp_Inc_Tax in functions.py
50 changes: 50 additions & 0 deletions taxcalc/calculate.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ def __init__(self, params=None, records=None, sync_years=True, **kwargs):
print("Your data have beeen extrapolated to "
+ str(self._records.current_year) + ".")

self.corp_inc_tax()

assert self._params.current_year == self._records.current_year

@property
Expand Down Expand Up @@ -142,6 +144,7 @@ def calc_all(self):
C1040(self.params, self.records)
DEITC(self.params, self.records)
OSPC_TAX(self.params, self.records)
self.corp_inc_tax()
ExpandIncome(self.params, self.records)

def calc_all_test(self):
Expand Down Expand Up @@ -175,6 +178,7 @@ def calc_all_test(self):
add_df(all_dfs, C1040(self.params, self.records))
add_df(all_dfs, DEITC(self.params, self.records))
add_df(all_dfs, OSPC_TAX(self.params, self.records))
self.corp_inc_tax()
add_df(all_dfs, ExpandIncome(self.params, self.records))
totaldf = pd.concat(all_dfs, axis=1)
return totaldf
Expand All @@ -183,10 +187,56 @@ def increment_year(self):
self.records.increment_year()
self.params.increment_year()

"""
TODO: Corporate Income Tax
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there something left to do here still?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we haven't decided on how we are going to impute it for future years


Change the json parameters for percent_labor, etc.
For example, percent_labor is given to be 25%, but it is a long
term affect for labor to bear the buren of this tax, so year 1
it should be 0 percent and then smoothly transition to 25 percent
over the 10-year budget window
"""

@property
def current_year(self):
return self.params.current_year

def corp_inc_tax(self):
"""
Calculates the aggregate dividends, capital gains, bonds, self-employed
income, and compensation for this calculator's Records attribute
Once calculated, uses these values to determine this caclulator's
Records's shares of the corporate income tax burden
"""

self.records.agg_self_employed_and_pt = (self.records.e_and_p * self.records.s006).sum()

self.records.agg_bonds = (self.records.bonds * self.records.s006).sum()

self.records.agg_comp = (self.records.compensation * self.records.s006).sum()

self.records.agg_capgains = (self.records.netcapgains * self.records.s006).sum()

self.records.agg_dividends = (self.records.dividends * self.records.s006).sum()

myfunc = np.vectorize(Dist_Corp_Inc_Tax)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just apply the @vectorize decorator to Dist_Corp_Inc_Tax?


revenue_collected = 1000000000000.
percent_labor = .2
percent_supernormal = .6
percent_normal = .2

self.records.share_corptax_burden = myfunc(revenue_collected,
percent_labor, percent_supernormal,
percent_normal, self.records.agg_comp, self.records.agg_dividends,
self.records.agg_capgains, self.records.agg_bonds,
self.records.agg_self_employed_and_pt,
self.records.share_corptax_burden, self.records.dividends,
self.records.e_and_p, self.records.netcapgains, self.records.bonds,
self.records.compensation)

# print self.records.share_corptax_burden
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably want to get rid of this commented out print statement


def mtr(self, income_type_string, diff=100):
"""
This method calculates the marginal tax rate for every record.
Expand Down
100 changes: 96 additions & 4 deletions taxcalc/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ def ItemDed(_posagi, e17500, e18400, e18425, e18450, e18500, e18800, e18900,
def EI_FICA( e00900, e02100, SS_Earnings_c, e00200,
e11055, e00250, e30100, FICA_ss_trt, FICA_mc_trt):
# Earned Income and FICA #

# employer_share_fica = (max(0, FICA_ss_trt * min(SS_Earnings_c, e00200)
# + FICA_mc_trt * e00200))

_sey = e00900 + e02100
_fica_ss = max(0, FICA_ss_trt * min(SS_Earnings_c, e00200
Expand Down Expand Up @@ -374,6 +377,7 @@ def TaxGains(e00650, c04800, e01000, c23650, e23250, e01100, e58990,
else:
_hasgain = 0.


if _hasgain == 1.:
#if/else 1
_dwks5 = max(0., e58990 - e58980)
Expand Down Expand Up @@ -1138,9 +1142,41 @@ def RefAmOpp(_cmp, c87521, _num, c00100, EDCRAGE, c87668):
def NonEdCr(c87550, MARS, ETC_pe_Married, c00100, _num,
c07180, e07200, c07230, e07240, e07960, e07260, e07300,
e07700, e07250, t07950, c05800, _precrd, ETC_pe_Single, _xlin3, _xlin6, c87668, c87620):
"""
Nonrefundable Education Credits
Form 8863 Tentative Education Credits

Notes
-----
Tax Law Parameters:

e07180 : Child Care Credit

e07200 : Credit for Elderly or Disabled

e07240 : Retirement Savings Contribution Credit

e07960 : Qualified Electric Vehicle Credit

e07260 : Residential Energy Credit

e07300 : Foreign Tax Credit

e07700 : Mortgage Int. Credit

e07250 : Adoption Credit Amt.

Intermediate Variables:

_num : filing status, number of people filing jointly

c87668 : nonrefundable Education Credit

Returns
-------

"""

# Nonrefundable Education Credits
# Form 8863 Tentative Education Credits
c87560 = c87550

# Phase Out
Expand Down Expand Up @@ -1429,6 +1465,63 @@ def Taxer_i(inc_in, MARS, II_rt1, II_rt2, II_rt3, II_rt4, II_rt5, II_rt6,
return inc_out


def Dist_Corp_Inc_Tax(revenue_collected, percent_labor, percent_supernormal,
percent_normal, agg_comp, agg_dividends, agg_capgains,
agg_bonds, agg_self_employed_and_pt, share_corptax_burden,
dividends, e_and_p, netcapgains, bonds, compensation):
"""
This function calculates the burden of the corporate income tax borne
by an individual in the economy. It also incorporates this burden into
our measure of the individual's expanded income.

Parameters
----------
revenue_collected : float
value of yearly revenue estimated to be collected in aggregate from the
corporate income tax assigned by the user
percent_labor : float
percent of the burden that will be borne by labor
percent_normal : float
percent of the burden that will be borne by normal returns
percent_supernormal : float
percent of the burden that will be borne by supernormal returns

Returns
-------
share_corptax_burden : float
individual's share of the corporate income tax
"""

# self-employment (e09400)
# individual's share of total self-employment
self_employed_and_pt = e_and_p / agg_self_employed_and_pt

share_of_divs = dividends / agg_dividends
share_of_capgains = netcapgains / agg_capgains

# adapted from the JCT
share_from_labor = (percent_labor * revenue_collected *
compensation / agg_comp)

# adapted from the JCT and TPC
share_from_normal = ((percent_normal * revenue_collected) *
(share_of_divs * .4 + share_of_capgains * .4 +
self_employed_and_pt * .4 + bonds / agg_bonds)
/ 2.2)

share_from_supernormal = (percent_supernormal * revenue_collected
* (share_of_divs * .6 + share_of_capgains * .6)
/ 1.2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the two .6 in this line for the supernormal return percentages of dividends and capital gain? If so, we should probably do the weighted sums of supernormal return and normal return first and then calculate the shares. Calculating the weighted sum of all the share would be fine for share from supernormal return if we assume the percentages of supernormal return are the same for dividends and cap gain, but it doesn't seem to work for the normal return part.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes the .6's are for the supernormal return percentages. Why does it not work for the normal return part?


# individual's share of the corporate income tax
share_corptax_burden = share_from_labor + share_from_normal + share_from_supernormal

# incorporating the burden into our measure of expanded income
# expanded_income = expanded_income + corp_tax_burden

return share_corptax_burden


@iterate_jit(nopython=True, parameters=['FICA_ss_trt', 'SS_Earnings_c',
'FICA_mc_trt'])
def ExpandIncome(FICA_ss_trt, SS_Earnings_c, e00200, FICA_mc_trt, e02400,
Expand All @@ -1445,5 +1538,4 @@ def ExpandIncome(FICA_ss_trt, SS_Earnings_c, e00200, FICA_mc_trt, e02400,
+ employer_share_fica)


return (_expanded_income)

return (_expanded_income)
50 changes: 47 additions & 3 deletions taxcalc/params.json
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,7 @@
},
"_CG_rt1":{
"long_name": "Long term capital gain and qualified dividends rate 1",
"description": "",
"description": "",
"start_year": 2013,
"col_var": "",
"row_var": "",
Expand Down Expand Up @@ -1146,7 +1146,7 @@
"col_label": "",
"value": [0.20]
},
"_CG_thd1":{
"_CG_thd1":{
"long_name": "Long term capital gain and qualified dividends threshold 1",
"description": "",
"start_year": 2013,
Expand Down Expand Up @@ -1208,7 +1208,7 @@
"col_label": "",
"value": [0.20]
},
"_AMT_CG_thd1":{
"_AMT_CG_thd1":{
"long_name": "Long term capital gain and qualified dividend threshold 1",
"description": "",
"start_year": 2013,
Expand All @@ -1233,5 +1233,49 @@
"value": [ [400000, 450000, 225000, 425000, 450000, 225000],
[406750, 457600, 228800, 432200, 457600, 228800],
[413200, 464850, 223425, 439000, 464850, 223425]]
},
"revenue_collected":{
"long_name": "Yearly Revnue Collected by the Corporate Income Tax",
"description": "",
"start_year": 2013,
"col_var": "",
"row_var": "",
"row_label": "",
"cpi_inflated": false,
"col_label": "",
"value": [20000]
},
"percent_labor":{
"long_name": "Percent of the Corporate Income Tax allocated to Labor",
"description": "",
"start_year": 2013,
"col_var": "",
"row_var": "",
"row_label": "",
"cpi_inflated": false,
"col_label": "",
"value": [0.20]
},
"percent_supernormal":{
"long_name": "Percent of the Corporate Income Tax allocated to Supernormal Returns",
"description": "",
"start_year": 2013,
"col_var": "",
"row_var": "",
"row_label": "",
"cpi_inflated": false,
"col_label": "",
"value": [0.60]
},
"percent_normal":{
"long_name": "Percent of the Corporate Income Tax allocated to Normal Returns",
"description": "",
"start_year": 2013,
"col_var": "",
"row_var": "",
"row_label": "",
"cpi_inflated": false,
"col_label": "",
"value": [0.20]
}
}
Loading