def run_reform(name, reform, behave): puf = pd.read_csv("../tax-calculator/puf.csv") policy_base = Policy(start_year=2013) records_base = Records(puf) policy_reform = Policy() records_reform = Records(puf) bhv = Behavior() calcbase = Calculator(policy=policy_base, records=records_base) calcreform = Calculator(policy=policy_reform, records=records_reform, behavior=bhv) policy_reform.implement_reform(reform) calcbase.advance_to_year(CURRENT_YEAR) calcreform.advance_to_year(CURRENT_YEAR) calcbase.calc_all() calcreform.calc_all() bhv.update_behavior(behave) calc_behav = Behavior.response(calcbase, calcreform) calc_behav.calc_all() base_list = multiyear_diagnostic_table(calcbase, 10) reform_list = multiyear_diagnostic_table(calc_behav, 10) difflist = (reform_list.iloc[18] - base_list.iloc[18]) return difflist
def taxcalc_results(start_year, reform_dict, itax_clp, ptax_clp): """ Use taxcalc package on this computer to compute aggregate income tax and payroll tax revenue difference (between reform and current-law policy) for ten years beginning with the specified start_year using the specified reform_dict dictionary and the two specified current-law-policy results dictionaries. Return two aggregate tax revenue difference dictionaries indexed by calendar year. """ pol = Policy() pol.implement_reform(reform_dict) calc = Calculator(policy=pol, records=Records(data=PUF_PATH), verbose=False) calc.advance_to_year(start_year) nyears = NUMBER_OF_YEARS adts = list() for iyr in range(-1, nyears - 1): calc.calc_all() adts.append(create_diagnostic_table(calc)) if iyr < nyears: calc.increment_year() adt = pd.concat(adts, axis=1) # note that adt is Pandas DataFrame object itax_ref = adt.xs('Ind Income Tax ($b)').to_dict() ptax_ref = adt.xs('Payroll Taxes ($b)').to_dict() itax_diff = {} ptax_diff = {} for year in itax_ref: itax_diff[year] = round(itax_ref[year] - itax_clp[year], 1) ptax_diff[year] = round(ptax_ref[year] - ptax_clp[year], 1) return (itax_diff, ptax_diff)
def test_mtr_graph_data(records_2009): calc = Calculator(policy=Policy(), records=records_2009) with pytest.raises(ValueError): gdata = mtr_graph_data(calc, calc, mars='bad', income_measure='agi', dollar_weighting=True) with pytest.raises(ValueError): gdata = mtr_graph_data(calc, calc, mars=0, income_measure='expanded_income', dollar_weighting=True) with pytest.raises(ValueError): gdata = mtr_graph_data(calc, calc, mars=list()) with pytest.raises(ValueError): gdata = mtr_graph_data(calc, calc, mtr_measure='badtax') with pytest.raises(ValueError): gdata = mtr_graph_data(calc, calc, income_measure='badincome') with pytest.raises(ValueError): calcx = Calculator(policy=Policy(), records=records_2009) calcx.advance_to_year(2020) gdata = mtr_graph_data(calcx, calc) gdata = mtr_graph_data(calc, calc, mars=1, mtr_wrt_full_compen=True, income_measure='wages', dollar_weighting=True) assert type(gdata) == dict
def diff_in_revenue(reform_on_II, orig_reform): policy_func = Policy() puf = pd.read_csv("./puf.csv") records_func = Records(puf) calc_func = Calculator(policy = policy_func, records = records_func) policy_bench = Policy() records_bench = Records(puf) calc_bench = Calculator(policy = policy_bench, records = records_bench) reform = { CURRENT_YEAR:{ "_II_rt1":[max(policy_bench._II_rt1[0] *(1 - reform_on_II),0.0)], "_II_rt2":[max(policy_bench._II_rt2[0] *(1 - reform_on_II),0.0)], "_II_rt3":[max(policy_bench._II_rt3[0] *(1 - reform_on_II),0.0)], "_II_rt4":[max(policy_bench._II_rt4[0] *(1 - reform_on_II),0.0)], "_II_rt5":[max(policy_bench._II_rt5[0] *(1 - reform_on_II),0.0)], "_II_rt6":[max(policy_bench._II_rt6[0] *(1 - reform_on_II),0.0)], "_II_rt7":[max(policy_bench._II_rt7[0] *(1 - reform_on_II),0.0)]} } policy_func.implement_reform(reform) policy_func.implement_reform(orig_reform) calc_func.advance_to_year(CURRENT_YEAR) calc_bench.advance_to_year(CURRENT_YEAR) calc_func.calc_all() calc_bench.calc_all() ans = ((calc_bench.records._combined*calc_bench.records.s006).sum()-(calc_func.records._combined*calc_func.records.s006).sum()) print("diff in revenue is ", ans) return ans
def test_dec_graph_plots(cps_subsample): pol = Policy() rec = Records.cps_constructor(data=cps_subsample) calc1 = Calculator(policy=pol, records=rec) year = 2020 calc1.advance_to_year(year) reform = { year: { '_SS_Earnings_c': [9e99], # OASDI FICA tax on all earnings '_FICA_ss_trt': [0.107484] # lower rate to keep revenue unchanged } } pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec) calc2.advance_to_year(year) assert calc1.current_year == calc2.current_year calc1.calc_all() calc2.calc_all() fig = calc1.decile_graph(calc2) assert fig dt1, dt2 = calc1.distribution_tables(calc2) dta = dec_graph_data(dt1, dt2, year, include_zero_incomes=True, include_negative_incomes=False) assert isinstance(dta, dict) dta = dec_graph_data(dt1, dt2, year, include_zero_incomes=False, include_negative_incomes=True) assert isinstance(dta, dict) dta = dec_graph_data(dt1, dt2, year, include_zero_incomes=False, include_negative_incomes=False) assert isinstance(dta, dict)
def test_itax_compare(tests_path, using_puf, puf_fullsample, cps_fullsample): """ Conduct income tax comparisons using ITAX data. """ using_puf_adjust_ratios = True # generate 2015 estimates by AGI category using Tax-Calculator if using_puf: if using_puf_adjust_ratios: recs = Records(data=puf_fullsample) else: recs = Records(data=puf_fullsample, adjust_ratios=None) else: recs = Records.cps_constructor(data=cps_fullsample) calc = Calculator(policy=Policy(), records=recs, verbose=False) calc.advance_to_year(2015) calc.calc_all() # open actual output file if using_puf: afilename = os.path.join(tests_path, 'cmpi_puf_actual.txt') else: afilename = os.path.join(tests_path, 'cmpi_cps_actual.txt') afile = open(afilename, 'w') # write compare results to afile for cname in sorted(ITAX.keys()): comparison(cname, calc, ITAX, afile) # close actual output file afile.close() # check for differences between actual and expect output files efilename = afilename.replace('actual', 'expect') differences(afilename, efilename)
def test_dec_graph_plots(cps_subsample): pol = Policy() rec = Records.cps_constructor(data=cps_subsample) calc1 = Calculator(policy=pol, records=rec) year = 2020 calc1.advance_to_year(year) reform = { 'SS_Earnings_c': {year: 9e99}, # OASDI FICA tax on all earnings 'FICA_ss_trt': {year: 0.107484} # lower rate to keep revenue unchanged } pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec) calc2.advance_to_year(year) assert calc1.current_year == calc2.current_year calc1.calc_all() calc2.calc_all() fig = calc1.decile_graph(calc2) assert fig dt1, dt2 = calc1.distribution_tables(calc2, 'weighted_deciles') dta = dec_graph_data(dt1, dt2, year, include_zero_incomes=True, include_negative_incomes=False) assert isinstance(dta, dict) dta = dec_graph_data(dt1, dt2, year, include_zero_incomes=False, include_negative_incomes=True) assert isinstance(dta, dict) dta = dec_graph_data(dt1, dt2, year, include_zero_incomes=False, include_negative_incomes=False) assert isinstance(dta, dict)
def test_Calculator_advance_to_year(records_2009): policy = Policy() calc = Calculator(policy=policy, records=records_2009) calc.advance_to_year(2016) assert calc.current_year == 2016 with pytest.raises(ValueError): calc.advance_to_year(2015)
def run_reform(name, reform, epsilon): puf = pd.read_csv("./puf.csv") policy_base = Policy(start_year=2013) records_base = Records(puf) policy_reform = Policy() records_reform = Records(puf) calcbase = Calculator(policy=policy_base, records=records_base) calcreform = Calculator(policy=policy_reform, records=records_reform) policy_reform.implement_reform(reform) calcbase.advance_to_year(CURRENT_YEAR) calcreform.advance_to_year(CURRENT_YEAR) calcbase.calc_all() calcreform.calc_all() diff_df = get_diff(calcbase, calcreform, name) data_df = print_data(calcbase, calcreform, weights=weighted, tab='c00100', name=name) equiv_tax_cut = reform_equiv(reform, epsilon) total_rev_raise = agg_diff(calcbase, calcreform) delta_num_filers, delta_percent_filers = agg_num_delta( calcbase, calcreform) #diff_df['equiv_rate_cut'] = len(diff_df)*[equiv_tax_cut] return (diff_df, data_df, equiv_tax_cut, total_rev_raise, delta_num_filers, delta_percent_filers)
def test_calc_all_benefits_amounts(cps_subsample): ''' Testing how benefits are handled in the calc_all method ''' # set a reform with a positive UBI amount ubi_ref = {'UBI_21': {2020: 1000}} # create baseline calculator pol = Policy() recs = Records.cps_constructor(data=cps_subsample) calc_base = Calculator(pol, recs) calc_base.advance_to_year(2020) calc_base.calc_all() # create reform calculator pol_ubi = Policy() pol_ubi.implement_reform(ubi_ref) calc_ubi = Calculator(pol_ubi, recs) calc_ubi.advance_to_year(2020) calc_ubi.calc_all() # check that differences in benefits totals are equal to diffs in # UBI ubi_diff = (calc_ubi.weighted_total('ubi') - calc_base.weighted_total('ubi')) / 1e9 benefit_cost_diff = (calc_ubi.weighted_total('benefit_cost_total') - calc_base.weighted_total('benefit_cost_total')) / 1e9 benefit_value_diff = (calc_ubi.weighted_total('benefit_cost_total') - calc_base.weighted_total('benefit_cost_total')) / 1e9 assert np.allclose(ubi_diff, benefit_cost_diff) assert np.allclose(ubi_diff, benefit_value_diff)
def test_ce_aftertax_income(puf_1991, weights_1991): # test certainty_equivalent() function con = 10000 cmin = 1000 assert con == round(certainty_equivalent(con, 0, cmin), 6) assert con > round(certainty_equivalent((math.log(con) - 0.1), 1, cmin), 6) # test with require_no_agg_tax_change equal to False cyr = 2020 crra = 1 # specify calc1 and calc_all() for cyr pol1 = Policy() rec1 = Records(data=puf_1991, weights=weights_1991, start_year=2009) calc1 = Calculator(policy=pol1, records=rec1) calc1.advance_to_year(cyr) calc1.calc_all() # specify calc2 and calc_all() for cyr pol2 = Policy() reform = {2018: {'_II_em': [0.0]}} pol2.implement_reform(reform) rec2 = Records(data=puf_1991, weights=weights_1991, start_year=2009) calc2 = Calculator(policy=pol2, records=rec2) calc2.advance_to_year(cyr) calc2.calc_all() cedict = ce_aftertax_income(calc1, calc2, require_no_agg_tax_change=False) assert cedict['year'] == cyr # test with require_no_agg_tax_change equal to True with pytest.raises(ValueError): ce_aftertax_income(calc1, calc2, require_no_agg_tax_change=True) # test with require_no_agg_tax_change equal to False and custom_params params = {'crra_list': [0, 2], 'cmin_value': 2000} with pytest.raises(ValueError): ce_aftertax_income(calc1, calc2, require_no_agg_tax_change=True, custom_params=params)
def test_calculator_advance_to_year(cps_subsample): rec = Records.cps_constructor(data=cps_subsample) pol = Policy() calc = Calculator(policy=pol, records=rec) calc.advance_to_year(2016) assert calc.current_year == 2016 with pytest.raises(ValueError): calc.advance_to_year(2015)
def test_Calculator_advance_to_year(): policy = Policy() puf = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009) calc = Calculator(policy=policy, records=puf) calc.advance_to_year(2016) assert calc.current_year == 2016 with pytest.raises(ValueError): calc.advance_to_year(2015)
def test_calculator_advance_to_year(cps_subsample): """ Test Calculator advance_to_year method. """ rec = Records.cps_constructor(data=cps_subsample) pol = Policy() calc = Calculator(policy=pol, records=rec) calc.advance_to_year(2016) assert calc.current_year == 2016 with pytest.raises(ValueError): calc.advance_to_year(2015)
def reform_results(reform_dict, puf_data, reform_2017_law): """ Return actual results of the reform specified in reform_dict. """ # pylint: disable=too-many-locals rec = Records(data=puf_data) # create baseline Calculator object, calc1 pol = Policy() if reform_dict['baseline'] == '2017_law.json': pol.implement_reform(reform_2017_law) elif reform_dict['baseline'] == 'current_law_policy.json': pass else: msg = 'illegal baseline value {}' raise ValueError(msg.format(reform_dict['baseline'])) calc1 = Calculator(policy=pol, records=rec, verbose=False, behavior=None) # create reform Calculator object, calc2, with possible behavioral response start_year = reform_dict['start_year'] beh = Behavior() if '_BE_cg' in reform_dict['value']: elasticity = reform_dict['value']['_BE_cg'] del reform_dict['value']['_BE_cg'] # in order to have a valid reform beh_assump = {start_year: {'_BE_cg': elasticity}} beh.update_behavior(beh_assump) reform = {start_year: reform_dict['value']} pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec, verbose=False, behavior=beh) # increment both Calculator objects to reform's start_year calc1.advance_to_year(start_year) calc2.advance_to_year(start_year) # calculate prereform and postreform output for several years output_type = reform_dict['output_type'] num_years = 4 results = list() for _ in range(0, num_years): calc1.calc_all() prereform = calc1.array(output_type) if calc2.behavior_has_response(): calc2_br = Behavior.response(calc1, calc2) postreform = calc2_br.array(output_type) else: calc2.calc_all() postreform = calc2.array(output_type) diff = postreform - prereform weighted_sum_diff = (diff * calc1.array('s006')).sum() * 1.0e-9 results.append(weighted_sum_diff) calc1.increment_year() calc2.increment_year() # write actual results to actual_str actual_str = 'Tax-Calculator' for iyr in range(0, num_years): actual_str += ',{:.1f}'.format(results[iyr]) return actual_str
def initiate_calculator(self): """ Creates an intial version of the taxcalc.Calculator object for 2014 """ policy1 = Policy() records1 = Records(data=self.records_data) if self.refdict != {}: policy1.implement_reform(self.refdict) calc1 = Calculator(records=records1, policy=policy1, verbose=False) calc1.advance_to_year(2014) calc1.calc_all() return (calc1)
def reform_results(reform_dict, puf_data): """ Return actual results of the reform specified in reform_dict. """ # pylint: disable=too-many-locals # create current-law-policy Calculator object pol1 = Policy() rec1 = Records(data=puf_data) calc1 = Calculator(policy=pol1, records=rec1, verbose=False, behavior=None) # create reform Calculator object with possible behavioral responses start_year = reform_dict['start_year'] beh2 = Behavior() if '_BE_cg' in reform_dict['value']: elasticity = reform_dict['value']['_BE_cg'] del reform_dict['value']['_BE_cg'] # in order to have a valid reform beh_assump = {start_year: {'_BE_cg': elasticity}} beh2.update_behavior(beh_assump) reform = {start_year: reform_dict['value']} pol2 = Policy() pol2.implement_reform(reform) rec2 = Records(data=puf_data) calc2 = Calculator(policy=pol2, records=rec2, verbose=False, behavior=beh2) # increment both calculators to reform's start_year calc1.advance_to_year(start_year) calc2.advance_to_year(start_year) # calculate prereform and postreform output for several years output_type = reform_dict['output_type'] num_years = 4 results = list() for _ in range(0, num_years): calc1.calc_all() prereform = getattr(calc1.records, output_type) if calc2.behavior.has_response(): calc_clp = calc2.current_law_version() calc2_br = Behavior.response(calc_clp, calc2) postreform = getattr(calc2_br.records, output_type) else: calc2.calc_all() postreform = getattr(calc2.records, output_type) diff = postreform - prereform weighted_sum_diff = (diff * calc1.records.s006).sum() * 1.0e-9 results.append(weighted_sum_diff) calc1.increment_year() calc2.increment_year() # write actual results to actual_str reform_description = reform_dict['name'] actual_str = '{}\n'.format(reform_description) actual_str += 'Tax-Calculator' for iyr in range(0, num_years): actual_str += ',{:.1f}'.format(results[iyr]) return actual_str
def fixture_tc_objs(request, reform_xx, puf_subsample, cps_subsample): """ Fixture for creating Tax-Calculator objects that use the PUF and use the CPS (called only twice: once for PUF and once for CPS) """ puftest = request.param p_xx = Policy() p_xx.implement_reform(reform_xx, raise_errors=False) if puftest: rec_xx = Records(data=puf_subsample) else: rec_xx = Records.cps_constructor(data=cps_subsample) c_xx = Calculator(policy=p_xx, records=rec_xx) c_xx.advance_to_year(TEST_YEAR) c_xx.calc_all() return rec_xx, c_xx, puftest
def test_mtr_pt_active(puf_subsample): """ Test whether including wages in active income causes MTRs on e00900p and e26270 to be less than -1 (i.e., -100%) """ # pylint: disable=too-many-locals rec = Records(data=puf_subsample) reform_year = 2018 # create current-law Calculator object, calc1 pol1 = Policy() calc1 = Calculator(policy=pol1, records=rec) calc1.advance_to_year(reform_year) calc1.calc_all() mtr1_e00900p = calc1.mtr('e00900p')[2] mtr1_e26270 = calc1.mtr('e26270')[2] assert min(mtr1_e00900p) > -1 assert min(mtr1_e26270) > -1 # change PT rates, calc2 reform2 = {'PT_rt7': {reform_year: 0.35}} pol2 = Policy() pol2.implement_reform(reform2) calc2 = Calculator(policy=pol2, records=rec) calc2.advance_to_year(reform_year) calc2.calc_all() mtr2_e00900p = calc2.mtr('e00900p')[2] mtr2_e26270 = calc2.mtr('e26270')[2] assert min(mtr2_e00900p) > -1 assert min(mtr2_e26270) > -1 # change PT_wages_active_income reform3 = {'PT_wages_active_income': {reform_year: True}} pol3 = Policy() pol3.implement_reform(reform3) calc3 = Calculator(policy=pol3, records=rec) calc3.advance_to_year(reform_year) calc3.calc_all() mtr3_e00900p = calc3.mtr('e00900p')[2] mtr3_e26270 = calc3.mtr('e26270')[2] assert min(mtr3_e00900p) > -1 assert min(mtr3_e26270) > -1 # change PT rates and PT_wages_active_income reform4 = { 'PT_wages_active_income': { reform_year: True }, 'PT_rt7': { reform_year: 0.35 } } pol4 = Policy() pol4.implement_reform(reform4) calc4 = Calculator(policy=pol4, records=rec) calc4.advance_to_year(reform_year) calc4.calc_all() mtr4_e00900p = calc4.mtr('e00900p')[2] mtr4_e26270 = calc4.mtr('e26270')[2] assert min(mtr4_e00900p) > -1 assert min(mtr4_e26270) > -1
def test_ce_aftertax_income(cps_subsample): # test certainty_equivalent() function with con>cmin con = 5000 cmin = 1000 assert con == round(certainty_equivalent(con, 0, cmin), 6) assert con > round(certainty_equivalent((math.log(con) - 0.1), 1, cmin), 6) # test certainty_equivalent() function with con<cmin con = 500 cmin = 1000 assert con == round(certainty_equivalent(con, 0, cmin), 6) # test with require_no_agg_tax_change equal to False rec = Records.cps_constructor(data=cps_subsample, no_benefits=True) cyr = 2020 # specify calc1 and calc_all() for cyr pol = Policy() calc1 = Calculator(policy=pol, records=rec) calc1.advance_to_year(cyr) calc1.calc_all() # specify calc2 and calc_all() for cyr reform = {2019: {'_II_em': [1000]}} pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec) calc2.advance_to_year(cyr) calc2.calc_all() df1 = calc1.dataframe(['s006', 'combined', 'expanded_income']) df2 = calc2.dataframe(['s006', 'combined', 'expanded_income']) cedict = ce_aftertax_expanded_income(df1, df2, require_no_agg_tax_change=False) assert isinstance(cedict, dict) np.allclose(cedict['ceeu1'], [55641, 27167, 5726, 2229, 1565], atol=0.5, rtol=0.0) np.allclose(cedict['ceeu2'], [54629, 26698, 5710, 2229, 1565], atol=0.5, rtol=0.0) # test with require_no_agg_tax_change equal to True with pytest.raises(ValueError): ce_aftertax_expanded_income(df1, df2, require_no_agg_tax_change=True) # test with require_no_agg_tax_change equal to False and custom_params params = {'crra_list': [0, 2], 'cmin_value': 2000} with pytest.raises(ValueError): ce_aftertax_expanded_income(df1, df2, require_no_agg_tax_change=True, custom_params=params)
def test_Calculator_results_consistency(pit_fullsample, gst_sample, cit_crosssample): # generate calculated-variable dataframe for full sample in second year recs = Records(data=pit_fullsample) grecs = GSTRecords(data=gst_sample) crecs = CorpRecords(data=cit_crosssample) calc = Calculator(policy=Policy(), records=recs, gstrecords=grecs, corprecords=crecs) assert isinstance(calc, Calculator) assert calc.current_year == Policy.JSON_START_YEAR calc.advance_to_year(Policy.JSON_START_YEAR + 1) assert calc.current_year == Policy.JSON_START_YEAR + 1 calc.calc_all() varlist = list(Records.CALCULATED_VARS) vdf = calc.dataframe(varlist) assert isinstance(vdf, pd.DataFrame) # check consistency of calculated results individual by individual assert np.allclose(vdf['TTI'], vdf['GTI'] - vdf['deductions']) assert np.allclose(vdf['Aggregate_Income'], np.maximum(0., vdf['TTI'] - vdf['TI_special_rates'])) assert np.all(vdf['Tax_ST_CG_RATE1'] >= 0.) assert np.all(vdf['Tax_ST_CG_RATE2'] >= 0.) assert np.all(vdf['Tax_ST_CG_APPRATE'] == 0.) assert np.allclose(vdf['Total_Tax_STCG'], (vdf['Tax_ST_CG_RATE1'] + vdf['Tax_ST_CG_RATE2'] + vdf['Tax_ST_CG_APPRATE'])) assert np.all(vdf['Tax_LT_CG_RATE1'] >= 0.) assert np.all(vdf['Tax_LT_CG_RATE2'] >= 0.) assert np.allclose(vdf['Total_Tax_LTCG'], vdf['Tax_LT_CG_RATE1'] + vdf['Tax_LT_CG_RATE2']) assert np.allclose(vdf['Total_Tax_Cap_Gains'], vdf['Total_Tax_STCG'] + vdf['Total_Tax_LTCG']) assert np.all(vdf['tax_Aggregate_Income'] >= 0.) assert np.all(vdf['tax_TI_special_rates'] >= 0.) assert np.all(vdf['rebate_agri'] >= 0.) exp = vdf['tax_Aggregate_Income'] + vdf['tax_TI_special_rates'] exp -= vdf['rebate_agri'] assert np.allclose(vdf['tax_TTI'], exp) assert np.all(vdf['rebate'] >= 0.) assert np.all(vdf['surcharge'] >= 0.) assert np.all(vdf['cess'] >= 0.) assert np.all(vdf['pitax'] >= 0.) exp = vdf['tax_TTI'] - vdf['rebate'] + vdf['surcharge'] + vdf['cess'] assert np.allclose(vdf['pitax'], exp)
def reform_results(rid, reform_dict, puf_data, reform_2017_law): """ Return actual results of the reform specified by rid and reform_dict. """ # pylint: disable=too-many-locals rec = Records(data=puf_data) # create baseline Calculator object, calc1 pol = Policy() if reform_dict['baseline'] == '2017_law.json': pol.implement_reform(reform_2017_law) elif reform_dict['baseline'] == 'policy_current_law.json': pass else: msg = 'illegal baseline value {}' raise ValueError(msg.format(reform_dict['baseline'])) calc1 = Calculator(policy=pol, records=rec, verbose=False) # create reform Calculator object, calc2 start_year = reform_dict['start_year'] reform = dict() for name, value in reform_dict['value'].items(): reform[name] = {start_year: value} pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec, verbose=False) # increment both Calculator objects to reform's start_year calc1.advance_to_year(start_year) calc2.advance_to_year(start_year) # calculate baseline and reform output for several years output_type = reform_dict['output_type'] num_years = 4 results = list() for _ in range(0, num_years): calc1.calc_all() baseline = calc1.array(output_type) calc2.calc_all() reform = calc2.array(output_type) diff = reform - baseline weighted_sum_diff = (diff * calc1.array('s006')).sum() * 1.0e-9 results.append(weighted_sum_diff) calc1.increment_year() calc2.increment_year() # write actual results to actual_str actual_str = '{}'.format(rid) for iyr in range(0, num_years): actual_str += ',{:.1f}'.format(results[iyr]) return actual_str
def reform_results(rid, reform_dict, reform_2017_law): """ Return actual results of the reform specified by rid and reform_dict. """ # pylint: disable=too-many-locals rec = Records.cps_constructor() # create baseline Calculator object, calc1 pol = Policy() if reform_dict['baseline'] == '2017_law.json': pol.implement_reform(reform_2017_law) elif reform_dict['baseline'] == 'policy_current_law.json': pass else: msg = 'illegal baseline value {}' raise ValueError(msg.format(reform_dict['baseline'])) calc1 = Calculator(policy=pol, records=rec, verbose=False) # create reform Calculator object, calc2 start_year = reform_dict['start_year'] reform = dict() for name, value in reform_dict['value'].items(): reform[name] = {start_year: value} pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec, verbose=False) # increment both Calculator objects to reform's start_year calc1.advance_to_year(start_year) calc2.advance_to_year(start_year) # calculate baseline and reform output for several years output_type = reform_dict['output_type'] num_years = 4 results = list() for _ in range(0, num_years): calc1.calc_all() baseline = calc1.array(output_type) calc2.calc_all() reform = calc2.array(output_type) diff = reform - baseline weighted_sum_diff = (diff * calc1.array('s006')).sum() * 1.0e-9 results.append(weighted_sum_diff) calc1.increment_year() calc2.increment_year() # write actual results to actual_str actual_str = '{}'.format(rid) for iyr in range(0, num_years): actual_str += ',{:.1f}'.format(results[iyr]) return actual_str
def test_mtr_graph_data(records_2009): calc = Calculator(policy=Policy(), records=records_2009) with pytest.raises(ValueError): gdata = mtr_graph_data(calc, calc, mars="bad", income_measure="agi", dollar_weighting=True) with pytest.raises(ValueError): gdata = mtr_graph_data(calc, calc, mars=0, income_measure="expanded_income", dollar_weighting=True) with pytest.raises(ValueError): gdata = mtr_graph_data(calc, calc, mars=list()) with pytest.raises(ValueError): gdata = mtr_graph_data(calc, calc, mtr_measure="badtax") with pytest.raises(ValueError): gdata = mtr_graph_data(calc, calc, income_measure="badincome") with pytest.raises(ValueError): calcx = Calculator(policy=Policy(), records=records_2009) calcx.advance_to_year(2020) gdata = mtr_graph_data(calcx, calc) gdata = mtr_graph_data(calc, calc, mars=1, mtr_wrt_full_compen=True, income_measure="wages", dollar_weighting=True) assert type(gdata) == dict
def test_atr_graph_data(records_2009): calc = Calculator(policy=Policy(), records=records_2009) with pytest.raises(ValueError): gdata = atr_graph_data(calc, calc, mars='bad') with pytest.raises(ValueError): gdata = atr_graph_data(calc, calc, mars=0) with pytest.raises(ValueError): gdata = atr_graph_data(calc, calc, mars=list()) with pytest.raises(ValueError): gdata = atr_graph_data(calc, calc, atr_measure='badtax') with pytest.raises(ValueError): calcx = Calculator(policy=Policy(), records=records_2009) calcx.advance_to_year(2020) gdata = atr_graph_data(calcx, calc) gdata = atr_graph_data(calc, calc, mars=1, atr_measure='combined') gdata = atr_graph_data(calc, calc, atr_measure='itax') gdata = atr_graph_data(calc, calc, atr_measure='ptax') assert type(gdata) == dict
def test_atr_graph_data(records_2009): calc = Calculator(policy=Policy(), records=records_2009) with pytest.raises(ValueError): gdata = atr_graph_data(calc, calc, mars="bad") with pytest.raises(ValueError): gdata = atr_graph_data(calc, calc, mars=0) with pytest.raises(ValueError): gdata = atr_graph_data(calc, calc, mars=list()) with pytest.raises(ValueError): gdata = atr_graph_data(calc, calc, atr_measure="badtax") with pytest.raises(ValueError): calcx = Calculator(policy=Policy(), records=records_2009) calcx.advance_to_year(2020) gdata = atr_graph_data(calcx, calc) gdata = atr_graph_data(calc, calc, mars=1, atr_measure="combined") gdata = atr_graph_data(calc, calc, atr_measure="itax") gdata = atr_graph_data(calc, calc, atr_measure="ptax") assert type(gdata) == dict
def test_mtr_pt_active(puf_subsample): """ Test whether including wages in active income causes MTRs on e00900p and e26270 to be less than -1 (i.e., -100%) """ # pylint: disable=too-many-locals rec = Records(data=puf_subsample) reform_year = 2018 # create current-law Calculator object, calc1 pol1 = Policy() calc1 = Calculator(policy=pol1, records=rec) calc1.advance_to_year(reform_year) calc1.calc_all() mtr1_e00900p = calc1.mtr('e00900p')[2] mtr1_e26270 = calc1.mtr('e26270')[2] assert min(mtr1_e00900p) > -1 assert min(mtr1_e26270) > -1 # change PT rates, calc2 reform2 = {'PT_rt7': {reform_year: 0.35}} pol2 = Policy() pol2.implement_reform(reform2) calc2 = Calculator(policy=pol2, records=rec) calc2.advance_to_year(reform_year) calc2.calc_all() mtr2_e00900p = calc2.mtr('e00900p')[2] mtr2_e26270 = calc2.mtr('e26270')[2] assert min(mtr2_e00900p) > -1 assert min(mtr2_e26270) > -1 # change PT_wages_active_income reform3 = {'PT_wages_active_income': {reform_year: True}} pol3 = Policy() pol3.implement_reform(reform3) calc3 = Calculator(policy=pol3, records=rec) calc3.advance_to_year(reform_year) calc3.calc_all() mtr3_e00900p = calc3.mtr('e00900p')[2] mtr3_e26270 = calc3.mtr('e26270')[2] assert min(mtr3_e00900p) > -1 assert min(mtr3_e26270) > -1 # change PT rates and PT_wages_active_income reform4 = { 'PT_wages_active_income': {reform_year: True}, 'PT_rt7': {reform_year: 0.35} } pol4 = Policy() pol4.implement_reform(reform4) calc4 = Calculator(policy=pol4, records=rec) calc4.advance_to_year(reform_year) calc4.calc_all() mtr4_e00900p = calc4.mtr('e00900p')[2] mtr4_e26270 = calc4.mtr('e26270')[2] assert min(mtr4_e00900p) > -1 assert min(mtr4_e26270) > -1
def test_dec_graph_plot(cps_subsample): pol = Policy() rec = Records.cps_constructor(data=cps_subsample) calc1 = Calculator(policy=pol, records=rec) year = 2020 calc1.advance_to_year(year) reform = { year: { '_SS_Earnings_c': [9e99], # OASDI FICA tax on all earnings '_FICA_ss_trt': [0.107484] # lower rate to keep revenue unchanged } } pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec) calc2.advance_to_year(year) assert calc1.current_year == calc2.current_year calc1.calc_all() calc2.calc_all() fig = calc1.decile_graph(calc2) assert fig
def test_Calculator_create_difference_table(puf_1991, weights_1991): # create current-law Policy object and use to create Calculator calc1 policy1 = Policy() puf1 = Records(data=puf_1991, weights=weights_1991, start_year=2009) calc1 = Calculator(policy=policy1, records=puf1) calc1.advance_to_year(2013) calc1.calc_all() # create policy-reform Policy object and use to create Calculator calc2 policy2 = Policy() reform = {2013: {'_II_rt7': [0.45]}} policy2.implement_reform(reform) puf2 = Records(data=puf_1991, weights=weights_1991, start_year=2009) calc2 = Calculator(policy=policy2, records=puf2) calc2.advance_to_year(2013) calc2.calc_all() # create difference table and check that it is a Pandas DataFrame dtable = create_difference_table(calc1.records, calc2.records, groupby="weighted_deciles") assert isinstance(dtable, pd.DataFrame)
def test_atr_graph_data(cps_subsample): pol = Policy() rec = Records.cps_constructor(data=cps_subsample) calc = Calculator(policy=pol, records=rec) with pytest.raises(ValueError): atr_graph_data(calc, calc, mars='bad') with pytest.raises(ValueError): atr_graph_data(calc, calc, mars=0) with pytest.raises(ValueError): atr_graph_data(calc, calc, mars=list()) with pytest.raises(ValueError): atr_graph_data(calc, calc, atr_measure='badtax') gdata = atr_graph_data(calc, calc, mars=1, atr_measure='combined') gdata = atr_graph_data(calc, calc, atr_measure='itax') gdata = atr_graph_data(calc, calc, atr_measure='ptax') assert isinstance(gdata, dict) with pytest.raises(ValueError): calcx = Calculator(policy=pol, records=rec) calcx.advance_to_year(2020) atr_graph_data(calcx, calc)
def test_ce_aftertax_income(cps_subsample): # test certainty_equivalent() function with con>cmin con = 5000 cmin = 1000 assert con == round(certainty_equivalent(con, 0, cmin), 6) assert con > round(certainty_equivalent((math.log(con) - 0.1), 1, cmin), 6) # test certainty_equivalent() function with con<cmin con = 500 cmin = 1000 assert con == round(certainty_equivalent(con, 0, cmin), 6) # test with require_no_agg_tax_change equal to False rec = Records.cps_constructor(data=cps_subsample) cyr = 2020 # specify calc1 and calc_all() for cyr pol = Policy() calc1 = Calculator(policy=pol, records=rec) calc1.advance_to_year(cyr) calc1.calc_all() # specify calc2 and calc_all() for cyr reform = {'II_em': {2019: 1000}} pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec) calc2.advance_to_year(cyr) calc2.calc_all() df1 = calc1.dataframe(['s006', 'combined', 'expanded_income']) df2 = calc2.dataframe(['s006', 'combined', 'expanded_income']) cedict = ce_aftertax_expanded_income(df1, df2, require_no_agg_tax_change=False) assert isinstance(cedict, dict) np.allclose(cedict['ceeu1'], [55641, 27167, 5726, 2229, 1565], atol=0.5, rtol=0.0) np.allclose(cedict['ceeu2'], [54629, 26698, 5710, 2229, 1565], atol=0.5, rtol=0.0) # test with require_no_agg_tax_change equal to True with pytest.raises(ValueError): ce_aftertax_expanded_income(df1, df2, require_no_agg_tax_change=True) # test with require_no_agg_tax_change equal to False and custom_params params = {'crra_list': [0, 2], 'cmin_value': 2000} with pytest.raises(ValueError): ce_aftertax_expanded_income(df1, df2, require_no_agg_tax_change=True, custom_params=params)
def test_credit_reforms(puf_subsample): """ Test personal credit reforms using puf.csv subsample """ rec = Records(data=puf_subsample) reform_year = 2017 # create current-law Calculator object, calc1 pol = Policy() calc1 = Calculator(policy=pol, records=rec) calc1.advance_to_year(reform_year) calc1.calc_all() itax1 = calc1.weighted_total('iitax') # create personal-refundable-credit-reform Calculator object, calc2 reform = {reform_year: {'_II_credit': [[1000, 1000, 1000, 1000, 1000]]}} pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec) calc2.advance_to_year(reform_year) calc2.calc_all() itax2 = calc2.weighted_total('iitax') # create personal-nonrefundable-credit-reform Calculator object, calc3 reform = {reform_year: {'_II_credit_nr': [[1000, 1000, 1000, 1000, 1000]]}} pol = Policy() pol.implement_reform(reform) calc3 = Calculator(policy=pol, records=rec) calc3.advance_to_year(reform_year) calc3.calc_all() itax3 = calc3.weighted_total('iitax') # check income tax revenues generated by the three Calculator objects assert itax2 < itax1 # because refundable credits lower revenues assert itax3 > itax2 # because nonrefundable credits lower revenues less assert itax3 < itax1 # because nonrefundable credits lower revenues some
def test_credit_reforms(puf_subsample): """ Test personal credit reforms using puf.csv subsample """ rec = Records(data=puf_subsample) reform_year = 2017 # create current-law Calculator object, calc1 pol = Policy() calc1 = Calculator(policy=pol, records=rec) calc1.advance_to_year(reform_year) calc1.calc_all() itax1 = calc1.weighted_total('iitax') # create personal-refundable-credit-reform Calculator object, calc2 reform = {'II_credit': {reform_year: [1000, 1000, 1000, 1000, 1000]}} pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec) calc2.advance_to_year(reform_year) calc2.calc_all() itax2 = calc2.weighted_total('iitax') # create personal-nonrefundable-credit-reform Calculator object, calc3 reform = {'II_credit_nr': {reform_year: [1000, 1000, 1000, 1000, 1000]}} pol = Policy() pol.implement_reform(reform) calc3 = Calculator(policy=pol, records=rec) calc3.advance_to_year(reform_year) calc3.calc_all() itax3 = calc3.weighted_total('iitax') # check income tax revenues generated by the three Calculator objects assert itax2 < itax1 # because refundable credits lower revenues assert itax3 > itax2 # because nonrefundable credits lower revenues less assert itax3 < itax1 # because nonrefundable credits lower revenues some
def run_reform(name, reform, epsilon): puf = pd.read_csv("./puf.csv") policy_base = Policy(start_year=2013) records_base = Records(puf) policy_reform = Policy() records_reform = Records(puf) calcbase = Calculator(policy = policy_base, records = records_base) calcreform = Calculator(policy = policy_reform, records = records_reform) policy_reform.implement_reform(reform) calcbase.advance_to_year(CURRENT_YEAR) calcreform.advance_to_year(CURRENT_YEAR) calcbase.calc_all() calcreform.calc_all() diff_df = get_diff(calcbase, calcreform, name) data_df = print_data(calcbase, calcreform, weights = weighted, tab = 'c00100', name=name) equiv_tax_cut = reform_equiv(reform, epsilon) total_rev_raise = agg_diff(calcbase, calcreform) delta_num_filers = agg_num_delta(calcbase, calcreform) #diff_df['equiv_rate_cut'] = len(diff_df)*[equiv_tax_cut] return diff_df, data_df, equiv_tax_cut, total_rev_raise, delta_num_filers
def test_Calculator_create_difference_table(puf_1991, weights_1991): # create current-law Policy object and use to create Calculator calc1 policy1 = Policy() puf1 = Records(data=puf_1991, weights=weights_1991, start_year=2009) calc1 = Calculator(policy=policy1, records=puf1) calc1.advance_to_year(2013) calc1.calc_all() # create policy-reform Policy object and use to create Calculator calc2 policy2 = Policy() reform = { 2013: {'_II_rt7': [0.45]}, 2013: {'_ALD_Investment_ec_base_code_active': [True]}, 0: {'ALD_Investment_ec_base_code': 'e00300 + e00650 + p23250'} } policy2.implement_reform(reform) puf2 = Records(data=puf_1991, weights=weights_1991, start_year=2009) calc2 = Calculator(policy=policy2, records=puf2) calc2.advance_to_year(2013) calc2.calc_all() # create difference table and check that it is a Pandas DataFrame dtable = create_difference_table(calc1.records, calc2.records, groupby="weighted_deciles") assert isinstance(dtable, pd.DataFrame)
def test_dec_graph_plot(cps_subsample): pol = Policy() rec = Records.cps_constructor(data=cps_subsample) calc1 = Calculator(policy=pol, records=rec) year = 2020 reform = { year: { '_SS_Earnings_c': [9e99], # OASDI FICA tax on all earnings '_FICA_ss_trt': [0.107484] # lower rate to keep revenue unchanged } } pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec) calc1.advance_to_year(year) with pytest.raises(ValueError): dec_graph_data(calc1, calc2) calc2.advance_to_year(year) gdata = dec_graph_data(calc1, calc2) assert isinstance(gdata, dict) deciles = gdata['bars'].keys() assert len(deciles) == 14 gplot = dec_graph_plot(gdata, xlabel='', ylabel='') assert gplot
def taxcalc_results(start_year, reform_dict, itax_clp, fica_clp): """ Use taxcalc package on this computer to compute aggregate income tax and payroll tax revenue difference (between reform and current-law policy) for ten years beginning with the specified start_year using the specified reform_dict dictionary and the two specified current-law-policy results dictionaries. Return two aggregate tax revenue difference dictionaries indexed by calendar year. """ pol = Policy() pol.implement_reform(reform_dict) calc = Calculator(policy=pol, records=Records(data=PUF_PATH)) calc.advance_to_year(start_year) adt = calc.diagnostic_table(num_years=NUMBER_OF_YEARS) # note that adt is Pandas DataFrame object itax_ref = adt.xs('Ind inc tax ($b)').to_dict() fica_ref = adt.xs('Payroll tax ($b)').to_dict() itax_diff = {} fica_diff = {} for year in itax_ref: itax_diff[year] = round(itax_ref[year] - itax_clp[year], 1) fica_diff[year] = round(fica_ref[year] - fica_clp[year], 1) return (itax_diff, fica_diff)
def diff_in_revenue(reform_on_II, orig_reform): policy_func = Policy() puf = pd.read_csv("./puf.csv") records_func = Records(puf) calc_func = Calculator(policy=policy_func, records=records_func) policy_bench = Policy() records_bench = Records(puf) calc_bench = Calculator(policy=policy_bench, records=records_bench) reform = { CURRENT_YEAR: { "_II_rt1": [max(policy_bench._II_rt1[0] * (1 - reform_on_II), 0.0)], "_II_rt2": [max(policy_bench._II_rt2[0] * (1 - reform_on_II), 0.0)], "_II_rt3": [max(policy_bench._II_rt3[0] * (1 - reform_on_II), 0.0)], "_II_rt4": [max(policy_bench._II_rt4[0] * (1 - reform_on_II), 0.0)], "_II_rt5": [max(policy_bench._II_rt5[0] * (1 - reform_on_II), 0.0)], "_II_rt6": [max(policy_bench._II_rt6[0] * (1 - reform_on_II), 0.0)], "_II_rt7": [max(policy_bench._II_rt7[0] * (1 - reform_on_II), 0.0)] } } policy_func.implement_reform(reform) policy_func.implement_reform(orig_reform) calc_func.advance_to_year(CURRENT_YEAR) calc_bench.advance_to_year(CURRENT_YEAR) calc_func.calc_all() calc_bench.calc_all() ans = ((calc_bench.records._combined * calc_bench.records.s006).sum() - (calc_func.records._combined * calc_func.records.s006).sum()) print("diff in revenue is ", ans) return ans
def test_ce_aftertax_income(cps_subsample): # test certainty_equivalent() function with con>cmin con = 5000 cmin = 1000 assert con == round(certainty_equivalent(con, 0, cmin), 6) assert con > round(certainty_equivalent((math.log(con) - 0.1), 1, cmin), 6) # test certainty_equivalent() function with con<cmin con = 500 cmin = 1000 assert con == round(certainty_equivalent(con, 0, cmin), 6) # test with require_no_agg_tax_change equal to False rec = Records.cps_constructor(data=cps_subsample) cyr = 2020 # specify calc1 and calc_all() for cyr pol = Policy() calc1 = Calculator(policy=pol, records=rec) calc1.advance_to_year(cyr) calc1.calc_all() # specify calc2 and calc_all() for cyr reform = {2018: {'_II_em': [0.0]}} pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec) calc2.advance_to_year(cyr) calc2.calc_all() cedict = ce_aftertax_income(calc1, calc2, require_no_agg_tax_change=False) assert cedict['year'] == cyr # test with require_no_agg_tax_change equal to True with pytest.raises(ValueError): ce_aftertax_income(calc1, calc2, require_no_agg_tax_change=True) # test with require_no_agg_tax_change equal to False and custom_params params = {'crra_list': [0, 2], 'cmin_value': 2000} with pytest.raises(ValueError): ce_aftertax_income(calc1, calc2, require_no_agg_tax_change=True, custom_params=params)
def test_credit_reforms(puf_path): # pylint: disable=redefined-outer-name """ Test personal credit reforms using small puf.csv sub-sample """ # pylint: disable=too-many-locals reform_year = 2017 fullsample = pd.read_csv(puf_path) subsample = fullsample.sample( frac=0.05, # pylint: disable=no-member random_state=180) # create current-law Calculator object, calc1 recs1 = Records(data=subsample) calc1 = Calculator(policy=Policy(), records=recs1) calc1.advance_to_year(reform_year) calc1.calc_all() itax1 = (calc1.records.iitax * calc1.records.s006).sum() # create personal-refundable-credit-reform Calculator object, calc2 recs2 = Records(data=subsample) policy2 = Policy() reform = {reform_year: {'_II_credit': [[1000, 1000, 1000, 1000, 1000]]}} policy2.implement_reform(reform) calc2 = Calculator(policy=policy2, records=recs2) calc2.advance_to_year(reform_year) calc2.calc_all() itax2 = (calc2.records.iitax * calc2.records.s006).sum() # create personal-nonrefundable-credit-reform Calculator object, calc3 recs3 = Records(data=subsample) policy3 = Policy() reform = {reform_year: {'_II_credit_nr': [[1000, 1000, 1000, 1000, 1000]]}} policy3.implement_reform(reform) calc3 = Calculator(policy=policy3, records=recs3) calc3.advance_to_year(reform_year) calc3.calc_all() itax3 = (calc3.records.iitax * calc3.records.s006).sum() # check income tax revenues generated by the three Calculator objects assert itax2 < itax1 # because refundable credits lower revenues assert itax3 > itax2 # because nonrefundable credits lower revenues less assert itax3 < itax1 # because nonrefundable credits lower revenues some
def test_benefits(tests_path, cps_fullsample): """ Test CPS benefits. """ # pylint: disable=too-many-locals benefit_names = ['ssi', 'mcare', 'mcaid', 'snap', 'wic', 'tanf', 'vet', 'housing'] # write benefits_actual.csv file recs = Records.cps_constructor(data=cps_fullsample) start_year = recs.current_year calc = Calculator(policy=Policy(), records=recs, verbose=False) assert calc.current_year == start_year year_list = list() bname_list = list() benamt_list = list() bencnt_list = list() benavg_list = list() for year in range(start_year, Policy.LAST_BUDGET_YEAR + 1): calc.advance_to_year(year) size = calc.array('XTOT') wght = calc.array('s006') # compute benefit aggregate amounts and head counts and average benefit # (head counts include all members of filing unit receiving a benefit, # which means benavg is f.unit benefit amount divided by f.unit size) for bname in benefit_names: ben = calc.array('{}_ben'.format(bname)) benamt = round((ben * wght).sum() * 1e-9, 3) bencnt = round((size[ben > 0] * wght[ben > 0]).sum() * 1e-6, 3) benavg = round(benamt / bencnt, 1) year_list.append(year) bname_list.append(bname) benamt_list.append(benamt) bencnt_list.append(bencnt) benavg_list.append(benavg) adict = {'year': year_list, 'bname': bname_list, 'benamt': benamt_list, 'bencnt': bencnt_list, 'benavg': benavg_list} adf = pd.DataFrame(data=adict, columns=['year', 'bname', 'benamt', 'bencnt', 'benavg']) ben_act_path = os.path.join(tests_path, 'benefits_actual.csv') adf.to_csv(ben_act_path, index=False) # read benefits_expect.csv file ben_exp_path = os.path.join(tests_path, 'benefits_expect.csv') edf = pd.read_csv(ben_exp_path) # compare benefit information atol = 0.0001 rtol = 0.0 diffs = False for col in ['benamt', 'bencnt', 'benavg']: if not np.allclose(adf[col], edf[col], atol=atol, rtol=rtol): diffs = True if diffs: msg = 'CPS BENEFITS RESULTS DIFFER\n' msg += '-------------------------------------------------\n' msg += '--- NEW RESULTS IN benefits_actual.txt FILE ---\n' msg += '--- if new OK, copy benefits_actual.txt to ---\n' msg += '--- benefits_expect.txt ---\n' msg += '--- and rerun test. ---\n' msg += '-------------------------------------------------\n' raise ValueError(msg) else: os.remove(ben_act_path)
beh2 = Behavior() if "_BE_cg" in REFORMS_JSON.get(this_reform).get("value"): elasticity = REFORMS_JSON[this_reform]["value"]["_BE_cg"] del REFORMS_JSON[this_reform]["value"]["_BE_cg"] # to not break reform beh_assump = {start_year: {"_BE_cg": elasticity}} beh2.update_behavior(beh_assump) reform = {start_year: REFORMS_JSON.get(this_reform).get("value")} pol2 = Policy() pol2.implement_reform(reform) rec2 = Records(data=PUF_DATA) calc2 = Calculator(policy=pol2, records=rec2, verbose=False, behavior=beh2) output_type = REFORMS_JSON.get(this_reform).get("output_type") reform_name = REFORMS_JSON.get(this_reform).get("name") # increment both calculators to reform's start_year calc1.advance_to_year(start_year) calc2.advance_to_year(start_year) # calculate prereform and postreform for num_years reform_results = [] for _ in range(0, NUM_YEARS): calc1.calc_all() prereform = getattr(calc1.records, output_type) if calc2.behavior.has_response(): calc_clp = calc2.current_law_version() calc2_br = Behavior.response(calc_clp, calc2) postreform = getattr(calc2_br.records, output_type) else: calc2.calc_all() postreform = getattr(calc2.records, output_type) diff = postreform - prereform
def test_reform_json_and_output(): """ Check that each JSON reform file can be converted into a reform dictionary that can then be passed to the Policy class implement_reform method that generates no parameter_errors. Then use each reform to generate static tax results for small set of filing units in a single tax_year and compare those results with expected results from a CSV-formatted file. """ # pylint: disable=too-many-statements,too-many-locals # embedded function used only in test_reform_json_and_output def write_res_file(calc, resfilename): """ Write calc output to CSV-formatted file with resfilename. """ varlist = [ 'RECID', 'c00100', 'standard', 'c04800', 'iitax', 'payrolltax' ] # varnames AGI STD TaxInc ITAX PTAX stats = calc.dataframe(varlist) stats['RECID'] = stats['RECID'].astype(int) with open(resfilename, 'w') as resfile: stats.to_csv(resfile, index=False, float_format='%.2f') # embedded function used only in test_reform_json_and_output def res_and_out_are_same(base): """ Return True if base.res.csv and base.out.csv file contents are same; return False if base.res.csv and base.out.csv file contents differ. """ resdf = pd.read_csv(base + '.res.csv') outdf = pd.read_csv(base + '.out.csv') diffs = False for col in resdf: if col in outdf: if not np.allclose(resdf[col], outdf[col]): diffs = True else: diffs = True return not diffs # specify Records object containing cases data tax_year = 2020 cases_path = os.path.join(CUR_PATH, '..', 'taxcalc', 'cases.csv') cases = Records( data=cases_path, start_year=tax_year, # set raw input data year gfactors=None, # keeps raw data unchanged weights=None, adjust_ratios=None) # specify list of reform failures failures = list() # specify current-law-policy Calculator object calc = Calculator(policy=Policy(), records=cases, verbose=False) calc.advance_to_year(tax_year) calc.calc_all() res_path = cases_path.replace('cases.csv', 'clp.res.csv') write_res_file(calc, res_path) if res_and_out_are_same(res_path.replace('.res.csv', '')): os.remove(res_path) else: failures.append(res_path) del calc # read 2017_law.json reform file and specify its parameters dictionary pre_tcja_jrf = os.path.join(CUR_PATH, '..', 'taxcalc', '2017_law.json') pre_tcja = Policy.read_json_reform(pre_tcja_jrf) # check reform file contents and reform results for each reform reforms_path = os.path.join(CUR_PATH, '..', 'taxcalc', '*.json') json_reform_files = glob.glob(reforms_path) for jrf in json_reform_files: # determine reform's baseline by reading contents of jrf with open(jrf, 'r') as rfile: jrf_text = rfile.read() pre_tcja_baseline = 'Reform_Baseline: 2017_law.json' in jrf_text # implement the reform relative to its baseline reform = Policy.read_json_reform(jrf_text) pol = Policy() # current-law policy if pre_tcja_baseline: pol.implement_reform(pre_tcja) assert not pol.parameter_errors pol.implement_reform(reform) assert not pol.parameter_errors calc = Calculator(policy=pol, records=cases, verbose=False) calc.advance_to_year(tax_year) calc.calc_all() res_path = jrf.replace('.json', '.res.csv') write_res_file(calc, res_path) if res_and_out_are_same(res_path.replace('.res.csv', '')): os.remove(res_path) else: failures.append(res_path) del calc if failures: msg = 'Following reforms have res-vs-out differences:\n' for ref in failures: msg += '{}\n'.format(os.path.basename(ref)) raise ValueError(msg)
def test_itemded_component_amounts(year, cvname, hcname, puf_fullsample): """ Check that all c04470 components are adjusted to reflect the filing unit's standard-vs-itemized-deduction decision. Check for 2018 (when current law has no Pease phaseout of itemized deductions and already has complete haircuts for Casualty and Miscellaneous deductions) and 2017 (when current law has a Pease phaseout of itemized deductions and has no haircuts). The calcfunctions.py code makes no attempt to adjust the components for the effects of Pease-like phaseout or any other type of limitation on total itemized deductions, so the pre-2018 tests here use c21060, instead of c04470, as the itemized deductions total. """ # pylint: disable=too-many-locals recs = Records(data=puf_fullsample) # policy1 such that everybody itemizes deductions and all are allowed policy1 = Policy() reform1 = { 'STD_Aged': {year: [0.0, 0.0, 0.0, 0.0, 0.0]}, 'STD': {year: [0.0, 0.0, 0.0, 0.0, 0.0]} } policy1.implement_reform(reform1) assert not policy1.parameter_errors # policy2 such that everybody itemizes deductions but one is disallowed policy2 = Policy() reform2 = { 'STD_Aged': {year: [0.0, 0.0, 0.0, 0.0, 0.0]}, 'STD': {year: [0.0, 0.0, 0.0, 0.0, 0.0]}, hcname: {year: 1.0} } policy2.implement_reform(reform2) assert not policy2.parameter_errors # compute tax liability in specified year calc1 = Calculator(policy=policy1, records=recs, verbose=False) calc1.advance_to_year(year) calc1.calc_all() calc2 = Calculator(policy=policy2, records=recs, verbose=False) calc2.advance_to_year(year) calc2.calc_all() # confirm that nobody is taking the standard deduction assert np.allclose(calc1.array('standard'), 0.) assert np.allclose(calc2.array('standard'), 0.) # calculate different in total itemized deductions if year == 2017: # pre-Pease limitation total itemized deductions itmded1 = calc1.weighted_total('c21060') * 1e-9 itmded2 = calc2.weighted_total('c21060') * 1e-9 elif year == 2018: # total itemized deductions (no Pease-like limitation) itmded1 = calc1.weighted_total('c04470') * 1e-9 itmded2 = calc2.weighted_total('c04470') * 1e-9 else: raise ValueError('illegal year value = {}'.format(year)) difference_in_total_itmded = itmded1 - itmded2 # calculate itemized component amount component_amt = calc1.weighted_total(cvname) * 1e-9 # confirm that component amount is equal to difference in total deductions if year == 2017 and cvname == 'c19700': atol = 0.009 elif year == 2017 and cvname == 'c19200': atol = 0.010 else: atol = 0.00001 if not np.allclose(component_amt, difference_in_total_itmded, atol=atol): txt = '\n{}={:.3f} != {:.3f}=difference_in_total_itemized_deductions' msg = txt.format(cvname, component_amt, difference_in_total_itmded) raise ValueError(msg)
def test_reform_json_and_output(tests_path): """ Check that each JSON reform file can be converted into a reform dictionary that can then be passed to the Policy class implement_reform method that generates no parameter_errors. Then use each reform to generate static tax results for small set of filing units in a single tax_year and compare those results with expected results from a text file. """ # pylint: disable=too-many-statements,too-many-locals used_dist_stats = ['c00100', # AGI 'c04600', # personal exemptions 'standard', # standard deduction 'c04800', # regular taxable income 'c05800', # income tax before credits 'iitax', # income tax after credits 'payrolltax', # payroll taxes 'aftertax_income'] # aftertax expanded income unused_dist_stats = set(DIST_TABLE_COLUMNS) - set(used_dist_stats) renamed_columns = {'c00100': 'AGI', 'c04600': 'pexempt', 'standard': 'stdded', 'c04800': 'taxinc', 'c05800': 'tax-wo-credits', 'iitax': 'inctax', 'payrolltax': 'paytax', 'aftertax_income': 'ataxinc'} # embedded function used only in test_reform_json_and_output def write_distribution_table(calc, resfilename): """ Write abbreviated distribution table calc to file with resfilename. """ dist, _ = calc.distribution_tables(None, 'standard_income_bins', scaling=False) for stat in unused_dist_stats: del dist[stat] dist = dist[used_dist_stats] dist.rename(mapper=renamed_columns, axis='columns', inplace=True) with open(resfilename, 'w') as resfile: dist.to_string(resfile, float_format='%7.0f') # embedded function used only in test_reform_json_and_output def res_and_out_are_same(base): """ Return True if base.res and base.out file contents are the same; return False if base.res and base.out file contents differ. """ with open(base + '.res') as resfile: act_res = resfile.read() with open(base + '.out') as outfile: exp_res = outfile.read() # check to see if act_res & exp_res have differences return not nonsmall_diffs(act_res.splitlines(True), exp_res.splitlines(True)) # specify Records object containing cases data tax_year = 2020 cases_path = os.path.join(tests_path, '..', 'reforms', 'cases.csv') cases = Records(data=cases_path, gfactors=None, # keeps raw data unchanged weights=None, adjust_ratios=None, start_year=tax_year) # set raw input data year # specify list of reform failures failures = list() # specify current-law-policy Calculator object calc1 = Calculator(policy=Policy(), records=cases, verbose=False) calc1.advance_to_year(tax_year) calc1.calc_all() res_path = cases_path.replace('cases.csv', 'clp.res') write_distribution_table(calc1, res_path) if res_and_out_are_same(res_path.replace('.res', '')): os.remove(res_path) else: failures.append(res_path) # read 2017_law.json reform file and specify its parameters dictionary pre_tcja_jrf = os.path.join(tests_path, '..', 'reforms', '2017_law.json') pre_tcja = Calculator.read_json_param_objects(pre_tcja_jrf, None) # check reform file contents and reform results for each reform reforms_path = os.path.join(tests_path, '..', 'reforms', '*.json') json_reform_files = glob.glob(reforms_path) for jrf in json_reform_files: # determine reform's baseline by reading contents of jrf with open(jrf, 'r') as rfile: jrf_text = rfile.read() pre_tcja_baseline = 'Reform_Baseline: 2017_law.json' in jrf_text # implement the reform relative to its baseline reform = Calculator.read_json_param_objects(jrf_text, None) pol = Policy() # current-law policy if pre_tcja_baseline: pol.implement_reform(pre_tcja['policy']) pol.implement_reform(reform['policy']) assert not pol.parameter_errors calc2 = Calculator(policy=pol, records=cases, verbose=False) calc2.advance_to_year(tax_year) calc2.calc_all() res_path = jrf.replace('.json', '.res') write_distribution_table(calc2, res_path) if res_and_out_are_same(res_path.replace('.res', '')): os.remove(res_path) else: failures.append(res_path) if failures: msg = 'Following reforms have res-vs-out differences:\n' for ref in failures: msg += '{}\n'.format(os.path.basename(ref)) raise ValueError(msg)
def test_reform_json_and_output(tests_path): """ Check that each JSON reform file can be converted into a reform dictionary that can then be passed to the Policy class implement_reform method that generates no parameter_errors. Then use each reform to generate static tax results for small set of filing units in a single tax_year and compare those results with expected results from a CSV-formatted file. """ # pylint: disable=too-many-statements,too-many-locals # embedded function used only in test_reform_json_and_output def write_res_file(calc, resfilename): """ Write calc output to CSV-formatted file with resfilename. """ varlist = [ 'RECID', 'c00100', 'standard', 'c04800', 'iitax', 'payrolltax' ] # varnames AGI STD TaxInc ITAX PTAX stats = calc.dataframe(varlist) stats['RECID'] = stats['RECID'].astype(int) with open(resfilename, 'w') as resfile: stats.to_csv(resfile, index=False, float_format='%.2f') # embedded function used only in test_reform_json_and_output def res_and_out_are_same(base): """ Return True if base.res.csv and base.out.csv file contents are same; return False if base.res.csv and base.out.csv file contents differ. """ resdf = pd.read_csv(base + '.res.csv') outdf = pd.read_csv(base + '.out.csv') diffs = False for col in resdf: if col in outdf: if not np.allclose(resdf[col], outdf[col]): diffs = True else: diffs = True return not diffs # specify Records object containing cases data tax_year = 2020 cases_path = os.path.join(tests_path, '..', 'reforms', 'cases.csv') cases = Records(data=cases_path, start_year=tax_year, # set raw input data year gfactors=None, # keeps raw data unchanged weights=None, adjust_ratios=None) # specify list of reform failures failures = list() # specify current-law-policy Calculator object calc = Calculator(policy=Policy(), records=cases, verbose=False) calc.advance_to_year(tax_year) calc.calc_all() res_path = cases_path.replace('cases.csv', 'clp.res.csv') write_res_file(calc, res_path) if res_and_out_are_same(res_path.replace('.res.csv', '')): os.remove(res_path) else: failures.append(res_path) del calc # read 2017_law.json reform file and specify its parameters dictionary pre_tcja_jrf = os.path.join(tests_path, '..', 'reforms', '2017_law.json') pre_tcja = Policy.read_json_reform(pre_tcja_jrf) # check reform file contents and reform results for each reform reforms_path = os.path.join(tests_path, '..', 'reforms', '*.json') json_reform_files = glob.glob(reforms_path) for jrf in json_reform_files: # determine reform's baseline by reading contents of jrf with open(jrf, 'r') as rfile: jrf_text = rfile.read() pre_tcja_baseline = 'Reform_Baseline: 2017_law.json' in jrf_text # implement the reform relative to its baseline reform = Policy.read_json_reform(jrf_text) pol = Policy() # current-law policy if pre_tcja_baseline: pol.implement_reform(pre_tcja) assert not pol.parameter_errors pol.implement_reform(reform) assert not pol.parameter_errors calc = Calculator(policy=pol, records=cases, verbose=False) calc.advance_to_year(tax_year) calc.calc_all() res_path = jrf.replace('.json', '.res.csv') write_res_file(calc, res_path) if res_and_out_are_same(res_path.replace('.res.csv', '')): os.remove(res_path) else: failures.append(res_path) del calc if failures: msg = 'Following reforms have res-vs-out differences:\n' for ref in failures: msg += '{}\n'.format(os.path.basename(ref)) raise ValueError(msg)
reforms_json = json.load(json_file) num_reforms = len(reforms_json) # create two calculators, one for baseline and the other for reforms tax_dta1 = pd.read_csv(PUF_PATH) records1 = Records(tax_dta1) policy1 = Policy(start_year=2013) calc1 = Calculator(records=records1, policy=policy1) tax_dta2 = pd.read_csv(PUF_PATH) records2 = Records(tax_dta2) policy2 = Policy(start_year=2013) calc2 = Calculator(records=records2, policy=policy2) # increment both calculators to 2015, when most reforms start calc1.advance_to_year(2015) calc2.advance_to_year(2015) # create a dictionary to save all results results = {} # runs one reform a time, each reform for 4 years # modify the number of reform & number of years as needed for i in range(1, num_reforms + 1): # make two deep copies so the originals could be used again in next loop c1 = copy.deepcopy(calc1) c2 = copy.deepcopy(calc2) # fetch this reform from json and implement in policy object this_reform = 'r' + str(i) start_year = reforms_json.get(this_reform).get("start_year")
def test_agg(tests_path, cps_fullsample): """ Test current-law aggregate taxes using cps.csv file. """ # pylint: disable=too-many-statements,too-many-locals nyrs = 10 # create a baseline Policy object with current-law policy parameters baseline_policy = Policy() # create a Records object (rec) containing all cps.csv input records recs = Records.cps_constructor(data=cps_fullsample) # create a Calculator object using baseline policy and cps records calc = Calculator(policy=baseline_policy, records=recs) calc.advance_to_year(START_YEAR) calc_start_year = calc.current_year # create aggregate diagnostic table (adt) as a Pandas DataFrame object adt = calc.diagnostic_table(nyrs).round(1) # column labels are int taxes_fullsample = adt.loc["Combined Liability ($b)"] # compare actual DataFrame, adt, with the expected DataFrame, edt aggres_path = os.path.join(tests_path, 'cpscsv_agg_expect.csv') edt = pd.read_csv(aggres_path, index_col=False) # column labels are str edt.drop('Unnamed: 0', axis='columns', inplace=True) assert len(adt.columns.values) == len(edt.columns.values) diffs = False for icol in adt.columns.values: if not np.allclose(adt[icol], edt[str(icol)]): diffs = True if diffs: new_filename = '{}{}'.format(aggres_path[:-10], 'actual.csv') adt.to_csv(new_filename, float_format='%.1f') msg = 'CPSCSV AGG RESULTS DIFFER\n' msg += '-------------------------------------------------\n' msg += '--- NEW RESULTS IN cpscsv_agg_actual.csv FILE ---\n' msg += '--- if new OK, copy cpscsv_agg_actual.csv to ---\n' msg += '--- cpscsv_agg_expect.csv ---\n' msg += '--- and rerun test. ---\n' msg += '-------------------------------------------------\n' raise ValueError(msg) # create aggregate diagnostic table using unweighted sub-sample of records rn_seed = 180 # to ensure sub-sample is always the same subfrac = 0.03 # sub-sample fraction subsample = cps_fullsample.sample(frac=subfrac, random_state=rn_seed) recs_subsample = Records.cps_constructor(data=subsample) calc_subsample = Calculator(policy=baseline_policy, records=recs_subsample) calc_subsample.advance_to_year(START_YEAR) adt_subsample = calc_subsample.diagnostic_table(nyrs) # compare combined tax liability from full and sub samples for each year taxes_subsample = adt_subsample.loc["Combined Liability ($b)"] msg = '' for cyr in range(calc_start_year, calc_start_year + nyrs): if cyr == calc_start_year: reltol = 0.0141 else: reltol = 0.0105 if not np.allclose(taxes_subsample[cyr], taxes_fullsample[cyr], atol=0.0, rtol=reltol): reldiff = (taxes_subsample[cyr] / taxes_fullsample[cyr]) - 1. line1 = '\nCPSCSV AGG SUB-vs-FULL RESULTS DIFFER IN {}' line2 = '\n when subfrac={:.3f}, rtol={:.4f}, seed={}' line3 = '\n with sub={:.3f}, full={:.3f}, rdiff={:.4f}' msg += line1.format(cyr) msg += line2.format(subfrac, reltol, rn_seed) msg += line3.format(taxes_subsample[cyr], taxes_fullsample[cyr], reldiff) if msg: raise ValueError(msg)
def main(mpc_e17500, mpc_e18400, mpc_e19800, mpc_e20400): """ Highest-level logic of consumption.py script that produces Tax-Calculator marginal-tax-rate results running the taxcalc package on this computer. """ # pylint: disable=too-many-locals # pylint: disable=too-many-statements if not os.path.isfile(PUFCSV_PATH): sys.stderr.write('ERROR: file {} does not exist\n'.format(PUFCSV_PATH)) return 1 cyr = 2014 # compute mtr under current-law policy with no consumption response recs0 = Records(data=PUFCSV_PATH) calc0 = Calculator(policy=Policy(), records=recs0, consumption=None, verbose=False) calc0.advance_to_year(cyr) wghts = calc0.records.s006 (mtr0_fica, mtr0_itax, _) = calc0.mtr(income_type_str='e00200p', wrt_full_compensation=False) # compute mtr under current-law policy with specified consumption response consump = Consumption() consump_mpc = {cyr: {'_MPC_e17500': [mpc_e17500], '_MPC_e18400': [mpc_e18400], '_MPC_e19800': [mpc_e19800], '_MPC_e20400': [mpc_e20400]}} consump.update_consumption(consump_mpc) recs1 = Records(data=PUFCSV_PATH) calc1 = Calculator(policy=Policy(), records=recs1, consumption=consump, verbose=False) calc1.advance_to_year(cyr) assert calc1.consumption.current_year == cyr (mtr1_fica, mtr1_itax, _) = calc1.mtr(income_type_str='e00200p', wrt_full_compensation=False) # compare unweighted mtr results with and without consumption response epsilon = 1.0e-6 # this would represent a mtr of 0.0001 percent assert np.allclose(mtr1_fica, mtr0_fica, atol=epsilon, rtol=0.0) mtr_raw_diff = mtr1_itax - mtr0_itax mtr1_itax = np.where(np.logical_and(mtr_raw_diff > 0.0, mtr_raw_diff < epsilon), mtr0_itax, mtr1_itax) # zero out small positive diffs num_total = mtr1_itax.size num_increases = np.sum(np.greater(mtr1_itax, mtr0_itax)) num_decreases = np.sum(np.less(mtr1_itax, mtr0_itax)) num_nochanges = num_total - num_increases - num_decreases res = 'unweighted_num_of_mtr_{}_with_consump_response= {:6d} ({:5.1f}%)\n' sys.stdout.write(res.format('increases', num_increases, (100.0 * num_increases) / num_total)) sys.stdout.write(res.format('decreases', num_decreases, (100.0 * num_decreases) / num_total)) sys.stdout.write(res.format('nochanges', num_nochanges, (100.0 * num_nochanges) / num_total)) sys.stdout.write(res.format('all_units', num_total, 100.0)) # compute average size of decreases in mtr_itax mtr_pre = mtr0_itax[mtr1_itax < mtr0_itax] assert mtr_pre.size == num_decreases avg_pre = np.mean(mtr_pre) res = 'unweighted_abs_mean_no_c_resp(for_decreases)mtr_itax= {:.4f}\n' sys.stdout.write(res.format(avg_pre)) mtr_diff = mtr1_itax - mtr0_itax mtr_neg = mtr_diff[mtr_diff < 0.0] assert mtr_neg.size == num_decreases avg_neg = np.mean(mtr_neg) assert avg_neg < 0.0 res = 'unweighted_abs_mean_change(for_decreases)in_mtr_itax= {:.4f}\n' sys.stdout.write(res.format(-avg_neg)) res = ' ratio_of_abs_change_in_mtr_itax_and_no_c_resp_mtr_itax= {:.3f}\n' sys.stdout.write(res.format(-avg_neg / avg_pre)) # compare weighted mtr results with and without consumption response wghts_pre = wghts[mtr1_itax < mtr0_itax] assert wghts_pre.size == num_decreases res = 'weighted_percent_of_units_with_mtr_decrease= {:.1f}%\n' frac = wghts_pre.sum() / wghts.sum() sys.stdout.write(res.format(100.0 * frac)) res = ' ratio_of_abs_change_in_mtr_itax_and_no_c_resp_mtr_itax= {:.3f}\n' w_avg_pre = np.mean((mtr_pre * wghts_pre).sum() / wghts_pre.sum()) w_avg_neg = np.mean((mtr_neg * wghts_pre).sum() / wghts_pre.sum()) sys.stdout.write(res.format(-w_avg_neg / w_avg_pre)) # return no-error exit code return 0
def test_compatible_data(cps_subsample, puf_subsample, allparams, reform_xx, tc_objs, allparams_batch): """ Test that the compatible_data attribute in policy_current_law.json is accurate by implementing the min and max values of each parameter as reforms and ensuring that revenue differs from baseline when for at least one of these reforms when using datasets marked compatible and does not differ when using datasets marked as incompatible. """ # pylint: disable=too-many-arguments,too-many-locals # pylint: disable=too-many-statements,too-many-branches # Check NPARAMS value assert NPARAMS == len(allparams) # Get taxcalc objects from tc_objs fixture rec_xx, c_xx, puftest = tc_objs # These parameters are exempt because they are not active under # current law and activating them would deactivate other parameters, # or if it is difficult to devise a test for them. exempt_from_testing = [ 'CG_ec', 'CG_reinvest_ec_rt', 'II_prt', 'ID_prt', 'ID_crt', 'CR_SchR_hc', 'ACTC_ChildNum' ] # Loop through the parameters in allparams_batch errmsg = 'ERROR: {} {}\n' errors = '' for pname in allparams_batch: param = allparams_batch[pname] max_listed = param['valid_values']['max'] # handle links to other params or self if isinstance(max_listed, str): if isinstance(allparams[max_listed]['value'][0], list): max_val = allparams[max_listed]['value'][0] else: max_val = float(allparams[max_listed]['value'][0]) else: if isinstance(param['value'][0], list): max_val = [max_listed] * len(param['value'][0]) else: max_val = max_listed min_listed = param['valid_values']['min'] if isinstance(min_listed, str): if isinstance(allparams[min_listed]['value'][0], list): min_val = allparams[min_listed]['value'][0] else: min_val = float(allparams[min_listed]['value'][0]) else: if isinstance(param['value'][0], list): min_val = [min_listed] * len(param['value'][0]) else: min_val = min_listed # create reform dictionaries max_reform = copy.deepcopy(reform_xx) min_reform = copy.deepcopy(reform_xx) max_reform[XX_YEAR][str(pname)] = [max_val] min_reform[XX_YEAR][str(pname)] = [min_val] # assess whether max reform changes results if puftest: rec_yy = Records(data=puf_subsample) else: rec_yy = Records.cps_constructor(data=cps_subsample) p_yy = Policy() p_yy.implement_reform(max_reform, raise_errors=False) c_yy = Calculator(policy=p_yy, records=rec_yy, verbose=False) c_yy.advance_to_year(TEST_YEAR) c_yy.calc_all() if pname.startswith('BEN') and pname.endswith('_repeal'): max_reform_change = ( c_yy.weighted_total('benefit_cost_total') - c_xx.weighted_total('benefit_cost_total') ) else: max_reform_change = ( c_yy.weighted_total('combined') - c_xx.weighted_total('combined') ) min_reform_change = 0 # assess whether min reform changes results, if max reform did not if max_reform_change == 0: p_yy = Policy() p_yy.implement_reform(min_reform, raise_errors=False) c_yy = Calculator(policy=p_yy, records=rec_xx) c_yy.advance_to_year(TEST_YEAR) c_yy.calc_all() if pname.startswith('BEN') and pname.endswith('_repeal'): min_reform_change = ( c_yy.weighted_total('benefit_cost_total') - c_xx.weighted_total('benefit_cost_total') ) else: min_reform_change = ( c_yy.weighted_total('combined') - c_xx.weighted_total('combined') ) if min_reform_change == 0 and pname not in exempt_from_testing: if puftest: if param['compatible_data']['puf'] is True: errors += errmsg.format(pname, 'is not True for puf') else: if param['compatible_data']['cps'] is True: errors += errmsg.format(pname, 'is not True for cps') if max_reform_change != 0 or min_reform_change != 0: if puftest: if param['compatible_data']['puf'] is False: errors += errmsg.format(pname, 'is not False for puf') else: if param['compatible_data']['cps'] is False: errors += errmsg.format(pname, 'is not False for cps') # test failure if any errors if errors: print(errors) assert 'compatible_data' == 'invalid'