Source code for ccc.get_taxcalc_rates

# imports
import numpy as np
from taxcalc import Policy, Records, Calculator
from ccc.utils import DEFAULT_START_YEAR, TC_LAST_YEAR, RECORDS_START_YEAR


[docs]def get_calculator(baseline, calculator_start_year, reform=None, data='cps', gfactors=None, weights=None, records_start_year=RECORDS_START_YEAR): ''' This function creates the tax calculator object for the microsim Args: baseline (bool): `True` if baseline tax policy calculator_start_year (integer): first year of budget window reform (dictionary): IIT reform parameters data (string or Pandas DataFrame): path to file or DataFrame for Tax-Calculator Records object (optional) weights (DataFrame): weights DataFrame for Tax-Calculator Records object (optional) records_start_year (integer): the start year for the data and weights dfs Returns: calc1 (Tax Calculator Calculator object): TC Calculator object with a current_year equal to calculator_start_year ''' # create a calculator policy1 = Policy() if data is not None and "cps" in data: records1 = Records.cps_constructor() # impute short and long term capital gains if using CPS data # in 2012 SOI data 6.587% of CG as short-term gains records1.p22250 = 0.06587 * records1.e01100 records1.p23250 = (1 - 0.06587) * records1.e01100 # set total capital gains to zero records1.e01100 = np.zeros(records1.e01100.shape[0]) elif data is not None: # pragma: no cover records1 = Records( data=data, gfactors=gfactors, weights=weights, start_year=records_start_year) # pragma: no cover else: records1 = Records() # pragma: no cover if baseline: # Should not be a reform if baseline is True assert not reform if not baseline: update_policy(policy1, reform) # the default set up increments year to 2013 calc1 = Calculator(records=records1, policy=policy1) print('Calculator initial year = ', calc1.current_year) # this increment_year function extrapolates all PUF variables to # the next year so this step takes the calculator to the start_year if calculator_start_year > TC_LAST_YEAR: raise RuntimeError("Start year is beyond data extrapolation.") while calc1.current_year < calculator_start_year: calc1.increment_year() return calc1
[docs]def get_rates(baseline=False, start_year=DEFAULT_START_YEAR, reform={}, data='cps'): ''' This function computes weighted average marginal tax rates using micro data from the tax calculator Args: baseline (bool): `True` if baseline tax policy, `False` if reform start_year (integer): first year of budget window reform (dict): reform parameters Returns: individual_rates (dict): individual income (IIT+payroll) marginal tax rates ''' calc1 = get_calculator(baseline=baseline, calculator_start_year=start_year, reform=reform, data=data) # running all the functions and calculates taxes calc1.calc_all() # Loop over years in window of calculations end_year = start_year array_size = end_year - start_year + 1 rates_dict = {'tau_div': 'e00650', 'tau_int': 'e00300', 'tau_scg': 'p22250', 'tau_lcg': 'p23250'} individual_rates = { 'tau_pt': np.zeros(array_size), 'tau_div': np.zeros(array_size), 'tau_int': np.zeros(array_size), 'tau_scg': np.zeros(array_size), 'tau_lcg': np.zeros(array_size), 'tau_td': np.zeros(array_size), 'tau_h': np.zeros(array_size)} for year in range(start_year, end_year + 1): print('Calculator year = ', calc1.current_year) calc1.advance_to_year(year) print('year: ', str(calc1.current_year)) # Compute mtrs # Sch C [mtr_fica_schC, mtr_iit_schC, mtr_combined_schC] =\ calc1.mtr('e00900p') # Sch E - includes partnership and s corp income [mtr_fica_schE, mtr_iit_schE, mtr_combined_schE] =\ calc1.mtr('e02000') # Partnership and s corp income [mtr_fica_PT, mtr_iit_PT, mtr_combined_PT] = calc1.mtr('e26270') # pension distributions # does PUF have e01500? Do we want IRA distributions here? # Weird - I see e01500 in PUF, but error when try to call it [mtr_fica_pension, mtr_iit_pension, mtr_combined_pension] =\ calc1.mtr('e01700') # mortgage interest and property tax deductions # do we also want mtg ins premiums here? # mtg interest [mtr_fica_mtg, mtr_iit_mtg, mtr_combined_mtg] =\ calc1.mtr('e19200') # prop tax [mtr_fica_prop, mtr_iit_prop, mtr_combined_prop] =\ calc1.mtr('e18500') pos_ti = calc1.array("c04800") > 0 individual_rates['tau_pt'][year - start_year] = ( (((mtr_iit_schC * np.abs(calc1.array("e00900p"))) + (mtr_iit_schE * np.abs(calc1.array("e02000") - calc1.array("e26270"))) + (mtr_iit_PT * np.abs(calc1.array("e26270")))) * pos_ti * calc1.array("s006")).sum() / ((np.abs(calc1.array("e00900p")) + np.abs(calc1.array("e02000") - calc1.array("e26270")) + np.abs(calc1.array("e26270"))) * pos_ti * calc1.array("s006")).sum()) individual_rates['tau_td'][year - start_year] = ( (mtr_iit_pension * calc1.array("e01500") * pos_ti * calc1.array("s006")).sum() / (calc1.array("e01500") * pos_ti * calc1.array("s006")).sum()) individual_rates['tau_h'][year - start_year] = -1 * ( ((mtr_iit_mtg * calc1.array("e19200")) + (mtr_iit_prop * calc1.array("e18500")) * pos_ti * calc1.array("s006")).sum() / ( (calc1.array("e19200")) + (calc1.array("e18500")) * pos_ti * calc1.array("s006")).sum()) # Loop over MTRs that have only one income source for k, v in rates_dict.items(): [mtr_fica, mtr_iit, mtr_combined] = calc1.mtr(v) individual_rates[k][year - start_year] = ( (mtr_iit * calc1.array(v) * pos_ti * calc1.array("s006")).sum() / (calc1.array(v) * pos_ti * calc1.array("s006")).sum()) print(individual_rates) return individual_rates
def update_policy(policy_obj, reform, **kwargs): """ Convenience method that updates the Policy object with the reform dict using the appropriate method, given the reform format. """ if is_paramtools_format(reform): policy_obj.adjust(reform, **kwargs) else: policy_obj.implement_reform(reform, **kwargs) def is_paramtools_format(reform): """ Check first item in reform to determine if it is using the ParamTools adjustment or the Tax-Calculator reform format. If first item is a dict, then it is likely be a Tax-Calculator reform: { param: {2020: 1000} } Otherwise, it is likely to be a ParamTools format. Returns: format (bool): True if reform is likely to be in PT format. """ for _, data in reform.items(): if isinstance(data, dict): return False # taxcalc reform else: # Not doing a specific check to see if the value is a list # since it could be a list or just a scalar value. return True