def test_Policy_reform_makes_no_changes_before_year(): ppo = Policy(start_year=2013) reform = {2015: {'_II_em': [4400], '_II_em_cpi': True}} ppo.implement_reform(reform) ppo.set_year(2015) assert_array_equal(ppo._II_em[:3], np.array([3900, 3950, 4400])) assert ppo.II_em == 4400
def test_convert(self): values = {"II_brk2_0": [36000., 38000., 40000.], "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=3) # 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])) exp = [[36000, 72250, 36500, 50200, 74900, 37450], [38000, 74000, f2_2016, 50400, 75300, 37650], [40000, f1_2017, f2_2017, None, None, None]] assert ans['_II_brk2'] == exp assert len(ans) == 1
def test_read_json_reform_file_and_implement_reform_b(reform_file): """ 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() policy.set_year(2015) # the only difference between this and prior test 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]
def test_variable_inflation_rate_with_reform(): syr = 2013 pol = Policy(start_year=syr) assert pol._II_em[2013 - syr] == 3900 # implement reform in 2020 which is two years before the last year, 2022 reform = { 2018: { '_II_em': [1000] }, # to avoid divide-by-zero under TCJA 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_Policy_reform_after_start_year(): ppo = Policy(start_year=2013) reform = {2015: {'_STD_Aged': [[1400, 1100, 1100, 1400, 1400, 1199]]}} ppo.implement_reform(reform) ppo.set_year(2015) assert_array_equal(ppo.STD_Aged, np.array([1400, 1100, 1100, 1400, 1400, 1199]))
def test_calculator_using_nonstd_input(rawinputfile): """ Test Calculator using non-standard input records. """ # check Calculator handling of raw, non-standard input data with no aging pol = Policy() pol.set_year(RAWINPUTFILE_YEAR) # set policy params to input data year nonstd = Records(data=rawinputfile.name, gfactors=None, # keeps raw data unchanged weights=None, start_year=RAWINPUTFILE_YEAR) # set raw input data year assert nonstd.array_length == RAWINPUTFILE_FUNITS calc = Calculator(policy=pol, records=nonstd, sync_years=False) # keeps raw data unchanged assert calc.current_year == RAWINPUTFILE_YEAR calc.calc_all() assert calc.weighted_total('e00200') == 0 assert calc.total_weight() == 0 varlist = ['RECID', 'MARS'] dframe = calc.dataframe(varlist) assert isinstance(dframe, pd.DataFrame) assert dframe.shape == (RAWINPUTFILE_FUNITS, len(varlist)) mars = calc.array('MARS') assert isinstance(mars, np.ndarray) assert mars.shape == (RAWINPUTFILE_FUNITS,) exp_iitax = np.zeros((nonstd.array_length,)) assert np.allclose(calc.array('iitax'), exp_iitax) mtr_ptax, _, _ = calc.mtr(wrt_full_compensation=False) exp_mtr_ptax = np.zeros((nonstd.array_length,)) exp_mtr_ptax.fill(0.153) assert np.allclose(mtr_ptax, exp_mtr_ptax)
def test_convert(self): values = {"II_brk2_0": [36000., 38000., 40000.], "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=3) # 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])) exp = [[36000, 72250, 36500, 50200, 74900], [38000, 74000, f2_2016, 50400.0, 75300.0], [40000, f1_2017, f2_2017, 50800.0, 75900.0]] assert ans['_II_brk2'] == exp assert len(ans) == 1
def test_round_trip_tcja_reform(tests_path): """ Check that current-law policy has the same policy parameter values in a future year as does a compound reform that first implements the reform specified in the 2017_law.json file and then implements the reform specified in the TCJA.json file. This test checks that the future-year parameter values for current-law policy (which incorporates TCJA) are the same as future-year parameter values for the compound round-trip reform. Doing this check ensures that the 2017_law.json and TCJA.json reform files are specified in a consistent manner. """ # pylint: disable=too-many-locals fyear = 2020 # create clp metadata dictionary for current-law policy in fyear pol = Policy() pol.set_year(fyear) clp_mdata = pol.metadata() # create rtr metadata dictionary for round-trip reform in fyear pol = Policy() reform_file = os.path.join(tests_path, '..', 'reforms', '2017_law.json') with open(reform_file, 'r') as rfile: rtext = rfile.read() pol.implement_reform(Policy.read_json_reform(rtext)) # eventually activate: assert not clp.parameter_warnings ctc_c_warning = 'CTC_c was redefined in release 1.0.0\n' assert pol.parameter_warnings == ctc_c_warning assert not pol.parameter_errors reform_file = os.path.join(tests_path, '..', 'reforms', 'TCJA.json') with open(reform_file, 'r') as rfile: rtext = rfile.read() pol.implement_reform(Policy.read_json_reform(rtext)) # eventually activate: assert not clp.parameter_warnings assert pol.parameter_warnings == ctc_c_warning assert not pol.parameter_errors pol.set_year(fyear) rtr_mdata = pol.metadata() # compare fyear policy parameter values assert clp_mdata.keys() == rtr_mdata.keys() fail_dump = False if fail_dump: rtr_fails = open('fails_rtr', 'w') clp_fails = open('fails_clp', 'w') fail_params = list() msg = '\nRound-trip-reform and current-law-policy param values differ for:' for pname in clp_mdata.keys(): rtr_val = rtr_mdata[pname]['value'] clp_val = clp_mdata[pname]['value'] if not np.allclose(rtr_val, clp_val): fail_params.append(pname) msg += '\n {} in {} : rtr={} clp={}'.format( pname, fyear, rtr_val, clp_val ) if fail_dump: rtr_fails.write('{} {} {}\n'.format(pname, fyear, rtr_val)) clp_fails.write('{} {} {}\n'.format(pname, fyear, clp_val)) if fail_dump: rtr_fails.close() clp_fails.close() if fail_params: raise ValueError(msg)
def test_calculator_using_nonstd_input(rawinputfile): # check Calculator handling of raw, non-standard input data with no aging pol = Policy() pol.set_year(RAWINPUTFILE_YEAR) # set policy params to input data year nonstd = Records( data=rawinputfile.name, gfactors=None, # keeps raw data unchanged weights=None, start_year=RAWINPUTFILE_YEAR) # set raw input data year assert nonstd.dim == RAWINPUTFILE_FUNITS calc = Calculator(policy=pol, records=nonstd, sync_years=False) # keeps raw data unchanged assert calc.current_year == RAWINPUTFILE_YEAR calc.calc_all() assert calc.weighted_total('e00200') == 0 assert calc.total_weight() == 0 varlist = ['RECID', 'MARS'] pdf = calc.dataframe(varlist) assert isinstance(pdf, pd.DataFrame) assert pdf.shape == (RAWINPUTFILE_FUNITS, len(varlist)) mars = calc.array('MARS') assert isinstance(mars, np.ndarray) assert mars.shape == (RAWINPUTFILE_FUNITS, ) exp_iitax = np.zeros((nonstd.dim, )) assert np.allclose(calc.records.iitax, exp_iitax) mtr_ptax, _, _ = calc.mtr(wrt_full_compensation=False) exp_mtr_ptax = np.zeros((nonstd.dim, )) exp_mtr_ptax.fill(0.153) assert np.allclose(mtr_ptax, exp_mtr_ptax)
def test_variable_inflation_rate_with_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 # implement reform in 2020 which is two years before the last year, 2022 reform = {2020: {'_II_em': [20000]}} ppo.implement_reform(reform) ppo.set_year(2020) assert ppo.current_year == 2020 # check implied inflation rate between 2018 and 2019 (before the reform) grate = float(ppo._II_em[2019 - syr]) / float(ppo._II_em[2018 - syr]) - 1.0 assert round(grate, 3) == round(0.04, 3) # check implied inflation rate between 2020 and 2021 (after the reform) 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 (after the reform) 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_expand_2D_accept_None(): _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]] exp1 = 74900 * 1.02 exp2 = 37450 * 1.02 exp3 = 50200 * 1.02 exp4 = 74900 * 1.02 exp5 = 37450 * 1.02 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]] exp = np.array(exp).astype('i4', casting='unsafe') res = Policy.expand_array(_II_brk2, inflate=True, inflation_rates=[0.02] * 5, num_years=4) 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(2019) irates = Policy.default_inflation_rates() # The 2019 policy should be the combination of the user-defined # value and CPI-inflated values from 2018 exp_2019 = [41000.] + [(1 + irates[2018]) * i for i in _II_brk2[2][1:]] exp_2019 = np.array(exp_2019) npt.assert_array_equal(pol.II_brk2, exp_2019)
def test_expand_2D_accept_None(): _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]] exp1 = 74900 * 1.02 exp2 = 37450 * 1.02 exp3 = 50200 * 1.02 exp4 = 74900 * 1.02 exp5 = 37450 * 1.02 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]] exp = np.array(exp).astype('i4', casting='unsafe') res = Policy.expand_array(_II_brk2, inflate=True, inflation_rates=[0.02] * 5, num_years=4) npt.assert_array_equal(res, exp) syr = 2013 pol = Policy(start_year=syr) irates = pol.inflation_rates() reform = {2016: {u'_II_brk2': _II_brk2}} pol.implement_reform(reform) pol.set_year(2019) # The 2019 policy should be the combination of the user-defined # value and CPI-inflated values from 2018 exp_2019 = [41000.] + [(1.0 + irates[2018 - syr]) * i for i in _II_brk2[2][1:]] exp_2019 = np.array(exp_2019) npt.assert_array_equal(pol.II_brk2, exp_2019)
def test_variable_inflation_rate_with_reform(): """ Test indexing of policy parameters involved in a reform. """ pol = Policy() syr = Policy.JSON_START_YEAR assert pol._II_em[2013 - syr] == 3900 # implement reform in 2020 which is two years before the last year, 2022 reform = { 'II_em': {2018: 1000, # to avoid divide-by-zero under TCJA 2020: 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_index_offset_reform(): """ Test a reform that includes both a change in CPI_offset and a change in a variable's indexed status in the same year. """ reform1 = {'CTC_c-indexed': {2020: True}} policy1 = Policy() policy1.implement_reform(reform1) offset = -0.005 reform2 = {'CTC_c-indexed': {2020: True}, 'CPI_offset': {2020: offset}} policy2 = Policy() policy2.implement_reform(reform2) # caused T-C crash before PR#2364 # extract from policy1 and policy2 the parameter values of CTC_c pvalue1 = dict() pvalue2 = dict() for cyr in [2019, 2020, 2021]: policy1.set_year(cyr) pvalue1[cyr] = policy1.CTC_c policy2.set_year(cyr) pvalue2[cyr] = policy2.CTC_c # check that pvalue1 and pvalue2 dictionaries contain the expected values assert pvalue2[2019] == pvalue1[2019] assert pvalue2[2020] == pvalue1[2020] assert pvalue2[2020] == pvalue2[2019] # ... indexing of CTC_c begins shows up first in 2021 parameter values assert pvalue1[2021] > pvalue1[2020] assert pvalue2[2021] > pvalue2[2020] # ... calculate expected pvalue2[2021] from offset and pvalue1 values indexrate1 = pvalue1[2021] / pvalue1[2020] - 1. expindexrate = indexrate1 + offset expvalue = round(pvalue2[2020] * (1. + expindexrate), 2) # ... compare expected value with actual value of pvalue2 for 2021 assert np.allclose([expvalue], [pvalue2[2021]])
def test_variable_inflation_rate_with_reform(): """ Test indexing of policy parameters involved in a reform. """ pol = Policy() syr = Policy.JSON_START_YEAR assert pol._II_em[2013 - syr] == 3900 # implement reform in 2020 which is two years before the last year, 2022 reform = { 'II_em': { 2018: 1000, # to avoid divide-by-zero under TCJA 2020: 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_calculator_using_nonstd_input(): """ Test Calculator using non-standard input records. """ # check Calculator handling of raw, non-standard input data with no aging pol = Policy() pol.set_year(RAWINPUT_YEAR) # set policy params to input data year nonstd = Records( data=pd.read_csv(StringIO(RAWINPUT_CONTENTS)), start_year=RAWINPUT_YEAR, # set raw input data year gfactors=None, # keeps raw data unchanged weights=None) assert nonstd.array_length == RAWINPUT_FUNITS calc = Calculator(policy=pol, records=nonstd, sync_years=False) # keeps raw data unchanged assert calc.current_year == RAWINPUT_YEAR calc.calc_all() assert calc.weighted_total('e00200') == 0 assert calc.total_weight() == 0 varlist = ['RECID', 'MARS'] dframe = calc.dataframe(varlist) assert isinstance(dframe, pd.DataFrame) assert dframe.shape == (RAWINPUT_FUNITS, len(varlist)) mars = calc.array('MARS') assert isinstance(mars, np.ndarray) assert mars.shape == (RAWINPUT_FUNITS, ) exp_iitax = np.zeros((nonstd.array_length, )) assert np.allclose(calc.array('iitax'), exp_iitax) mtr_ptax, _, _ = calc.mtr(wrt_full_compensation=False) exp_mtr_ptax = np.zeros((nonstd.array_length, )) exp_mtr_ptax.fill(0.153) assert np.allclose(mtr_ptax, exp_mtr_ptax)
def test_round_trip_tcja_reform(tests_path): """ Check that current-law policy has the same policy parameter values in a future year as does a compound reform that first implements the reform specified in the 2017_law.json file and then implements the reform specified in the TCJA.json file. This test checks that the future-year parameter values for current-law policy (which incorporates TCJA) are the same as future-year parameter values for the compound round-trip reform. Doing this check ensures that the 2017_law.json and TCJA.json reform files are specified in a consistent manner. """ # pylint: disable=too-many-locals fyear = 2020 # create clp metadata dictionary for current-law policy in fyear pol = Policy() pol.set_year(fyear) clp_mdata = pol.metadata() # create rtr metadata dictionary for round-trip reform in fyear pol = Policy() reform_file = os.path.join(tests_path, '..', 'reforms', '2017_law.json') with open(reform_file, 'r') as rfile: rtext = rfile.read() pol.implement_reform(Policy.read_json_reform(rtext)) # eventually activate: assert not clp.parameter_warnings ctc_c_warning = 'CTC_c was redefined in release 1.0.0\n' assert pol.parameter_warnings == ctc_c_warning assert not pol.parameter_errors reform_file = os.path.join(tests_path, '..', 'reforms', 'TCJA.json') with open(reform_file, 'r') as rfile: rtext = rfile.read() pol.implement_reform(Policy.read_json_reform(rtext)) # eventually activate: assert not clp.parameter_warnings assert pol.parameter_warnings == ctc_c_warning assert not pol.parameter_errors pol.set_year(fyear) rtr_mdata = pol.metadata() # compare fyear policy parameter values assert clp_mdata.keys() == rtr_mdata.keys() fail_dump = False if fail_dump: rtr_fails = open('fails_rtr', 'w') clp_fails = open('fails_clp', 'w') fail_params = list() msg = '\nRound-trip-reform and current-law-policy param values differ for:' for pname in clp_mdata.keys(): rtr_val = rtr_mdata[pname]['value'] clp_val = clp_mdata[pname]['value'] if not np.allclose(rtr_val, clp_val): fail_params.append(pname) msg += '\n {} in {} : rtr={} clp={}'.format( pname, fyear, rtr_val, clp_val) if fail_dump: rtr_fails.write('{} {} {}\n'.format(pname, fyear, rtr_val)) clp_fails.write('{} {} {}\n'.format(pname, fyear, clp_val)) if fail_dump: rtr_fails.close() clp_fails.close() if fail_params: raise ValueError(msg)
def test_2017_law_reform(tests_path): """ Check that policy parameter values in a future year under current-law policy and under the reform specified in the 2017_law.json file are sensible. """ # create pre metadata dictionary for 2017_law.json reform in fyear pol = Policy() reform_file = os.path.join(tests_path, '..', 'reforms', '2017_law.json') with open(reform_file, 'r') as rfile: rtext = rfile.read() reform = Calculator.read_json_param_objects(rtext, None) pol.implement_reform(reform['policy']) # eventually activate: assert not clp.parameter_warnings ctc_c_warning = 'CTC_c was redefined in release 1.0.0\n' assert pol.parameter_warnings == ctc_c_warning assert not pol.parameter_errors pol.set_year(2018) pre_mdata = pol.metadata() # check some policy parameter values against expected values under 2017 law pre_expect = { # relation '<' implies asserting that actual < expect # relation '>' implies asserting that actual > expect # ... parameters not affected by TCJA and that are not indexed 'AMEDT_ec': {'relation': '=', 'value': 200000}, 'SS_thd85': {'relation': '=', 'value': 34000}, # ... parameters not affected by TCJA and that are indexed 'STD_Dep': {'relation': '>', 'value': 1050}, 'CG_brk2': {'relation': '>', 'value': 425800}, 'AMT_CG_brk1': {'relation': '>', 'value': 38600}, 'AMT_brk1': {'relation': '>', 'value': 191100}, 'EITC_c': {'relation': '>', 'value': 519}, 'EITC_ps': {'relation': '>', 'value': 8490}, 'EITC_ps_MarriedJ': {'relation': '>', 'value': 5680}, 'EITC_InvestIncome_c': {'relation': '>', 'value': 3500}, # ... parameters affected by TCJA and that are not indexed 'ID_Charity_crt_all': {'relation': '=', 'value': 0.5}, 'II_rt3': {'relation': '=', 'value': 0.25}, # ... parameters affected by TCJA and that are indexed 'II_brk3': {'relation': '>', 'value': 91900}, 'STD': {'relation': '<', 'value': 7000}, 'II_em': {'relation': '>', 'value': 4050}, 'AMT_em_pe': {'relation': '<', 'value': 260000} } assert isinstance(pre_expect, dict) assert set(pre_expect.keys()).issubset(set(pre_mdata.keys())) for name in pre_expect: aval = pre_mdata[name]['value'] if isinstance(aval, list): act = aval[0] # comparing only first item in a vector parameter else: act = aval exp = pre_expect[name]['value'] if pre_expect[name]['relation'] == '<': assert act < exp, '{} a={} !< e={}'.format(name, act, exp) elif pre_expect[name]['relation'] == '>': assert act > exp, '{} a={} !> e={}'.format(name, act, exp) elif pre_expect[name]['relation'] == '=': assert act == exp, '{} a={} != e={}'.format(name, act, exp)
def convert_defaults(pcl): type_map = { "real": "float", "boolean": "bool", "integer": "int", "string": "str", } new_pcl = defaultdict(dict) new_pcl["schema"] = POLICY_SCHEMA LAST_YEAR = 2028 pol = Policy() pol.set_year(2028) for param, item in pcl.items(): values = [] pol_val = getattr(pol, f"_{param}").tolist() min_year = min(item["value_yrs"]) if isinstance(pol_val[0], list): for year in range(len(pol_val)): if min_year + year > LAST_YEAR: break for dim1 in range(len(pol_val[0])): values.append({ "year": min_year + year, item["vi_name"]: item["vi_vals"][dim1], "value": pol_val[year][dim1] }) else: for year in range(len(pol_val)): if min_year + year > LAST_YEAR: break values.append({ "year": min_year + year, "value": pol_val[year] }) new_pcl[param]['value'] = values new_pcl[param]['title'] = pcl[param]["long_name"] new_pcl[param]['type'] = type_map[pcl[param]["value_type"]] new_pcl[param]["validators"] = {"range": pcl[param]["valid_values"]} # checkbox if indexable if item["indexable"]: if item["indexed"]: new_pcl[param]["checkbox"] = True else: new_pcl[param]["checkbox"] = False to_keep = list(POLICY_SCHEMA["additional_members"].keys()) + [ "description", "notes", ] for k in to_keep: if k in pcl[param]: new_pcl[param][k] = pcl[param][k] return new_pcl
def test_Policy_reform_after_start_year(): ppo = Policy(start_year=2013) reform = {2015: {'_STD_Aged': [[1400, 1100, 1100, 1400, 1400]]}} ppo.implement_reform(reform) ppo.set_year(2015) assert_allclose(ppo.STD_Aged, np.array([1400, 1100, 1100, 1400, 1400]), atol=0.01, rtol=0.0)
def test_Policy_reform_with_default_cpi_flags(): ppo = Policy(start_year=2013) reform = {2015: {'_II_em': [4300]}} ppo.implement_reform(reform) # '_II_em' has a default cpi_flag of True, so # in 2016 its value should be greater than 4300 ppo.set_year(2016) assert ppo.II_em > 4300
def main(start_year, delay_years, scale_factor, no_indexing, each_separate): """ Highest-level logic of make_reforms.py script. """ # check validity of function arguments if start_year < FIRST_YEAR: msg = 'ERROR: --year {} sets year before {}\n' sys.stderr.write(msg.format(start_year, FIRST_YEAR)) return 1 if scale_factor < 1.0: msg = 'ERROR: --scale {} sets scale below one\n' sys.stderr.write(msg.format(scale_factor)) return 1 if each_separate: reform = PROVISIONS_EACH_SEPARATE else: reform = PROVISIONS_ALL_TOGETHER # get current-law-policy parameters for start_year in a Policy object clp = Policy() clp.set_year(start_year) # construct of set of Policy parameter names policy_param_names = set(getattr(clp, '_vals').keys()) # remove names of policy parameters not currently used by TaxBrain param_names = policy_param_names - PARAMS_NOT_USED_IN_TAXBRAIN # add *_cpi parameter names if no_indexing is true if no_indexing: param_names = param_names | indexed_parameter_names(clp, param_names) # remove "null" reform provisions if scale_factor == 1.0: excluded_names = set() for name in param_names: if not name.endswith('_cpi'): excluded_names.add(name) param_names = param_names - excluded_names # write a JSON entry for each parameter np.random.seed(seed=987654321) if reform == PROVISIONS_ALL_TOGETHER: write_all_together(param_names, clp, start_year, delay_years, scale_factor) elif reform == PROVISIONS_EACH_SEPARATE: write_each_separate(param_names, clp, start_year, delay_years, scale_factor) else: msg = 'ERROR: reform has illegal value {}\n' sys.stderr.write(msg.format(reform)) return 1 # return no-error exit code return 0
def get_defaults(start_year, **kwargs): pol = Policy() pol.set_year(start_year) pol_mdata = pol.metadata() # serialize taxcalc params seri = {} for param, data in pol_mdata.items(): seri[param] = dict(data, **{"value": np.array(data["value"]).tolist()}) return {"policy": seri, "behavior": BEHV_PARAMS}
def test_Policy_reform_makes_no_changes_before_year(): ppo = Policy() reform = {2015: {'_II_em': [4400], '_II_em_cpi': True}} ppo.implement_reform(reform) ppo.set_year(2015) assert np.allclose(ppo._II_em[:3], np.array([3900, 3950, 4400]), atol=0.01, rtol=0.0) assert ppo.II_em == 4400
def test_reform_makes_no_changes_before_year(): """ Test that implement_reform makes no changes before first reform year. """ ppo = Policy() reform = {'II_em': {2015: 4400}, 'II_em-indexed': {2015: True}} ppo.implement_reform(reform) ppo.set_year(2015) assert np.allclose(ppo._II_em[:3], np.array([3900, 3950, 4400]), atol=0.01, rtol=0.0) assert ppo.II_em == 4400
def test_correct_Policy_instantiation(): pol = Policy() assert pol pol.implement_reform({}) with pytest.raises(ValueError): pol.implement_reform(list()) with pytest.raises(ValueError): pol.implement_reform({2099: {'_II_em': [99000]}}) pol.set_year(2019) with pytest.raises(ValueError): pol.implement_reform({2018: {'_II_em': [99000]}})
def test_reform_with_default_indexed(): """ Test that implement_reform indexes after first reform year. """ ppo = Policy() reform = {'II_em': {2015: 4300}} ppo.implement_reform(reform) # II_em has a default indexing status of true, so # in 2016 its value should be greater than 4300 ppo.set_year(2016) assert ppo.II_em > 4300
def propagate_user_list(x, defaults, cpi, first_budget_year): """ Dispatch to either expand_1D or expand2D depending on the dimension of x Parameters: ----------- x : list from user to propagate forward in time. The first value is for year 'first_budget_year'. The value at index i is the value for budget year first_budget_year + i. defaults: list of default values; our result must be at least this long cpi: Bool first_budget_year: int Returns: -------- list of length 'num_years'. if 'cpi'==True, the values will be inflated based on the last value the user specified """ # x can't be empty assert x num_years = max(len(defaults), len(x)) is_rate = any([ i < 1.0 for i in x]) pp = Policy(start_year=2013) pp.set_year(first_budget_year) # irates are rates for 2015, 2016, and 2017 if cpi: irates = pp.indexing_rates_for_update(param_name='II_brk2', calyear=first_budget_year, num_years_to_expand=num_years) else: irates = [0.0] * num_years last_val = x[-1] ans = [None] * num_years for i in range(num_years): if i < len(x): if x[i] == '*': ans[i] = defaults[i] else: ans[i] = x[i] else: newval = ans[i-1] * (1.0 + irates[i-1]) ans[i] = newval if is_rate else int(newval) return ans
def test_convert_multiple_items(self): values = { "II_brk2_0": [36000., 38000., 40000., 41000], "II_brk2_1": [72250., 74000.], "II_brk2_2": [36500.] } values['II_em'] = [4000] ans = package_up_vars(values, first_budget_year=FBY) defaults = taxcalc.policy.Policy.default_data(start_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 # For scalar parameter values, we still have that all user # choices propagate up through whatever is specified as # a default. We know that _II_em is specified up to 2016, so # package up vars needs to overwrite those default and return # 2015 and 2016 values exp_em = [4000, int(4000 * (1 + irates[0])), 4165] assert ans['_II_em'] == exp_em assert len(ans) == 2
def test_correct_Policy_instantiation(): pol = Policy() assert pol wrates = Policy.default_wage_growth_rates() assert len(wrates) == Policy.DEFAULT_NUM_YEARS pol.implement_reform({}) with pytest.raises(ValueError): pol.implement_reform(list()) with pytest.raises(ValueError): pol.implement_reform({2099: {'_II_em': [99000]}}) pol.set_year(2019) with pytest.raises(ValueError): pol.implement_reform({2018: {'_II_em': [99000]}})
def test_calc_all(): """ Test calc_all method. """ cyr = 2016 pol = Policy() pol.set_year(cyr) nonstd = Records(data=pd.read_csv(StringIO(RAWINPUT_CONTENTS)), start_year=cyr, gfactors=None, weights=None) assert nonstd.array_length == RAWINPUT_FUNITS calc = Calculator(policy=pol, records=nonstd, sync_years=False) # keeps raw data unchanged assert calc.current_year == cyr
def test_correct_Policy_instantiation(): pol = Policy() assert pol pol.implement_reform({}) with pytest.raises(ValueError): pol.implement_reform(list()) with pytest.raises(ValueError): pol.implement_reform({2099: {'_rate2': [0.07]}}) pol.set_year(2018) with pytest.raises(ValueError): pol.implement_reform({2017: {'_rate2': [0.07]}}) with pytest.raises(ValueError): pol.implement_reform({2019: {'_rate2': [-0.10]}})
def test_calc_all(reform_file, rawinputfile): cyr = 2016 pol = Policy() param_dict = Calculator.read_json_param_objects(reform_file.name, None) pol.implement_reform(param_dict['policy']) pol.set_year(cyr) nonstd = Records(data=rawinputfile.name, gfactors=None, weights=None, start_year=cyr) assert nonstd.array_length == RAWINPUTFILE_FUNITS calc = Calculator(policy=pol, records=nonstd, sync_years=False) # keeps raw data unchanged assert calc.current_year == cyr calc.calc_all()
def test_convert_multiple_items(self): values = {"II_brk2_0": [36000., 38000., 40000., 41000], "II_brk2_1": [72250., 74000.], "II_brk2_2": [36500.] } values['II_em'] = [4000] ans = package_up_vars(values, first_budget_year=FBY) defaults = taxcalc.policy.Policy.default_data(start_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, f1_2017, f2_2017, None, None, None], [41000, f1_2018, f2_2018, None, None, None]] assert ans['_II_brk2'] == exp # For scalar parameter values, we still have that all user # choices propagate up through whatever is specified as # a default. We know that _II_em is specified up to 2016, so # package up vars needs to overwrite those default and return # 2015 and 2016 values exp_em = [4000, int(4000 *(1 + irates[0]))] assert ans['_II_em'] == exp_em assert len(ans) == 2
def test_calc_all(): """ Test calc_all method. """ cyr = 2016 pol = Policy() param_dict = Calculator.read_json_param_objects(REFORM_JSON, None) pol.implement_reform(param_dict['policy']) pol.set_year(cyr) nonstd = Records(data=pd.read_csv(StringIO(RAWINPUT_CONTENTS)), start_year=cyr, gfactors=None, weights=None) assert nonstd.array_length == RAWINPUT_FUNITS calc = Calculator(policy=pol, records=nonstd, sync_years=False) # keeps raw data unchanged assert calc.current_year == cyr assert calc.reform_warnings == ''
def test_calc_all(reform_file, rawinputfile): """ Test calc_all method. """ cyr = 2016 pol = Policy() param_dict = Calculator.read_json_param_objects(reform_file.name, None) pol.implement_reform(param_dict['policy']) pol.set_year(cyr) nonstd = Records(data=rawinputfile.name, gfactors=None, weights=None, start_year=cyr) assert nonstd.array_length == RAWINPUTFILE_FUNITS calc = Calculator(policy=pol, records=nonstd, sync_years=False) # keeps raw data unchanged assert calc.current_year == cyr assert calc.reform_warnings == ''
def test_correct_class_instantiation(): """ Test correct instantiation of Policy class object. """ pol = Policy() assert pol pol.implement_reform({}) with pytest.raises(ValueError): pol.implement_reform(list()) with pytest.raises(ValueError): pol.implement_reform({2099: {'II_em': 99000}}) pol.set_year(2019) with pytest.raises(ValueError): pol.implement_reform({2018: {'II_em': 99000}}) with pytest.raises(ValueError): pol.implement_reform({2020: {'II_em': -1000}})
def run(): """ Compute histograms for each marginal tax rate income type using sample input from the 'puf.csv' file and writing output to stdout. """ if NEG_DIFF: sys.stdout.write('MTR computed using NEGATIVE finite_diff.\n') else: sys.stdout.write('MTR computed using POSITIVE finite_diff.\n') # create a Policy object (clp) containing current-law policy parameters clp = Policy() clp.set_year(TAX_YEAR) # create a Records object (puf) containing puf.csv input records puf = Records() recid = puf.RECID # pylint: disable=no-member # create a Calculator object using clp policy and puf records calc = Calculator(policy=clp, records=puf) # . . . specify FICA mtr histogram bin boundaries (or edges): fica_bin_edges = [0.0, 0.02, 0.04, 0.06, 0.08, 0.10, 0.12, 0.14, 0.16, 0.18, 1.0] # the bin boundaries above are arbitrary, so users # may want to experiment with alternative boundaries # . . . specify IIT mtr histogram bin boundaries (or edges): iit_bin_edges = [-1.0, -0.30, -0.20, -0.10, 0.0, 0.10, 0.20, 0.30, 0.40, 0.50, 1.0] # the bin boundaries above are arbitrary, so users # may want to experiment with alternative boundaries assert len(fica_bin_edges) == len(iit_bin_edges) sys.stdout.write('{} = {}\n'.format('Total number of data records', puf.dim)) sys.stdout.write('FICA mtr histogram bin edges:\n') sys.stdout.write(' {}\n'.format(fica_bin_edges)) sys.stdout.write('IIT mtr histogram bin edges:\n') sys.stdout.write(' {}\n'.format(iit_bin_edges)) inctype_header = 'FICA and IIT mtr histogram bin counts for' # compute marginal tax rate (mtr) histograms for each mtr income type for inctype in Calculator.MTR_VALID_INCOME_TYPES: (mtr_fica, mtr_iit, _) = calc.mtr(income_type_str=inctype, negative_finite_diff=NEG_DIFF, wrt_full_compensation=False) sys.stdout.write('{} {}:\n'.format(inctype_header, inctype)) write_mtr_bin_counts(mtr_fica, fica_bin_edges, recid) write_mtr_bin_counts(mtr_iit, iit_bin_edges, recid)
def propagate_user_list(x, num_years, cpi, first_budget_year): """ Dispatch to either expand_1D or expand2D depending on the dimension of x Parameters: ----------- x : list from user to progagate forward in time. The first value is for year 'first_budget_year'. The value at index i is the value for budget year first_budget_year + i. num_years: int Number of budget years to expand cpi: Bool first_budget_year: int Returns: -------- list of length 'num_years'. if 'cpi'==True, the values will be inflated based on the last value the user specified """ # x can't be empty assert x pp = Policy(start_year=2013) pp.set_year(first_budget_year) # irates are rates for 2015, 2016, and 2017 if cpi: irates = pp.indexing_rates_for_update(param_name='II_brk2', calyear=first_budget_year, num_years_to_expand=num_years) else: irates = [0.0] * num_years last_val = x[-1] ans = [None] * num_years for i in range(num_years): if i < len(x): ans[i] = x[i] else: ans[i] = int(ans[i-1] * (1.0 + irates[i-1])) return ans
def test_Calculator_using_nonstd_input(rawinputfile): # check Calculator handling of raw, non-standard input data with no aging policy = Policy() policy.set_year(RAWINPUTFILE_YEAR) # set policy params to input data year nonpuf = Records( data=rawinputfile.name, start_year=RAWINPUTFILE_YEAR, # set raw input data year consider_imputations=False) # keeps raw data unchanged assert nonpuf.dim == RAWINPUTFILE_FUNITS calc = Calculator(policy=policy, records=nonpuf, sync_years=False) # keeps raw data unchanged assert calc.current_year == RAWINPUTFILE_YEAR calc.calc_all() exp_iitax = np.zeros((nonpuf.dim, )) assert_allclose(nonpuf._iitax, exp_iitax) mtr_fica, _, _ = calc.mtr(wrt_full_compensation=False) exp_mtr_fica = np.zeros((nonpuf.dim, )) exp_mtr_fica.fill(0.153) assert_allclose(mtr_fica, exp_mtr_fica)
def test_Calculator_using_nonstd_input(rawinputfile): # check Calculator handling of raw, non-standard input data with no aging policy = Policy() policy.set_year(RAWINPUTFILE_YEAR) # set policy params to input data year nonpuf = Records(data=rawinputfile.name, start_year=RAWINPUTFILE_YEAR, # set raw input data year consider_imputations=False) # keeps raw data unchanged assert nonpuf.dim == RAWINPUTFILE_FUNITS calc = Calculator(policy=policy, records=nonpuf, sync_years=False) # keeps raw data unchanged assert calc.current_year == RAWINPUTFILE_YEAR calc.calc_all() exp_iitax = np.zeros((nonpuf.dim,)) assert_array_equal(nonpuf._iitax, exp_iitax) mtr_fica, _, _ = calc.mtr(wrt_full_compensation=False) exp_mtr_fica = np.zeros((nonpuf.dim,)) exp_mtr_fica.fill(0.153) assert_array_equal(mtr_fica, exp_mtr_fica)
def test_expand_2d_accept_none_add_row(): # pylint doesn't like caps in var name, so pylint: disable=invalid-name _II_brk2 = [[36000, 72250, 36500, 48600, 72500], [38000, 74000, 36900, 49400, 73800], [40000, 74900, 37450, 50200, 74900], [41000, None, None, None, None], [43000, None, None, None, None]] exx = [0.0] exx.append(74900 * 1.02) # exx[1] exx.append(37450 * 1.02) # exx[2] exx.append(50200 * 1.02) # exx[3] exx.append(74900 * 1.02) # exx[4] exx.append(0.0) exx.append(exx[1] * 1.03) # exx[6] exx.append(exx[2] * 1.03) # exx[7] exx.append(exx[3] * 1.03) # exx[8] exx.append(exx[4] * 1.03) # exx[9] exp = [[36000, 72250, 36500, 48600, 72500], [38000, 74000, 36900, 49400, 73800], [40000, 74900, 37450, 50200, 74900], [41000, exx[1], exx[2], exx[3], exx[4]], [43000, exx[6], exx[7], exx[8], exx[9]]] inflation_rates = [0.015, 0.02, 0.02, 0.03] res = ParametersBase._expand_array(_II_brk2, inflate=True, inflation_rates=inflation_rates, num_years=5) assert_equal(res, exp) user_mods = {2016: {'_II_brk2': _II_brk2}} syr = 2013 pol = Policy(start_year=syr) irates = pol.inflation_rates() pol.implement_reform(user_mods) pol.set_year(2020) irates = pol.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 - syr]) * (1 + irates[2018 - syr]) * i for i in _II_brk2[2][1:]] exp_2020 = np.array(exp_2020) assert np.allclose(pol.II_brk2, exp_2020)
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}} syr = 2013 pol = Policy(start_year=syr) irates = pol.inflation_rates() pol.implement_reform(user_mods) pol.set_year(2020) irates = pol.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 - syr]) * (1 + irates[2018 - syr]) * i for i in _II_brk2[2][1:]] exp_2020 = np.array(exp_2020) npt.assert_allclose(pol.II_brk2, exp_2020)
def test_Calculator_using_nonstd_input(rawinputfile): # check Calculator handling of raw, non-standard input data with no aging policy = Policy() policy.set_year(RAWINPUTFILE_YEAR) # set policy params to input data year nonpuf = Records(data=rawinputfile.name, blowup_factors=None, # keeps raw data unchanged weights=None, start_year=RAWINPUTFILE_YEAR) # set raw input data year assert nonpuf.dim == RAWINPUTFILE_FUNITS calc = Calculator(policy=policy, records=nonpuf, sync_years=False) # keeps raw data unchanged assert calc.current_year == RAWINPUTFILE_YEAR calc.calc_all() exp_iitax = np.zeros((nonpuf.dim,)) assert np.allclose(nonpuf._iitax, exp_iitax) mtr_ptax, _, _ = calc.mtr(wrt_full_compensation=False) exp_mtr_ptax = np.zeros((nonpuf.dim,)) exp_mtr_ptax.fill(0.153) assert np.allclose(mtr_ptax, exp_mtr_ptax)
def test_variable_inflation_rate_with_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 # implement reform in 2020 which is two years before the last year, 2022 reform = {2020: {'_II_em': [20000]}} ppo.implement_reform(reform) ppo.set_year(2020) assert ppo.current_year == 2020 # check implied inflation rate between 2018 and 2019 (before the reform) grate = float(ppo._II_em[2019 - syr]) / float(ppo._II_em[2018 - syr]) - 1.0 assert round(grate, 3) == round(0.04, 3) # check implied inflation rate between 2020 and 2021 (after the reform) 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 (after the reform) 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_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 # pylint: disable=protected-access,no-member 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_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.0] + [(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_convert_non_cpi_inflated(self): values = {"FEI_ec_c": [100000.]} ans = package_up_vars(values, first_budget_year=FBY) defaults = taxcalc.policy.Policy.default_data(start_year=2015) 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='FEI_ec_c', calyear=FBY, num_years_to_expand=2) # User choices propagate through to all future years # The user has specified the parameter just for 2015, but # the defaults JSON file has values up to 2016. We should # give back values up to 2016, with user choice propagating f2_2016 = 100000 exp = [100000, f2_2016] assert ans['_FEI_ec_c'] == exp
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, rb, rg, rc = Calculator.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_brk1 = policy._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 = 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
def test_read_json_param_and_implement_reform(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_json = """ // Example of JSON reform text suitable for the // Calculator.read_json_param_objects() method. // This JSON text can contain any number of trailing //-style comments, // which will be removed before the contents are converted from JSON to // a dictionary. // The primary keys are policy parameters and secondary keys are years. // Both the primary & secondary key values must be enclosed in quotes ("). // Boolean variables are specified as true or false with no quotes and all // lowercase characters. { "policy": { "AMT_brk1": // top of first AMT tax bracket {"2015": 200000, "2017": 300000 }, "EITC_c": // max EITC amount by number of qualifying kids (0,1,2,3+) {"2016": [ 900, 5000, 8000, 9000], "2019": [1200, 7000, 10000, 12000] }, "II_em": // personal exemption amount (see indexing changes below) {"2016": 6000, "2018": 7500, "2020": 9000 }, "II_em-indexed": // personal exemption amount indexing status {"2016": false, // values in future years are same as this year value "2018": true // vals in future years indexed with this year as base }, "SS_Earnings_c": // Social Security (OASDI) maximum taxable earnings {"2016": 300000, "2018": 500000, "2020": 700000 }, "AMT_em-indexed": // AMT exemption amount indexing status {"2017": false, // values in future years are same as this year value "2020": true // vals in future years indexed with this year as base } } } """ policy = Policy() if set_year: policy.set_year(2015) param_dict = Calculator.read_json_param_objects(reform_json, None) policy.implement_reform(param_dict['policy']) syr = policy.start_year amt_brk1 = policy._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 = 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