From d88917b8a861f54f715c24b35c1ee82246e16d2e Mon Sep 17 00:00:00 2001 From: codykallen Date: Wed, 11 Oct 2017 11:09:33 -0400 Subject: [PATCH] Add files via upload --- EATR_growth_workbook.ipynb | 95 +++++++++++ __pycache__/parameters.cpython-36.pyc | Bin 0 -> 1598 bytes basedata.csv | 30 ++++ default_params.json | 116 ++++++++++++++ eatr and growth code.txt | 215 +++++++++++++++++++++++++ eatr_growth.py | 216 ++++++++++++++++++++++++++ growthdata.csv | 34 ++++ parameters.py | 50 ++++++ test_parameters.py | 47 ++++++ test_params.json | 20 +++ 10 files changed, 823 insertions(+) create mode 100644 EATR_growth_workbook.ipynb create mode 100644 __pycache__/parameters.cpython-36.pyc create mode 100644 basedata.csv create mode 100644 default_params.json create mode 100644 eatr and growth code.txt create mode 100644 eatr_growth.py create mode 100644 growthdata.csv create mode 100644 parameters.py create mode 100644 test_parameters.py create mode 100644 test_params.json diff --git a/EATR_growth_workbook.ipynb b/EATR_growth_workbook.ipynb new file mode 100644 index 0000000..981a48d --- /dev/null +++ b/EATR_growth_workbook.ipynb @@ -0,0 +1,95 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import copy" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'execfile' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mexecfile\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'eatr_growth.py'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'execfile' is not defined" + ] + } + ], + "source": [ + "execfile('eatr_growth.py')" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "params_corptax_ref = {\n", + " 'ccr_method': 'EXP',\n", + " 'corptax_rate': 0.2,\n", + " 'int_deductibility': 0,\n", + " 'dividend_credit': 0\n", + "}\n", + "deltaInv = investmentResponse(params_corptax_ref, params_iitax_base, 'semi', -1.5)\n", + "growth_accounting(params_econ, deltaInv, 'basedata.csv', 'growthdata.csv', 2018)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.0" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/__pycache__/parameters.cpython-36.pyc b/__pycache__/parameters.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..164f470de4f5f1687c3a2a7e236dd1b825469ee3 GIT binary patch literal 1598 zcmds1&2H2%5VoD4hV73^ix904vi7zJbq~O$st^@z#i1Z5iwY}XF|oIGn~hW3Te?;D z!g7ZP;01Uja^S*=SK!1rY1J*NIB~+!Ovd(TX7bH9xjj8y8#TYb{1zhg1C1>Y?E4_* zCMb?LPEZ?h(#G85J`Z-hHsK+k_=wsbkN72c`y4+*joMG}M~{!^x#+TfVmlertY?d_0Zs+Hba*uGB9GUYOMU@<+Q@1@}pMXCo}^)u02Q*pm1Qfr#A;)704agmtj89|n^K{2-@ zZ0CG}2*Q~~P$(jp;E2@lHIONIWy8#@%-@<9TSa!THUVbKT;@lh+s!2Zo4 zIoil^P8JaCmSGk=;4$p>Lw&!p+-#g$!1Tq+`_I#DbTDMephHw9hCFIV3#UOO(tU5m4g50gHg4u;kUyIFFg&tDtV-5oaJ~_smov$ zla98X%C!y$#yO!V#I=$KSIKpv=i#IgX!oDgjsoq;Y6w~{pR7MCSyH-;g)Wnn@uL-B WWIqx29FNQtsEGJLID$hGE&c}Yq`{y7 literal 0 HcmV?d00001 diff --git a/basedata.csv b/basedata.csv new file mode 100644 index 0000000..0c4e105 --- /dev/null +++ b/basedata.csv @@ -0,0 +1,30 @@ +year,K_equip,K_struc,K_ip,K_rr,I_equip,I_struc,I_ip,I_rr +1987,3900.085,9540.71,906.564,2287.199,370.92,407.057,168.306,91.692 +1988,3950.974,9771.807,960.509,2324.093,391.579,408.148,175.99,80.447 +1989,4014.228,9996.389,1017.683,2354.392,407.37,405.878,191.276,81.347 +1990,4073.984,10223.867,1079.574,2381.293,396.609,425.709,203.326,76.445 +1991,4110.253,10426.599,1143.18,2396.928,371.387,368.15,214.19,61.564 +1992,4135.305,10574.6,1205.469,2404.03,382.518,327.753,220.929,61.96 +1993,4185.707,10705.007,1264.9,2413.235,429.202,343.615,228.907,68.242 +1994,4274.555,10838.623,1321.694,2426.141,469.326,344.328,236.147,71.89 +1995,4394.293,10978.152,1379.733,2446.971,506.044,365.365,251.935,86.688 +1996,4535.435,11137.189,1448.267,2474.017,531.925,392.863,278.107,87.052 +1997,4694.234,11317.572,1533.929,2501.988,565.336,417.319,309.518,91.38 +1998,4881.104,11511.747,1635.655,2529.536,616.165,429.67,339.318,89.102 +1999,5101.932,11703.923,1754.589,2559.872,666.473,422.335,380.461,99.939 +2000,5346.76,11908.081,1888.688,2594.509,703.666,462.047,414.484,100.878 +2001,5566.939,12128.868,2014.354,2625.954,661.565,463.706,415.568,96.94 +2002,5722.894,12297.511,2111.14,2656.537,618.418,365.903,408.596,102.575 +2003,5843.752,12405.39,2189.043,2692.891,628.508,349.364,422.027,112.023 +2004,5978.749,12502.489,2265.501,2734.877,679.629,350.391,442.247,117.667 +2005,6155.614,12603.38,2350.269,2779.792,745.635,362.599,472.222,122.057 +2006,6375.662,12722.213,2444.413,2820.146,803.33,391.692,494.302,113.032 +2007,6613.808,12880.443,2545.228,2848.893,824.829,446.784,518.556,103.398 +2008,6809.789,13077.635,2649.523,2863.141,765.717,475.182,533.705,88.377 +2009,6862.082,13236.631,2739.765,2859.326,580.376,376.236,523.16,71.195 +2010,6856.512,13312.89,2814.618,2841.202,677.096,314.925,533.333,63.087 +2011,6933.6,13363.363,2891.543,2818.603,764.48,328.796,551.755,65.008 +2012,7084.874,13439.947,2977.935,2800.087,849.43,371.143,574.515,73.606 +2013,7279.911,13542.872,3072.032,2789.132,881.556,385.973,592.857,82.215 +2014,7494.106,13679.261,3173.154,2784.573,922.01,443.028,618.558,88.316 +2015,7732.626,13829.036,3285.862,2787.782,967.283,418.343,651,99.474 diff --git a/default_params.json b/default_params.json new file mode 100644 index 0000000..940cce0 --- /dev/null +++ b/default_params.json @@ -0,0 +1,116 @@ +{ + "real_int_rate": { + "param_type": "economic assumption", + "description": "real interest rate (relevant to the investment)", + "source": "assumed", + "value": [0.075] + }, + "inflation_rate": { + "param_type": "economic assumption", + "description": "Expected annual inflation rate", + "source": "assumed based on CBO forcast of CPI inflation", + "value": [0.024] + }, + "real_financial_return": { + "param_type": "economic assumption", + "description": "Real gross rate of return on an investment, including supernormal returns", + "source": "assumed", + "value": [0.2] + }, + "debt_financing": { + "param_type": "economic assumption", + "description": "Debt financing share of the investment", + "source": "based on historical data", + "value": [0.32] + }, + "new_equity_financing": { + "param_type": "economic assumption", + "description": "New equity (not retained earnings) financing share of the investment", + "source": "assumed", + "value": [0.0] + }, + "corp_investment_share": { + "param_type": "economic assumption", + "description": "C-corporation share of private fixed investment", + "source": "based on calculation from Jason Debacker", + "value": [0.545] + }, + "incshare_capital": { + "param_type": "economic assumption", + "description": "Share of total income accruing to capital", + "source": "BLS data for 2015", + "value": [0.406] + }, + "capincshare_equip": { + "param_type": "economic assumption", + "description": "Share of capital income accruing to equipment", + "source": "BLS data for 2015", + "value": [0.297] + }, + "capincshare_struc": { + "param_type": "economic assumption", + "description": "Share of capital income accruing to structures", + "source": "BLS data for 2015", + "value": [0.275] + }, + "capincshare_ip": { + "param_type": "economic assumption", + "description": "Share of capital income accruing to intellectual property", + "source": "BLS data for 2015", + "value": [0.202] + }, + "capincshare_rr": { + "param_type": "economic assumption", + "description": "Share of capital income accruing to rental residential capital", + "source": "BLS data for 2015", + "value": [0.061] + }, + "ccr_method": { + "param_type": "corporate tax baseline", + "description": "Capital cost recovery method", + "source": "", + "value": ["DDB"] + }, + "corptax_rate": { + "param_type": "corporate tax baseline", + "description": "Statutory corporate income tax rate", + "source": "", + "value": [0.35] + }, + "int_deductibility": { + "param_type": "corporate tax baseline", + "description": "Fraction of interest paid deductible", + "source": "", + "value": [1.0] + }, + "dividend_credit": { + "param_type": "corporate tax baseline", + "description": "Rate of credit available on dividends paid", + "source": "", + "value": [0] + }, + "mtr_interest": { + "param_type": "individual income tax baseline", + "description": "MTR on marginal investor's interest income", + "source": "", + "value": [0.392] + }, + "mtr_dividends": { + "param_type": "individual income tax baseline", + "description": "MTR on marginal investor's dividend income", + "source": "", + "value": [0.2] + }, + "mtr_capitalgains": { + "param_type": "individual income tax baseline", + "description": "MTR on marginal investor's capital gains (not accrual effective)", + "source": "", + "value": [] + }, + "cg_holding_period": { + "param_type": "individual income tax baseline", + "description": "Equity holding period for marginal investor", + "source": "", + "value": [5] + } +} diff --git a/eatr and growth code.txt b/eatr and growth code.txt new file mode 100644 index 0000000..4078077 --- /dev/null +++ b/eatr and growth code.txt @@ -0,0 +1,215 @@ +import pandas as pd +import numpy as np + +params_econ = { + 'real_int_rate': 0.075, + 'inflation_rate': 0.024, + 'real_financial_return': 0.2, + 'debt_financing': 0.32, + 'new_equity_financing': 0, + 'corp_investment_share': 0.545, + 'incshare_capital': 0.406, + 'capincshare_equip': 0.297, + 'capincshare_struc': 0.275, + 'capincshare_ip': 0.202, + 'capincshare_rr': 0.061 +} + +params_corptax_base = { + 'ccr_method': 'DDB', + 'corptax_rate': 0.35, + 'int_deductibility': 1, + 'dividend_credit': 0, +} + +params_iitax_base = { + 'mtr_interest': 0.392, + 'mtr_dividends': 0.2, + 'mtr_capitalgains': 0.2, + 'cg_holding_period': 5 +} + +def calcA(life, method, i): + if method == 'DDB': + if life == 5: + deductions = [0.2, 0.32, 0.192, 0.1152, 0.1152, 0.567, 0, 0] + else: + deductions = [0.1429, 0.2449, 0.1749, 0.1249, 0.0893, 0.0892, 0.0893, 0.0446] + elif method == 'SL': + if life == 5: + deductions = [0.1, 0.2, 0.2, 0.2, 0.2, 0.1, 0, 0] + else: + deductions = [0.07145, 0.1429, 0.1429, 0.1429, 0.1429, 0.1429, 0.1429, 0.0715] + else: + deductions = [1, 0, 0, 0, 0, 0, 0, 0] + + i = (1 + r) * (1 + pi) - 1 + pv_deductions = [0] * 8 + for i in range(8): + pv_deductions[i] = deductions[i] / (1 + i)**i + return sum(pv_deductions) + +def calcEATR(econ_params, corptax_params, iitax_params, L): + r = econ_params['real_int_rate'] + pi = econ_params['inflation_rate'] + p = econ_params['real_financial_return'] + dB = econ_params['debt_financing'] + dN = econ_params['new_equity_financing'] + i = (1 + r) * (1 + pi) - 1 + assert dB >= 0 or db <= 1 + assert dN >= 0 or db <= 1 + assert i > 0 + + mi = iitax_params['mtr_interest'] + md = iitax_params['mtr_dividends'] + mcg = iitax_params['mtr_capitalgains'] + n_cg = iitax_params['cg_holding_period'] + c = corptax_params['dividend_credit'] + assert n_cg > 0 + z = 1 - ((1 + i) ** n_cg * (1 - mcg) + mcg) ** (1 / n_cg) / i + rho = (1 - mi) * i / (1 - z) + gamma = (1 - md) / (1 - c) / (1 - z) + + assert L in [5, 7] + delta = 1.0 / L + + tau = corptax_params['corptax_rate'] + phi = corptax_params['int_deductibility'] + ccr_method = corptax_params['ccr_method'] + assert ccr_method in ['DDB', 'SL', 'EXP'] + A = calcA(L, ccr_method, i) + + F = gamma * dB* (1 - (1 + i * (1 - phi * tau)) / (1 + rho)) - (1 - gamma) * dN * (1 - 1 / (1 + rho)) + p~ = (1 - tau * A) / (1 - tau) * (r + delta) - F * (1 + r) / gamma / (1 - tau) - delta + p = max(p, p~) + R = (p - p~) * gamma * (1 - tau) * (1 + pi) / (1 + rho) + Rstar = (p - r) / (1 + r) + EATR = (Rstar - R) / (p / (1 + r)) + return EATR + +def investmentResponse(econ_params_ref, corptax_params_ref, iitax_params_ref, elast_type, elast_value): + eatr5_base = calcEATR(params_econ, params_corptax_base, params_iitax_base, 5) + eatr7_base = calcEATR(params_econ, params_corptax_base, params_iitax_base, 7) + eatr5_ref = calcEATR(params_econ_ref, params_corptax_fef, params_iitax_ref, 5) + eatr7_ref = calcEATR(params_econ_ref, params_corptax_fef, params_iitax_ref, 7) + + assert elast_type in ['EATR', 'net of EATR', 'semi'] + if elast_type == 'EATR': + assert elast_value <= 0 + pctchg5 = eatr5_ref / eatr_base - 1 + pctchg7 = eatr7_ref / eatr7_base - 1 + deltaI = elast_value * (pctchg5 + pctchg7) / 2 + elif elast_type == 'net of EATR': + assert elast_value >= 0 + pctchg5 = (1 - eatr5_ref) / (1 - eatr5_base) - 1 + pctchg7 = (1 - eatr7_ref) / (1 - eatr7_base) - 1 + deltaI = elast_value * (pctchg5 + pctchg7) / 2 + else: + assert elast_value <= 0 + deltaI = elast_value * (eatr5_ref + eatr7_ref - eatr5_base - eatr7_base) / 2 + return deltaI + + +def growth_accounting(econ_params, deltaI=0, cap_data_path='basedata.csv', growth_data_path='growthdata.csv', response_start_year=2018) + assert response_start_year > 2016 + alpha_equip = econ_params['incshare_capital'] * econ_params['capincshare_equip'] + alpha_struc = econ_params['incshare_capital'] * econ_params['capincshare_struc'] + alpha_ip = econ_params['incshare_capital'] * econ_params['capincshare_ip'] + alpha_rr = econ_params['incshare_capital'] * econ_params['capincshare_rr'] + base_data = pd.read_csv(cap_data_path') + K_equip_old = np.asarray(base_data['K_equip']) + K_struc_old = np.asarray(base_data['K_struc']) + K_ip_old = np.asarray(base_data['K_ip']) + K_rr_old = np.asarray(base_data['K_rr']) + I_equip_old = np.asarray(base_data['I_equip']) + I_struc_old = np.asarray(base_data['I_struc']) + I_ip_old = np.asarray(base_data['I_ip']) + I_rr_old = np.asarray(base_data['I_rr']) + D_equip = -[K_equip[i+1] - K_equip[i] - I_equip[i] for i in range(len(K_equip) - 1)] + D_struc = -[K_struc[i+1] - K_struc[i] - I_struc[i] for i in range(len(K_struc) - 1)] + D_ip = -[K_ip[i+1] - K_ip[i] - I_ip[i] for i in range(len(K_ip) - 1)] + D_rr = -[K_rr[i+1] - K_rr[i] - I_rr[i] for i in range(len(K_rr) - 1)] + delta_equip = sum([D_equip[i] * K_equip[i] for i in range(len(D_equip))]) / sum([K_equip[i] ** 2 for i in range(len(D_equip))]) + delta_struc = sum([D_struc[i] * K_struc[i] for i in range(len(D_struc))]) / sum([K_struc[i] ** 2 for i in range(len(D_struc))]) + delta_ip = sum([D_ip[i] * K_ip[i] for i in range(len(D_ip))]) / sum([K_ip[i] ** 2 for i in range(len(D_ip))]) + delta_rr = sum([D_rr[i] * K_rr[i] for i in range(len(D_rr))]) / sum([K_rr[i] ** 2 for i in range(len(D_rr))]) + corpshare = econ_params['corp_investment_share'] + + growth_data = pd.read_csv(growth_data_path) + maxyear = 2250 + + ## set up first year (2015) for all variables + K_equip_base = [K_equip_old[-1]] + K_struc_base = [K_struc_old[-1]] + K_ip_base = [K_ip_old[-1]] + K_rr_base = [K_rr_old[-1]] + K_equip_ref = [K_equip_old[-1]] + K_struc_ref = [K_struc_old[-1]] + K_ip_ref = [K_ip_old[-1]] + K_rr_ref = [K_rr_old[-1]] + I_equip_base = [I_equip_old[-1]] + I_struc_base = [I_struc_old[-1]] + I_ip_base = [I_ip_old[-1]] + I_rr_base = [I_rr_old[-1]] + I_equip_ref = [I_equip_old[-1]] + I_struc_ref = [I_struc_old[-1]] + I_ip_ref = [I_ip_old[-1]] + I_rr_ref = [I_rr_old[-1]] + GDP_base = [growth_data['gdp'][0]] + govshare = [growth_data['govshare'][0]] + dy_equip = [0] + dy_struc = [0] + dy_ip = [0] + dy_rr = [0] + dy_tot = [0] + gov_inc = [govshare[0] * GDP_base[0]] + priv_inc_base = [(1 - govshare[0]) * GDP_base[0]] + priv_inc_ref = [(1 - govshare[0]) * GDP_base[0]] + GDP_ref = gov_inc + priv_inc_ref + ## extrapolate forward + for i in range(1, maxyear - 2015): + if i + 2015 < 2028: + GDP_base.append(growth_data['gdp'][i]) + govshare.append(growth_data['govshare'][i]) + elif i + 2015 < 2048: + GDP_base.append(GDP_base[i-1] * (1 + growth_data['gdp_growth'][i])) + govshare.append(govshare[i-1]) + else: + GDP_base.append(GDP_base[i-1] * (1 + 0.02)) + govshare.append(govshare[i-1]) + K_equip_base.append(K_equip_base[i-1] * (1 - delta_equip) + I_equip_base[i-1]) + K_struc_base.append(K_struc_base[i-1] * (1 - delta_struc) + I_struc_base[i-1]) + K_ip_base.append(K_ip_base[i-1] * (1 - delta_ip) + I_ip_base[i-1]) + K_rr_base.append(K_rr_base[i-1] * (1 - delta_rr) + I_rr_base[i-1]) + K_equip_ref.append(K_equip_ref[i-1] * (1 - delta_equip) + I_equip_ref[i-1]) + K_struc_ref.append(K_struc_ref[i-1] * (1 - delta_struc) + I_struc_ref[i-1]) + K_ip_ref.append(K_ip_ref[i-1] * (1 - delta_ip) + I_ip_ref[i-1]) + K_rr_ref.append(K_rr_ref[i-1] * (1 - delta_rr) + I_rr_ref[i-1]) + I_equip_base.append(I_equip_base[i-1] * GDP_base[i] / GDP_base[i-1]) + I_struc_base.append(I_struc_base[i-1] * GDP_base[i] / GDP_base[i-1]) + I_ip_base.append(I_ip_base[i-1] * GDP_base[i] / GDP_base[i-1]) + I_rr_base.append(I_rr_base[i-1] * GDP_base[i] / GDP_base[i-1]) + if i + 2015 < response_start_year: + I_equip_ref.append(I_equip_base[i]) + I_struc_ref.append(I_struc_base[i]) + I_ip_ref.append(I_ip_base[i]) + I_rr_ref.append(I_rr_base[i]) + else: + I_equip_ref.append(I_equip_base[i] * (1 + deltaI * corpshare)) + I_struc_ref.append(I_struc_base[i] * (1 + deltaI * corpshare)) + I_ip_ref.append(I_ip_base[i] * (1 + deltaI * corpshare)) + I_rr_ref.append(I_rr_base[i] * (1 + deltaI * corpshare)) + dy_equip.append((K_equip_ref[i] / K_equip_ref[i-1] - K_equip_base[i] / K_equip_base[i-1]) * alpha_equip) + dy_struc.append((K_struc_ref[i] / K_struc_ref[i-1] - K_struc_base[i] / K_struc_base[i-1]) * alpha_struc) + dy_ip.append((K_ip_ref[i] / K_ip_ref[i-1] - K_ip_base[i] / K_ip_base[i-1]) * alpha_ip) + dy_rr.append((K_rr_ref[i] / K_rr_ref[i-1] - K_rr_base[i] / K_rr_base[i-1]) * alpha_rr) + dy_tot.append(dy_equip[i] + dy_struc[i] + dy_ip[i] + dy_rr[i]) + gov_inc.append(govshare[i] * GDP_base[i]) + priv_inc_base.append((1 - govshare[i]) * GDP_base[i]) + priv_inc_ref.append(priv_inc_ref[i-1] * (priv_inc_base[i] / priv_inc_base[i-1] + dy_tot[i])) + GDP_ref.append(gov_inc[i] + priv_inc_ref[i]) + change_steadystate = GDP_ref[-1] / GDP_base[-1] - 1 + change_2028 = GDP_ref[13] / GDP_base[13] - 1 + change_growth_2018_2028 = (GDP_ref[13] / GDP_ref[3])**0.1 - (GDP_base[13] / GDP_base[3])**0.1 + return [change_steadystate, change_2028, change_growth_2018_2028) + diff --git a/eatr_growth.py b/eatr_growth.py new file mode 100644 index 0000000..5f0e212 --- /dev/null +++ b/eatr_growth.py @@ -0,0 +1,216 @@ +import pandas as pd +import numpy as np + +params_econ = { + 'real_int_rate': 0.075, + 'inflation_rate': 0.024, + 'real_financial_return': 0.2, + 'debt_financing': 0.32, + 'new_equity_financing': 0, + 'corp_investment_share': 0.545, + 'incshare_capital': 0.406, + 'capincshare_equip': 0.297, + 'capincshare_struc': 0.275, + 'capincshare_ip': 0.202, + 'capincshare_rr': 0.061 +} + +params_corptax_base = { + 'ccr_method': 'DDB', + 'corptax_rate': 0.35, + 'int_deductibility': 1, + 'dividend_credit': 0 +} + +params_iitax_base = { + 'mtr_interest': 0.392, + 'mtr_dividends': 0.2, + 'mtr_capitalgains': 0.2, + 'cg_holding_period': 5 +} + +def calcA(life, method, i): + if method == 'DDB': + if life == 5: + deductions = [0.2, 0.32, 0.192, 0.1152, 0.1152, 0.0567] + else: + deductions = [0.1429, 0.2449, 0.1749, 0.1249, 0.0893, 0.0892, 0.0893, 0.0446] + elif method == 'SL': + if life == 5: + deductions = [0.1, 0.2, 0.2, 0.2, 0.2, 0.1] + else: + deductions = [0.07145, 0.1429, 0.1429, 0.1429, 0.1429, 0.1429, 0.1429, 0.0715] + else: + deductions = [1] + pv_deductions = [] + for j in range(len(deductions)): + pv_deductions.append(deductions[j] / (1 + i)**j) + return sum(pv_deductions) + +def calcEATR(econ_params, corptax_params, iitax_params, L): + r = econ_params['real_int_rate'] + pi = econ_params['inflation_rate'] + p = econ_params['real_financial_return'] + dB = econ_params['debt_financing'] + dN = econ_params['new_equity_financing'] + i = (1 + r) * (1 + pi) - 1 + assert dB >= 0 or db <= 1 + assert dN >= 0 or db <= 1 + assert i > 0 + + mi = iitax_params['mtr_interest'] + md = iitax_params['mtr_dividends'] + mcg = iitax_params['mtr_capitalgains'] + n_cg = iitax_params['cg_holding_period'] + c = corptax_params['dividend_credit'] + assert n_cg > 0 + z = 1 - (((1 + i) ** n_cg * (1 - mcg) + mcg) ** (1.0 / n_cg) - 1) / i + rho = (1 - mi) * i / (1 - z) + gamma = (1 - md) / (1 - c) / (1 - z) + + assert L in [5, 7] + delta = 1.0 / L + + tau = corptax_params['corptax_rate'] + phi = corptax_params['int_deductibility'] + ccr_method = corptax_params['ccr_method'] + assert ccr_method in ['DDB', 'SL', 'EXP'] + A = calcA(L, ccr_method, i) + + F = gamma * dB* (1 - (1 + i * (1 - phi * tau)) / (1 + rho)) - (1 - gamma) * dN * (1 - 1 / (1 + rho)) + p_coc = (1 - tau * A) / (1 - tau) * (r + delta) - F * (1 + r) / gamma / (1 - tau) - delta + p = max(p, p_coc) + R = (p - p_coc) * gamma * (1 - tau) * (1 + pi) / (1 + rho) + Rstar = (p - r) / (1 + r) + EATR = (Rstar - R) / (p / (1 + r)) + user_cost = p_coc + delta + return (EATR, user_cost) + +def investmentResponse(corptax_params_ref, iitax_params_ref, elast_type, elast_value): + (eatr5_base, coc5_base) = calcEATR(params_econ, params_corptax_base, params_iitax_base, 5) + (eatr7_base, coc7_base) = calcEATR(params_econ, params_corptax_base, params_iitax_base, 7) + (eatr5_ref, coc5_ref) = calcEATR(params_econ, corptax_params_ref, iitax_params_ref, 5) + (eatr7_ref, coc7_ref) = calcEATR(params_econ, corptax_params_ref, iitax_params_ref, 7) + + assert elast_type in ['EATR', 'net of EATR', 'semi', 'user cost'] + if elast_type == 'EATR': + assert elast_value <= 0 + pctchg5 = eatr5_ref / eatr5_base - 1 + pctchg7 = eatr7_ref / eatr7_base - 1 + deltaI = elast_value * (pctchg5 + pctchg7) / 2 + elif elast_type == 'net of EATR': + assert elast_value >= 0 + pctchg5 = (1 - eatr5_ref) / (1 - eatr5_base) - 1 + pctchg7 = (1 - eatr7_ref) / (1 - eatr7_base) - 1 + deltaI = elast_value * (pctchg5 + pctchg7) / 2 + elif elast_type == 'semi': + assert elast_value <= 0 + deltaI = elast_value * (eatr5_ref + eatr7_ref - eatr5_base - eatr7_base) / 2 + else: + assert elast_value <= 0 + deltaI = elast_value * ((coc5_ref + coc7_ref) / (coc5_base + coc7_base) - 1) + return deltaI + + +def growth_accounting(econ_params, deltaI, cap_data_path, growth_data_path, response_start_year): + assert response_start_year > 2016 + alpha_equip = econ_params['incshare_capital'] * econ_params['capincshare_equip'] + alpha_struc = econ_params['incshare_capital'] * econ_params['capincshare_struc'] + alpha_ip = econ_params['incshare_capital'] * econ_params['capincshare_ip'] + alpha_rr = econ_params['incshare_capital'] * econ_params['capincshare_rr'] + base_data = pd.read_csv(cap_data_path) + K_equip_old = np.asarray(base_data['K_equip']) + K_struc_old = np.asarray(base_data['K_struc']) + K_ip_old = np.asarray(base_data['K_ip']) + K_rr_old = np.asarray(base_data['K_rr']) + I_equip_old = np.asarray(base_data['I_equip']) + I_struc_old = np.asarray(base_data['I_struc']) + I_ip_old = np.asarray(base_data['I_ip']) + I_rr_old = np.asarray(base_data['I_rr']) + D_equip_old = [K_equip_old[i+1] - K_equip_old[i] - I_equip_old[i] for i in range(len(K_equip_old) - 1)] + D_struc_old = [K_struc_old[i+1] - K_struc_old[i] - I_struc_old[i] for i in range(len(K_struc_old) - 1)] + D_ip_old = [K_ip_old[i+1] - K_ip_old[i] - I_ip_old[i] for i in range(len(K_ip_old) - 1)] + D_rr_old = [K_rr_old[i+1] - K_rr_old[i] - I_rr_old[i] for i in range(len(K_rr_old) - 1)] + delta_equip = -sum([D_equip_old[i] * K_equip_old[i] for i in range(len(D_equip_old))]) / sum([K_equip_old[i] ** 2 for i in range(len(D_equip_old))]) + delta_struc = -sum([D_struc_old[i] * K_struc_old[i] for i in range(len(D_struc_old))]) / sum([K_struc_old[i] ** 2 for i in range(len(D_struc_old))]) + delta_ip = -sum([D_ip_old[i] * K_ip_old[i] for i in range(len(D_ip_old))]) / sum([K_ip_old[i] ** 2 for i in range(len(D_ip_old))]) + delta_rr = -sum([D_rr_old[i] * K_rr_old[i] for i in range(len(D_rr_old))]) / sum([K_rr_old[i] ** 2 for i in range(len(D_rr_old))]) + corpshare = econ_params['corp_investment_share'] + + growth_data = pd.read_csv(growth_data_path) + maxyear = 2250 + + ## set up first year (2015) for all variables + K_equip_base = [K_equip_old[-1]] + K_struc_base = [K_struc_old[-1]] + K_ip_base = [K_ip_old[-1]] + K_rr_base = [K_rr_old[-1]] + K_equip_ref = [K_equip_old[-1]] + K_struc_ref = [K_struc_old[-1]] + K_ip_ref = [K_ip_old[-1]] + K_rr_ref = [K_rr_old[-1]] + I_equip_base = [I_equip_old[-1]] + I_struc_base = [I_struc_old[-1]] + I_ip_base = [I_ip_old[-1]] + I_rr_base = [I_rr_old[-1]] + I_equip_ref = [I_equip_old[-1]] + I_struc_ref = [I_struc_old[-1]] + I_ip_ref = [I_ip_old[-1]] + I_rr_ref = [I_rr_old[-1]] + GDP_base = [growth_data['gdp'][0]] + govshare = [growth_data['govshare'][0]] + dy_equip = [0] + dy_struc = [0] + dy_ip = [0] + dy_rr = [0] + dy_tot = [0] + gov_inc = [govshare[0] * GDP_base[0]] + priv_inc_base = [(1 - govshare[0]) * GDP_base[0]] + priv_inc_ref = [(1 - govshare[0]) * GDP_base[0]] + GDP_ref = [gov_inc[0] + priv_inc_ref[0]] + ## extrapolate forward + for j in range(1, maxyear - 2015): + if j + 2015 < 2028: + GDP_base.append(growth_data['gdp'][j]) + govshare.append(growth_data['govshare'][j]) + elif j + 2015 < 2048: + GDP_base.append(GDP_base[j-1] * (1 + growth_data['gdp_growth'][j])) + govshare.append(govshare[j-1]) + else: + GDP_base.append(GDP_base[j-1] * (1 + 0.02)) + govshare.append(govshare[j-1]) + K_equip_base.append(K_equip_base[j-1] * (1 - delta_equip) + I_equip_base[j-1]) + K_struc_base.append(K_struc_base[j-1] * (1 - delta_struc) + I_struc_base[j-1]) + K_ip_base.append(K_ip_base[j-1] * (1 - delta_ip) + I_ip_base[j-1]) + K_rr_base.append(K_rr_base[j-1] * (1 - delta_rr) + I_rr_base[j-1]) + K_equip_ref.append(K_equip_ref[j-1] * (1 - delta_equip) + I_equip_ref[j-1]) + K_struc_ref.append(K_struc_ref[j-1] * (1 - delta_struc) + I_struc_ref[j-1]) + K_ip_ref.append(K_ip_ref[j-1] * (1 - delta_ip) + I_ip_ref[j-1]) + K_rr_ref.append(K_rr_ref[j-1] * (1 - delta_rr) + I_rr_ref[j-1]) + I_equip_base.append(I_equip_base[j-1] * GDP_base[j] / GDP_base[j-1]) + I_struc_base.append(I_struc_base[j-1] * GDP_base[j] / GDP_base[j-1]) + I_ip_base.append(I_ip_base[j-1] * GDP_base[j] / GDP_base[j-1]) + I_rr_base.append(I_rr_base[j-1] * GDP_base[j] / GDP_base[j-1]) + if j + 2015 < response_start_year: + I_equip_ref.append(I_equip_base[j]) + I_struc_ref.append(I_struc_base[j]) + I_ip_ref.append(I_ip_base[j]) + I_rr_ref.append(I_rr_base[j]) + else: + I_equip_ref.append(I_equip_base[j] * (1 + deltaI * corpshare)) + I_struc_ref.append(I_struc_base[j] * (1 + deltaI * corpshare)) + I_ip_ref.append(I_ip_base[j] * (1 + deltaI * corpshare)) + I_rr_ref.append(I_rr_base[j] * (1 + deltaI * corpshare)) + dy_equip.append((K_equip_ref[j] / K_equip_ref[j-1] - K_equip_base[j] / K_equip_base[j-1]) * alpha_equip) + dy_struc.append((K_struc_ref[j] / K_struc_ref[j-1] - K_struc_base[j] / K_struc_base[j-1]) * alpha_struc) + dy_ip.append((K_ip_ref[j] / K_ip_ref[j-1] - K_ip_base[j] / K_ip_base[j-1]) * alpha_ip) + dy_rr.append((K_rr_ref[j] / K_rr_ref[j-1] - K_rr_base[j] / K_rr_base[j-1]) * alpha_rr) + dy_tot.append(dy_equip[j] + dy_struc[j] + dy_ip[j] + dy_rr[j]) + gov_inc.append(govshare[j] * GDP_base[j]) + priv_inc_base.append((1 - govshare[j]) * GDP_base[j]) + priv_inc_ref.append(priv_inc_ref[j-1] * (priv_inc_base[j] / priv_inc_base[j-1] + dy_tot[j])) + GDP_ref.append(gov_inc[j] + priv_inc_ref[j]) + change_steadystate = GDP_ref[-1] / GDP_base[-1] - 1 + change_2028 = GDP_ref[13] / GDP_base[13] - 1 + change_growth_2018_2028 = (GDP_ref[13] / GDP_ref[3])**0.1 - (GDP_base[13] / GDP_base[3])**0.1 + return (change_steadystate, change_2028, change_growth_2018_2028) diff --git a/growthdata.csv b/growthdata.csv new file mode 100644 index 0000000..4cdc0c4 --- /dev/null +++ b/growthdata.csv @@ -0,0 +1,34 @@ +year,gdp_growth,gdp,govshare +2015,,16397.2,0.174756397 +2016,,16662.1,0.173496369 +2017,,17019.3,0.173769985 +2018,,17388.5,0.170340126 +2019,,17680.6,0.175467676 +2020,,17935.7,0.179433603 +2021,,18241.1,0.182905546 +2022,,18583.5,0.187303088 +2023,,18935.4,0.187542731 +2024,,19294.7,0.187330627 +2025,,19658.4,0.191002223 +2026,,20026,0.193945032 +2027,,20400.3,0.196019946 +2028,0.021,, +2029,0.021,, +2030,0.02,, +2031,0.019,, +2032,0.019,, +2033,0.019,, +2034,0.019,, +2035,0.02,, +2036,0.02,, +2037,0.02,, +2038,0.02,, +2039,0.02,, +2040,0.02,, +2041,0.019,, +2042,0.019,, +2043,0.019,, +2044,0.019,, +2045,0.019,, +2046,0.019,, +2047,0.02,, diff --git a/parameters.py b/parameters.py new file mode 100644 index 0000000..651f0e0 --- /dev/null +++ b/parameters.py @@ -0,0 +1,50 @@ +import json + +DEFAULT_PARAM_PATH = "default_params.json" +PARAM_TYPES = ["economic assumption", + "corporate tax baseline", + "individual income tax baseline"] + +def get_default_params(): + """" + Read parameters from default_params.json + + returns: dictionary with keys "economic assumption", "corporate tax baseline" + and "individual income tax baseline" with all params + sorted into the dictionary corresponding to param_type + """ + param_dict = {"economic assumption": {}, + "corporate tax baseline": {}, + "individual income tax baseline": {}} + + with open(DEFAULT_PARAM_PATH) as js: + default_params = json.loads(js.read()) + + for param in default_params: + param_type = default_params[param]["param_type"] + v = default_params[param]["value"] + assert isinstance(v, list) + if len(v) > 0: + param_dict[param_type][param] = v[0] + else: + param_dict[param_type][param] = None + return param_dict + + +def read_reform(reform): + """ + Read reform and fill in default parameters where paramters are not specified + + returns: dictionary with keys "economic assumption", "corporate tax baseline" + and "individual income tax baseline" with all params + sorted into the dictionary corresponding to param_type + """ + default_params = get_default_params() + for param_type in default_params: + for param in default_params[param_type]: + if param in reform[param_type]: + reform[param_type][param] = reform[param_type][param] + else: + reform[param_type][param] = default_params[param_type][param] + + return reform diff --git a/test_parameters.py b/test_parameters.py new file mode 100644 index 0000000..50ba2a9 --- /dev/null +++ b/test_parameters.py @@ -0,0 +1,47 @@ + +import numpy as np + +def test_get_default(): + import parameters + parameters.DEFAULT_PARAM_PATH = "test_params.json" + + act = parameters.get_default_params() + exp = {"economic assumption": { + "real_int_rate": 0.075 + }, + "corporate tax baseline": { + "ccr_method": "DDB" + }, + "individual income tax baseline": { + "mtr_interest": 0.392 + } + } + + assert act == exp + + +def test_load_reform(): + import parameters + parameters.DEFAULT_PARAM_PATH = "default_params.json" + + ref = {"economic assumption": { + "real_int_rate": 0.05 + }, + "corporate tax baseline": { + "ccr_method": "SL" + }, + "individual income tax baseline": { + "mtr_interest": 0.4 + } + } + + processed_reform = parameters.read_reform(ref) + assert processed_reform["economic assumption"]["real_int_rate"] == 0.05 + assert processed_reform["corporate tax baseline"]["ccr_method"] == "SL" + assert processed_reform["individual income tax baseline"]["mtr_interest"] == 0.4 + assert processed_reform["economic assumption"]["inflation_rate"] == 0.024 + + +if __name__ == "__main__": + test_get_default() + test_load_reform() diff --git a/test_params.json b/test_params.json new file mode 100644 index 0000000..09245f8 --- /dev/null +++ b/test_params.json @@ -0,0 +1,20 @@ +{ + "real_int_rate": { + "param_type": "economic assumption", + "description": "real interest rate (relevant to the investment)", + "source": "assumed", + "value": [0.075] + }, + "ccr_method": { + "param_type": "corporate tax baseline", + "description": "Capital cost recovery method", + "source": "", + "value": ["DDB"] + }, + "mtr_interest": { + "param_type": "individual income tax baseline", + "description": "MTR on marginal investor's interest income", + "source": "", + "value": [0.392] + } +}