def convert_adj(adj, start_year): pol = Policy() new_adj = defaultdict(dict) for param, valobjs in adj.items(): if param.endswith("checkbox"): param_name = param.split("_checkbox")[0] new_adj[f"{param_name}-indexed"][start_year] = valobjs[0]["value"] continue for valobj in valobjs: # has keys "year" and "value" if len(valobj) == 2: new_adj[param][valobj["year"]] = valobj["value"] # has keys "year", "value", and one of "MARS", "idedtype", or "EIC" elif len(valobj) == 3: other_label = next(k for k in valobj.keys() if k not in ("year", "value")) param_meta = pol._vals[f"_{param}"] if other_label != param_meta["vi_name"]: msg = (f"Label {other_label} does not match expected" f"label {param_meta['vi_name']}") raise ValueError(msg) ol_ix = param_meta["vi_vals"].index(valobj[other_label]) other_label_ix = ol_ix if valobj["year"] in new_adj[param]: defaultlist = new_adj[param][valobj["year"]] else: year_ix = valobj["year"] - min(param_meta["value_yrs"]) # shallow copy the list defaultlist = list(param_meta["value"][year_ix]) defaultlist[other_label_ix] = valobj["value"] new_adj[param][valobj["year"]] = defaultlist else: msg = (f"Dict should have 2 or 3 keys. It has {len(valobj)}" f"instead (key={list(valobj.keys())}).") raise ValueError(msg) return new_adj
def test_atr_graph_data(cps_subsample): pol = Policy() rec = Records.cps_constructor(data=cps_subsample) calc = Calculator(policy=pol, records=rec) year = calc.current_year with pytest.raises(ValueError): atr_graph_data(None, year, mars='bad') with pytest.raises(ValueError): atr_graph_data(None, year, mars=0) with pytest.raises(ValueError): atr_graph_data(None, year, mars=list()) with pytest.raises(ValueError): atr_graph_data(None, year, atr_measure='badtax') calc.calc_all() vdf = calc.dataframe(['s006', 'MARS', 'expanded_income']) tax = 0.20 * np.ones_like(vdf['expanded_income']) vdf['tax1'] = tax vdf['tax2'] = tax gdata = atr_graph_data(vdf, year, mars=1, atr_measure='combined') gdata = atr_graph_data(vdf, year, atr_measure='itax') gdata = atr_graph_data(vdf, year, atr_measure='ptax') assert isinstance(gdata, dict)
def test_expand_2D_accept_None_additional_row(): _II_brk2 = [[36000, 72250, 36500, 48600, 72500, 36250], [38000, 74000, 36900, 49400, 73800, 36900], [40000, 74900, 37450, 50200, 74900, 37450], [41000, None, None, None, None, None], [43000, None, None, None, None, None]] exp1 = 74900 * 1.02 exp2 = 37450 * 1.02 exp3 = 50200 * 1.02 exp4 = 74900 * 1.02 exp5 = 37450 * 1.02 exp6 = exp1 * 1.03 exp7 = exp2 * 1.03 exp8 = exp3 * 1.03 exp9 = exp4 * 1.03 exp10 = exp5 * 1.03 exp = [[36000, 72250, 36500, 48600, 72500, 36250], [38000, 74000, 36900, 49400, 73800, 36900], [40000, 74900, 37450, 50200, 74900, 37450], [41000, exp1, exp2, exp3, exp4, exp5], [43000, exp6, exp7, exp8, exp9, exp10]] inflation_rates = [0.015, 0.02, 0.02, 0.03] res = Policy.expand_array(_II_brk2, inflate=True, inflation_rates=inflation_rates, num_years=5) npt.assert_array_equal(res, exp) user_mods = {2016: {u'_II_brk2': _II_brk2}} pol = Policy(start_year=2013) pol.implement_reform(user_mods) pol.set_year(2020) irates = Policy.default_inflation_rates() # The 2020 policy should be the combination of the user-defined # value and CPI-inflated values from 2018 exp_2020 = [43000.] + [(1 + irates[2019]) * (1 + irates[2018]) * i for i in _II_brk2[2][1:]] exp_2020 = np.array(exp_2020) npt.assert_allclose(pol.II_brk2, exp_2020)
def test_create_parameters_from_file(policyfile): with open(policyfile.name) as pfile: policy = json.load(pfile) ppo = Policy(parameter_dict=policy) inf_rates = ppo.inflation_rates() assert_allclose(ppo._almdep, Policy._expand_array(np.array([7150, 7250, 7400], dtype=np.float64), False, inflate=True, inflation_rates=inf_rates, num_years=ppo.num_years), atol=0.01, rtol=0.0) assert_allclose(ppo._almsep, Policy._expand_array(np.array([40400, 41050], dtype=np.float64), False, inflate=True, inflation_rates=inf_rates, num_years=ppo.num_years), atol=0.01, rtol=0.0) assert_allclose(ppo._rt5, Policy._expand_array(np.array([0.33]), False, inflate=False, inflation_rates=inf_rates, num_years=ppo.num_years), atol=0.01, rtol=0.0) assert_allclose(ppo._rt7, Policy._expand_array(np.array([0.396]), False, inflate=False, inflation_rates=inf_rates, num_years=ppo.num_years), atol=0.01, rtol=0.0)
def test_update_behavior(): beh = Behavior(start_year=2013) beh.update_behavior({ 2014: { '_BE_sub': [0.5] }, 2015: { '_BE_CG_per': [1.2] } }) policy = Policy() should_be = np.full((Behavior.DEFAULT_NUM_YEARS, ), 0.5) should_be[0] = 0.0 assert np.allclose(beh._BE_sub, should_be, rtol=0.0) assert np.allclose(beh._BE_inc, np.zeros((Behavior.DEFAULT_NUM_YEARS, )), rtol=0.0) beh.set_year(2015) assert beh.current_year == 2015 assert beh.BE_sub == 0.5 assert beh.BE_inc == 0.0 assert beh.BE_CG_per == 1.2
def test_make_Calculator_with_multiyear_reform(): # create a Policy object and apply a policy reform policy3 = Policy() reform3 = {2015: {}} reform3[2015]['_STD_Aged'] = [[1600, 1300, 1600, 1300, 1600, 1300]] reform3[2015]['_II_em'] = [5000, 6000] # reform values for 2015 and 2016 reform3[2015]['_II_em_cpi'] = False policy3.implement_reform(reform3) # create a Calculator object using this policy-reform puf = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009) calc3 = Calculator(policy=policy3, records=puf) # check that Policy object embedded in Calculator object is correct assert calc3.current_year == 2013 assert calc3.policy.II_em == 3900 assert calc3.policy.num_years == Policy.DEFAULT_NUM_YEARS exp_II_em = [3900, 3950, 5000] + [6000] * (Policy.DEFAULT_NUM_YEARS - 3) assert_array_equal(calc3.policy._II_em, np.array(exp_II_em)) calc3.increment_year() calc3.increment_year() assert calc3.current_year == 2015 assert_array_equal(calc3.policy.STD_Aged, np.array([1600, 1300, 1600, 1300, 1600, 1300]))
def test_reform_json(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. """ reforms_path = os.path.join(tests_path, '..', 'reforms', '*.json') for jpf in glob.glob(reforms_path): # read contents of jpf (JSON parameter filename) jfile = open(jpf, 'r') jpf_text = jfile.read() # check that jpf_text has "policy" that can be implemented as a reform if '"policy"' in jpf_text: gdiffbase = {} gdiffresp = {} # pylint: disable=protected-access policy_dict = (Calculator._read_json_policy_reform_text( jpf_text, gdiffbase, gdiffresp)) policy = Policy() policy.implement_reform(policy_dict) else: # jpf_text is not a valid JSON policy reform file print('test-failing-filename: ' + jpf) assert False
def test_diff_table_sum_row(cps_subsample): rec = Records.cps_constructor(data=cps_subsample) # create a current-law Policy object and Calculator calc1 pol = Policy() calc1 = Calculator(policy=pol, records=rec) calc1.calc_all() # create a policy-reform Policy object and Calculator calc2 reform = {2013: {'_II_rt4': [0.56]}} pol.implement_reform(reform) calc2 = Calculator(policy=pol, records=rec) calc2.calc_all() # create two difference tables and compare their content tdiff1 = create_difference_table(calc1.dataframe(DIFF_VARIABLES), calc2.dataframe(DIFF_VARIABLES), 'standard_income_bins', 'iitax') tdiff2 = create_difference_table(calc1.dataframe(DIFF_VARIABLES), calc2.dataframe(DIFF_VARIABLES), 'soi_agi_bins', 'iitax') non_digit_cols = ['perc_inc', 'perc_cut'] digit_cols = [c for c in list(tdiff1) if c not in non_digit_cols] assert np.allclose(tdiff1[digit_cols][-1:], tdiff2[digit_cols][-1:]) np.allclose(tdiff1[non_digit_cols][-1:], tdiff2[non_digit_cols][-1:])
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, '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_qbid_calculation(): """ Test Calculator's QBID calculations using the six example filing units specified in Table 1 of this TPC publication: "Navigating the New Pass-Through Provisions: A Technical Explanation" by William G. Gale and Aaron Krupkin (January 31, 2018), which is available at this URL: https://www.taxpolicycenter.org/publications/ navigating-new-pass-through-provisions-technical-explanation/full """ # In constructing the TPC example filing units, assume that the taxpayer # has business income in the form of e26270/e02000 income and no earnings, # and that the spouse has no business income and only earnings. TPC_YEAR = 2018 TPC_VARS = ( 'RECID,MARS,e00200s,e00200,e26270,e02000,PT_SSTB_income,' 'PT_binc_w2_wages,PT_ubia_property,pre_qbid_taxinc,qbid\n' ) TPC_FUNITS = ( '1,2, 99000, 99000,75000,75000,1,20000,90000,150000,15000.00\n' '2,2,349000,349000,75000,75000,1,20000,90000,400000, 1612.50\n' '3,2,524000,524000,75000,75000,1,20000,90000,575000, 0.00\n' '4,2, 99000, 99000,75000,75000,0,20000,90000,150000,15000.00\n' '5,2,349000,349000,75000,75000,0,20000,90000,400000,10750.00\n' '6,2,524000,524000,75000,75000,0,20000,90000,575000,10000.00\n' ) # generate actual Calculator pre-qbid taxinc and qbid amounts tpc_df = pd.read_csv(StringIO(TPC_VARS + TPC_FUNITS)) recs = Records(data=tpc_df, start_year=TPC_YEAR, gfactors=None, weights=None) calc = Calculator(policy=Policy(), records=recs) assert calc.current_year == TPC_YEAR calc.calc_all() varlist = ['RECID', 'c00100', 'standard', 'c04470', 'qbided'] tc_df = calc.dataframe(varlist) # compare actual amounts with expected amounts from TPC publication act_taxinc = tc_df.c00100 - np.maximum(tc_df.standard, tc_df.c04470) exp_taxinc = tpc_df.pre_qbid_taxinc assert np.allclose(act_taxinc, exp_taxinc) assert np.allclose(tc_df.qbided, tpc_df.qbid)
def main(): parser = argparse.ArgumentParser( prog="python stats_summary.py", description=('Generates a files for either statistics summary' 'on a 10-year span or correlation matrix of current' 'tax year. Adding either sum-stats or correlation' 'as an argument after python Stats_Summary.py --output')) parser.add_argument('--output', default='sum-stats') args = parser.parse_args() # create a calculator tax_dta1 = pd.read_csv(PUF_PATH) records1 = Records(tax_dta1) policy1 = Policy(start_year=2013) calc1 = Calculator(records=records1, policy=policy1) table = creat_table_base() if args.output == 'sum-stats': gen_sum_stats(table, calc=calc1) elif args.output == 'correlation': gen_correlation(table, calc=calc1) else: print("no such output available") return 0
def test_read_json_reform_file_and_implement_reform(reform_file, assump_file, set_year): """ Test reading and translation of reform file into a reform dictionary that is then used to call implement_reform method and Calculate.calc_all() NOTE: implement_reform called when policy.current_year == policy.start_year """ pol = Policy() if set_year: pol.set_year(2015) param_dict = Calculator.read_json_param_objects(reform_file.name, assump_file.name) pol.implement_reform(param_dict['policy']) syr = pol.start_year amt_brk1 = pol._AMT_brk1 assert amt_brk1[2015 - syr] == 200000 assert amt_brk1[2016 - syr] > 200000 assert amt_brk1[2017 - syr] == 300000 assert amt_brk1[2018 - syr] > 300000 ii_em = pol._II_em assert ii_em[2016 - syr] == 6000 assert ii_em[2017 - syr] == 6000 assert ii_em[2018 - syr] == 7500 assert ii_em[2019 - syr] > 7500 assert ii_em[2020 - syr] == 9000 assert ii_em[2021 - syr] > 9000 amt_em = pol._AMT_em assert amt_em[2016 - syr, 0] > amt_em[2015 - syr, 0] assert amt_em[2017 - syr, 0] > amt_em[2016 - syr, 0] assert amt_em[2018 - syr, 0] == amt_em[2017 - syr, 0] assert amt_em[2019 - syr, 0] == amt_em[2017 - syr, 0] assert amt_em[2020 - syr, 0] == amt_em[2017 - syr, 0] assert amt_em[2021 - syr, 0] > amt_em[2020 - syr, 0] assert amt_em[2022 - syr, 0] > amt_em[2021 - syr, 0] add4aged = pol._ID_Medical_frt_add4aged assert add4aged[2015 - syr] == -0.025 assert add4aged[2016 - syr] == -0.025 assert add4aged[2017 - syr] == 0.0 assert add4aged[2022 - syr] == 0.0
def test_Calculator_create_distribution_table(records_2009): policy = Policy() calc = Calculator(policy=policy, records=records_2009) calc.calc_all() dist_labels = [ 'Returns', 'AGI', 'Standard Deduction Filers', 'Standard Deduction', 'Itemizers', 'Itemized Deduction', 'Personal Exemption', 'Taxable Income', 'Regular Tax', 'AMTI', 'AMT Filers', 'AMT', 'Tax before Credits', 'Non-refundable Credits', 'Tax before Refundable Credits', 'Refundable Credits', 'Individual Income Tax Liabilities', 'Payroll Tax Liablities', 'Combined Payroll and Individual Income Tax Liabilities' ] dt1 = create_distribution_table(calc.records, groupby="weighted_deciles", result_type="weighted_sum") dt1.columns = dist_labels dt2 = create_distribution_table(calc.records, groupby="small_income_bins", result_type="weighted_avg") assert isinstance(dt1, pd.DataFrame) assert isinstance(dt2, pd.DataFrame)
def test_distribution_tables(cps_subsample): pol = Policy() recs = Records.cps_constructor(data=cps_subsample) calc1 = Calculator(policy=pol, records=recs) assert calc1.current_year == 2014 calc1.calc_all() dt1, dt2 = calc1.distribution_tables(None) assert isinstance(dt1, pd.DataFrame) assert dt2 is None dt1, dt2 = calc1.distribution_tables(calc1) assert isinstance(dt1, pd.DataFrame) assert isinstance(dt2, pd.DataFrame) reform = {2014: {'_UBI_u18': [1000], '_UBI_1820': [1000], '_UBI_21': [1000]}} pol.implement_reform(reform) assert not pol.parameter_errors calc2 = Calculator(policy=pol, records=recs) calc2.calc_all() dt1, dt2 = calc1.distribution_tables(calc2) assert isinstance(dt1, pd.DataFrame) assert isinstance(dt2, pd.DataFrame)
def test_make_calculator_with_policy_reform(cps_subsample): rec = Records.cps_constructor(data=cps_subsample) year = rec.current_year # create a Policy object and apply a policy reform pol = Policy() reform = {2013: {'_II_em': [4000], '_II_em_cpi': False, '_STD_Aged': [[1600, 1300, 1300, 1600, 1600]], '_STD_Aged_cpi': False}} pol.implement_reform(reform) # create a Calculator object using this policy reform calc = Calculator(policy=pol, records=rec) # check that Policy object embedded in Calculator object is correct assert calc.current_year == year assert calc.policy_param('II_em') == 4000 assert np.allclose(calc.policy_param('_II_em'), np.array([4000] * Policy.DEFAULT_NUM_YEARS)) exp_STD_Aged = [[1600, 1300, 1300, 1600, 1600]] * Policy.DEFAULT_NUM_YEARS assert np.allclose(calc.policy_param('_STD_Aged'), np.array(exp_STD_Aged)) assert np.allclose(calc.policy_param('STD_Aged'), np.array([1600, 1300, 1300, 1600, 1600]))
def test_validate_param_names_types_errors(): """ Check detection of invalid policy parameter names and types in reforms. """ pol0 = Policy() ref0 = {2020: {'_STD_cpi': 2}} with pytest.raises(ValueError): pol0.implement_reform(ref0) pol1 = Policy() ref1 = {2020: {'_badname_cpi': True}} with pytest.raises(ValueError): pol1.implement_reform(ref1) pol2 = Policy() ref2 = {2020: {'_II_em_cpi': 5}} with pytest.raises(ValueError): pol2.implement_reform(ref2) pol3 = Policy() ref3 = {2020: {'_badname': [0.4]}} with pytest.raises(ValueError): pol3.implement_reform(ref3) pol4 = Policy() ref4 = {2020: {'_EITC_MinEligAge': [21.4]}} with pytest.raises(ValueError): pol4.implement_reform(ref4) pol5 = Policy() ref5 = {2025: {'_ID_BenefitSurtax_Switch': [[False, True, 0, 2, 0, 1, 0]]}} with pytest.raises(ValueError): pol5.implement_reform(ref5) pol6 = Policy() ref6 = {2021: {'_II_em': ['not-a-number']}} with pytest.raises(ValueError): pol6.implement_reform(ref6) pol7 = Policy() ref7 = {2019: {'_FICA_ss_trt_cpi': True}} with pytest.raises(ValueError): pol7.implement_reform(ref7)
def test_convert_4_budget_years(self): values = { "II_brk2_0": [36000., 38000., 40000., 41000], "II_brk2_1": [72250., 74000.], "II_brk2_2": [36500.] } ans = package_up_vars(values, first_budget_year=FBY) pp = Policy(start_year=2013) pp.set_year(FBY) # irates are rates for 2015, 2016, and 2017 irates = pp.indexing_rates_for_update(param_name='II_brk2', calyear=FBY, num_years_to_expand=4) # User choices propagate through to all future years # The user has specified part of the parameter up to 2017. # So, we choose to fill in the propagated value, which is # either inflated or not. f2_2016 = int(36500 * (1.0 + irates[0])) f3_2016 = int(50200 * (1.0 + irates[0])) f4_2016 = int(74900 * (1.0 + irates[0])) f5_2016 = int(37450 * (1.0 + irates[0])) f1_2017 = int(74000 * (1.0 + irates[1])) f2_2017 = int(f2_2016 * (1.0 + irates[1])) f1_2018 = int(f1_2017 * (1.0 + irates[2])) f2_2018 = int(f2_2017 * (1.0 + irates[2])) exp = [[36000, 72250, 36500, 50200, 74900, 37450], [38000, 74000, f2_2016, 50400, 75300, 37650], [40000, 75687, f2_2017, 50800.0, 75900.0, 37950.0], [41000, f1_2018, f2_2018, None, None, None]] assert ans['_II_brk2'] == exp
def get_inputs(meta_params_dict): """ Return default parameters from Tax-Cruncher """ metaparams = MetaParameters() metaparams.adjust(meta_params_dict) params = CruncherParams() policy_params = Policy() policy_params.set_state(year=metaparams.year.tolist()) policy_params.array_first = False # Hack to work smoothly with convert_policy_defaults since # it expects a data_source attribute. metaparams.data_source = "CPS" filtered_pol_params = inputs.convert_policy_defaults( metaparams, policy_params) keep = [ "mstat", "page", "sage", "dep13", "dep17", "dep18", "otherdep", "pwages", "swages", "dividends", "intrec", "stcg", "ltcg", "otherprop", "nonprop", "pensions", "gssi", "ui", "proptax", "otheritem", "childcare", "mortgage", "businc", "sstb", "w2paid", "qualprop", "mtr_options", "schema" ] cruncher_dict = params.dump() default_params = { "Tax Information": {k: v for k, v in cruncher_dict.items() if k in keep}, "Policy": filtered_pol_params } meta = metaparams.dump() return {"meta_parameters": meta, "model_parameters": default_params}
def test_agg(): """ Test Tax-Calculator aggregate taxes with no policy reform using puf.csv """ # create a Policy object (clp) containing current-law policy parameters clp = Policy() # create a Records object (puf) containing puf.csv input records puf = Records(data=PUFCSV_PATH) # create a Calculator object using clp policy and puf records calc = Calculator(policy=clp, records=puf) # create aggregate diagnostic table (adt) as a Pandas DataFrame object adt = calc.diagnostic_table(num_years=10) # convert adt results to a string with a trailing EOL character adtstr = adt.to_string() + '\n' # generate differences between actual and expected results actual = adtstr.splitlines(True) with open(AGGRES_PATH, 'r') as expected_file: txt = expected_file.read() expected_results = txt.rstrip('\n\t ') + '\n' # cleanup end of file txt expected = expected_results.splitlines(True) diff = difflib.unified_diff(expected, actual, fromfile='expected', tofile='actual', n=0) # convert diff generator into a list of lines: diff_lines = list() for line in diff: diff_lines.append(line) # test failure if there are any diff_lines if len(diff_lines) > 0: new_filename = '{}{}'.format(AGGRES_PATH[:-10], 'actual.txt') with open(new_filename, 'w') as new_file: new_file.write(adtstr) sys.stdout.write('*************************************************\n') sys.stdout.write('*** NEW RESULTS IN pufcsv_agg_actual.txt FILE ***\n') sys.stdout.write('*** if new OK, copy pufcsv_agg_actual.txt to ***\n') sys.stdout.write('*** pufcsv_agg_expect.txt ***\n') sys.stdout.write('*** and rerun test. ***\n') sys.stdout.write('*************************************************\n') assert False
def test_variable_inflation_rate_without_reform(): syr = 2013 irates = { 2013: 0.04, 2014: 0.04, 2015: 0.04, 2016: 0.04, 2017: 0.04, 2018: 0.04, 2019: 0.04, 2020: 0.04, 2021: 0.08, 2022: 0.08 } ppo = Policy(start_year=syr, num_years=10, inflation_rates=irates) assert ppo._II_em[2013 - syr] == 3900 # no reform # check implied inflation rate between 2020 and 2021 grate = float(ppo._II_em[2021 - syr]) / float(ppo._II_em[2020 - syr]) - 1.0 assert round(grate, 3) == round(0.04, 3) # check implied inflation rate between 2021 and 2022 grate = float(ppo._II_em[2022 - syr]) / float(ppo._II_em[2021 - syr]) - 1.0 assert round(grate, 3) == round(0.08, 3)
def test_variable_inflation_rate_with_reform(): syr = 2013 pol = Policy(start_year=syr, num_years=10) assert pol._II_em[2013 - syr] == 3900 # implement reform in 2020 which is two years before the last year, 2022 reform = {2020: {'_II_em': [20000]}} pol.implement_reform(reform) pol.set_year(2020) assert pol.current_year == 2020 # extract price inflation rates pirates = pol.inflation_rates() irate2018 = pirates[2018 - syr] irate2020 = pirates[2020 - syr] irate2021 = pirates[2021 - syr] # check implied inflation rate between 2018 and 2019 (before the reform) grate = float(pol._II_em[2019 - syr]) / float(pol._II_em[2018 - syr]) assert round(grate - 1.0, 5) == round(irate2018, 5) # check implied inflation rate between 2020 and 2021 (after the reform) grate = float(pol._II_em[2021 - syr]) / float(pol._II_em[2020 - syr]) assert round(grate - 1.0, 5) == round(irate2020, 5) # check implied inflation rate between 2021 and 2022 (after the reform) grate = float(pol._II_em[2022 - syr]) / float(pol._II_em[2021 - syr]) assert round(grate - 1.0, 5) == round(irate2021, 5)
def test_make_calculator_with_multiyear_reform(cps_subsample): rec = Records.cps_constructor(data=cps_subsample) year = rec.current_year # create a Policy object and apply a policy reform pol = Policy() reform = {2015: {}, 2016: {}} reform[2015]['_II_em'] = [5000, 6000] # reform values for 2015 and 2016 reform[2015]['_II_em_cpi'] = False reform[2016]['_STD_Aged'] = [[1600, 1300, 1600, 1300, 1600]] pol.implement_reform(reform) # create a Calculator object using this policy-reform calc = Calculator(policy=pol, records=rec) # check that Policy object embedded in Calculator object is correct assert calc.current_year == year assert calc.policy.II_em == 3950 assert calc.policy.num_years == Policy.DEFAULT_NUM_YEARS exp_II_em = [3900, 3950, 5000] + [6000] * (Policy.DEFAULT_NUM_YEARS - 3) assert np.allclose(calc.policy._II_em, np.array(exp_II_em)) calc.increment_year() calc.increment_year() assert calc.current_year == 2016 assert np.allclose(calc.policy.STD_Aged, np.array([1600, 1300, 1600, 1300, 1600]))
def test_make_calculator(cps_subsample): syr = 2014 pol = Policy(start_year=syr, num_years=9) assert pol.current_year == syr rec = Records.cps_constructor(data=cps_subsample) consump = Consumption() consump.update_consumption({syr: {'_MPC_e20400': [0.05]}}) assert consump.current_year == Consumption.JSON_START_YEAR calc = Calculator(policy=pol, records=rec, consumption=consump, behavior=Behavior()) assert calc.current_year == syr assert calc.records_current_year() == syr # test incorrect Calculator instantiation: with pytest.raises(ValueError): Calculator(policy=None, records=rec) with pytest.raises(ValueError): Calculator(policy=pol, records=None) with pytest.raises(ValueError): Calculator(policy=pol, records=rec, behavior=list()) with pytest.raises(ValueError): Calculator(policy=pol, records=rec, consumption=list())
def test_myr_diag_table_w_behv(records_2009): pol = Policy() behv = Behavior() calc = Calculator(policy=pol, records=records_2009, behavior=behv) assert calc.current_year == 2013 reform = { 2013: { '_II_rt7': [0.33], '_PT_rt7': [0.33], } } pol.implement_reform(reform) reform_be = {2013: {'_BE_sub': [0.4], '_BE_cg': [-3.67]}} behv.update_behavior(reform_be) calc_clp = calc.current_law_version() calc_behv = Behavior.response(calc_clp, calc) calc_behv.calc_all() liabilities_x = (calc_behv.records.combined * calc_behv.records.s006).sum() adt = multiyear_diagnostic_table(calc_behv, 1) # extract combined liabilities as a float and # adopt units of the raw calculator data in liabilities_x liabilities_y = adt.iloc[19].tolist()[0] * 1000000000 assert_almost_equal(liabilities_x, liabilities_y, 2)
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 test_reforms(reforms_path): # pylint: disable=redefined-outer-name """ Check that each JSON reform file can be converted into a reform dictionary, which can then be passed to the Policy.implement_reform() method. While doing this, construct a set of Policy parameters (other than those ending in '_cpi') included in the JSON reform files. """ params_set = set() for jrf in glob.glob(reforms_path): # read contents of jrf (JSON reform filename) with open(jrf) as jrfile: jrf_text = jrfile.read() # check that jrf_text can be implemented as a Policy reform jrf_dict = Policy.read_json_reform_text(jrf_text) policy = Policy() policy.implement_reform(jrf_dict) # identify policy parameters included in jrf after removing //-comments json_without_comments = re.sub('//.*', ' ', jrf_text) json_dict = json.loads(json_without_comments) for param in json_dict.keys(): if param.endswith('_cpi'): continue params_set.add(param)
def test_make_Calculator_with_policy_reform(records_2009): # create a Policy object and apply a policy reform policy2 = Policy() reform2 = { 2013: { '_II_em': np.array([4000]), '_II_em_cpi': False, '_STD_Aged': [[1600, 1300, 1300, 1600, 1600]], "_STD_Aged_cpi": False } } policy2.implement_reform(reform2) # create a Calculator object using this policy-reform calc2 = Calculator(policy=policy2, records=records_2009) # check that Policy object embedded in Calculator object is correct assert calc2.current_year == 2013 assert calc2.policy.II_em == 4000 assert np.allclose(calc2.policy._II_em, np.array([4000] * Policy.DEFAULT_NUM_YEARS)) exp_STD_Aged = [[1600, 1300, 1300, 1600, 1600]] * Policy.DEFAULT_NUM_YEARS assert np.allclose(calc2.policy._STD_Aged, np.array(exp_STD_Aged)) assert np.allclose(calc2.policy.STD_Aged, np.array([1600, 1300, 1300, 1600, 1600]))
def test_Calculator_mtr(records_2009): calc = Calculator(policy=Policy(), records=records_2009) recs_pre_e00200p = copy.deepcopy(calc.records.e00200p) (mtr_ptx, mtr_itx, mtr_combined) = calc.mtr(variable_str='e00200p', zero_out_calculated_vars=True) recs_post_e00200p = copy.deepcopy(calc.records.e00200p) assert np.allclose(recs_post_e00200p, recs_pre_e00200p) assert type(mtr_combined) == np.ndarray assert np.array_equal(mtr_combined, mtr_ptx) is False assert np.array_equal(mtr_ptx, mtr_itx) is False with pytest.raises(ValueError): (_, _, mtr_combined) = calc.mtr(variable_str='bad_income_type') (_, _, mtr_combined) = calc.mtr(variable_str='e00200s') assert type(mtr_combined) == np.ndarray (_, _, mtr_combined) = calc.mtr(variable_str='e00650', negative_finite_diff=True) assert type(mtr_combined) == np.ndarray (_, _, mtr_combined) = calc.mtr(variable_str='e00900p') assert type(mtr_combined) == np.ndarray (_, _, mtr_combined) = calc.mtr(variable_str='e01700') assert type(mtr_combined) == np.ndarray (_, _, mtr_combined) = calc.mtr(variable_str='e26270') assert type(mtr_combined) == np.ndarray
def test_make_calculator(cps_subsample): """ Test Calculator class ctor. """ start_year = Policy.JSON_START_YEAR sim_year = 2018 pol = Policy() assert pol.current_year == start_year rec = Records.cps_constructor(data=cps_subsample) consump = Consumption() consump.update_consumption({'MPC_e20400': {sim_year: 0.05}}) assert consump.current_year == start_year calc = Calculator(policy=pol, records=rec, consumption=consump, verbose=True) assert calc.data_year == Records.CPSCSV_YEAR assert calc.current_year == Records.CPSCSV_YEAR # test incorrect Calculator instantiation: with pytest.raises(ValueError): Calculator(policy=None, records=rec) with pytest.raises(ValueError): Calculator(policy=pol, records=None) with pytest.raises(ValueError): Calculator(policy=pol, records=rec, consumption=list())
def test_read_json_reform_file_and_implement_reform(reform_file, set_year): """ Test reading and translation of reform file into a reform dictionary that is then used to call implement_reform method. NOTE: implement_reform called when policy.current_year == policy.start_year """ reform = Policy.read_json_reform_file(reform_file.name) policy = Policy() if set_year: policy.set_year(2015) policy.implement_reform(reform) syr = policy.start_year amt_tthd = policy._AMT_tthd assert amt_tthd[2015 - syr] == 200000 assert amt_tthd[2016 - syr] > 200000 assert amt_tthd[2017 - syr] == 300000 assert amt_tthd[2018 - syr] > 300000 ii_em = policy._II_em assert ii_em[2016 - syr] == 6000 assert ii_em[2017 - syr] == 6000 assert ii_em[2018 - syr] == 7500 assert ii_em[2019 - syr] > 7500 assert ii_em[2020 - syr] == 9000 assert ii_em[2021 - syr] > 9000 amt_em = policy._AMT_em assert amt_em[2016 - syr, 0] > amt_em[2015 - syr, 0] assert amt_em[2017 - syr, 0] > amt_em[2016 - syr, 0] assert amt_em[2018 - syr, 0] == amt_em[2017 - syr, 0] assert amt_em[2019 - syr, 0] == amt_em[2017 - syr, 0] assert amt_em[2020 - syr, 0] == amt_em[2017 - syr, 0] assert amt_em[2021 - syr, 0] > amt_em[2020 - syr, 0] assert amt_em[2022 - syr, 0] > amt_em[2021 - syr, 0] add4aged = policy._ID_Medical_frt_add4aged assert add4aged[2015 - syr] == -0.025 assert add4aged[2016 - syr] == -0.025 assert add4aged[2017 - syr] == 0.0 assert add4aged[2022 - syr] == 0.0