def test_response_json(tests_path): """ Check that each JSON file can be converted into dictionaries that can be used to construct objects needed for a Calculator object. """ responses_path = os.path.join(tests_path, '..', 'responses', '*.json') for jpf in glob.glob(responses_path): # read contents of jpf (JSON parameter filename) jfile = open(jpf, 'r') jpf_text = jfile.read() # check that jpf_text can be used to construct objects response_file = ('"consumption"' in jpf_text and '"behavior"' in jpf_text and '"growdiff_baseline"' in jpf_text and '"growdiff_response"' in jpf_text) if response_file: # pylint: disable=protected-access (con, beh, gdiff_base, gdiff_resp) = Calculator._read_json_econ_assump_text(jpf_text) cons = Consumption() cons.update_consumption(con) behv = Behavior() behv.update_behavior(beh) growdiff_baseline = Growdiff() growdiff_baseline.update_growdiff(gdiff_base) growdiff_response = Growdiff() growdiff_response.update_growdiff(gdiff_resp) else: # jpf_text is not a valid JSON response assumption file print('test-failing-filename: ' + jpf) assert False
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_taxbrain_json(taxbrain_path): # pylint: disable=redefined-outer-name """ Check that each JSON parameter file can be converted into dictionaries that can be used to construct objects needed for a Calculator object. """ for jpf in glob.glob(taxbrain_path): # read contents of jpf (JSON parameter filename) jfile = open(jpf, 'r') jpf_text = jfile.read() # check that jpf_text can be used to construct objects if '"policy"' in jpf_text: pol = Calculator.read_json_policy_reform_text(jpf_text) policy = Policy() policy.implement_reform(pol) elif ('"consumption"' in jpf_text and '"behavior"' in jpf_text and '"growdiff_baseline"' in jpf_text and '"growdiff_response"' in jpf_text): (con, beh, gdiff_base, gdiff_resp) = Calculator.read_json_econ_assump_text(jpf_text) cons = Consumption() cons.update_consumption(con) behv = Behavior() behv.update_behavior(beh) growdiff_baseline = Growdiff() growdiff_baseline.update_growdiff(gdiff_base) growdiff_response = Growdiff() growdiff_response.update_growdiff(gdiff_resp) else: # jpf_text is not a valid JSON parameter file print('test-failing-filename: ' + jpf) assert False
def test_response_json(tests_path): """ Check that each JSON file can be converted into dictionaries that can be used to construct objects needed for a Calculator object. """ # pylint: disable=too-many-locals responses_path = os.path.join(tests_path, '..', 'responses', '*.json') for jpf in glob.glob(responses_path): # read contents of jpf (JSON parameter filename) jfile = open(jpf, 'r') jpf_text = jfile.read() # check that jpf_text can be used to construct objects response_file = ('"consumption"' in jpf_text and '"growdiff_baseline"' in jpf_text and '"growdiff_response"' in jpf_text) if response_file: # pylint: disable=protected-access (con, gdiff_base, gdiff_resp) = Calculator._read_json_econ_assump_text(jpf_text) cons = Consumption() cons.update_consumption(con) growdiff_baseline = GrowDiff() growdiff_baseline.update_growdiff(gdiff_base) growdiff_response = GrowDiff() growdiff_response.update_growdiff(gdiff_resp) else: # jpf_text is not a valid JSON response assumption file print('test-failing-filename: ' + jpf) assert False
def test_response_json(tests_path): """ Check that each JSON file can be converted into dictionaries that can be used to construct objects needed for a Calculator object. """ # pylint: disable=too-many-locals responses_path = os.path.join(tests_path, '..', 'responses', '*.json') for jpf in glob.glob(responses_path): # read contents of jpf (JSON parameter filename) jfile = open(jpf, 'r') jpf_text = jfile.read() # check that jpf_text can be used to construct objects response_file = ('"consumption"' in jpf_text and '"growdiff_baseline"' in jpf_text and '"growdiff_response"' in jpf_text) if response_file: consumption = Consumption() con_change = Consumption.read_json_update(jpf_text) consumption.update_consumption(con_change) del consumption for topkey in ['growdiff_baseline', 'growdiff_response']: growdiff = GrowDiff() gdiff_change = GrowDiff.read_json_update(jpf_text, topkey) growdiff.update_growdiff(gdiff_change) del growdiff else: # jpf_text is not a valid JSON response assumption file print('test-failing-filename: ' + jpf) assert False
def test_consumption_default_data(): consump = Consumption() pdata = consump.specification(meta_data=True, ignore_state=True) for pname in pdata.keys(): if pname.startswith('MPC'): assert pdata[pname]['value'] == [{"value": 0.0, "year": 2013}] elif pname.startswith('BEN'): assert pdata[pname]['value'] == [{"value": 1.0, "year": 2013}]
def reform_warnings_errors(user_mods, using_puf): """ The reform_warnings_errors function assumes user_mods is a dictionary returned by the Calculator.read_json_param_objects() function. This function returns a dictionary containing five STR:STR subdictionaries, where the dictionary keys are: 'policy', 'behavior', consumption', 'growdiff_baseline' and 'growdiff_response'; and the subdictionaries are: {'warnings': '<empty-or-message(s)>', 'errors': '<empty-or-message(s)>'}. Note that non-policy parameters have no warnings, so the 'warnings' string for the non-policy parameters is always empty. """ rtn_dict = {'policy': {'warnings': '', 'errors': ''}, 'behavior': {'warnings': '', 'errors': ''}, 'consumption': {'warnings': '', 'errors': ''}, 'growdiff_baseline': {'warnings': '', 'errors': ''}, 'growdiff_response': {'warnings': '', 'errors': ''}} # create GrowDiff objects gdiff_baseline = GrowDiff() try: gdiff_baseline.update_growdiff(user_mods['growdiff_baseline']) except ValueError as valerr_msg: rtn_dict['growdiff_baseline']['errors'] = valerr_msg.__str__() gdiff_response = GrowDiff() try: gdiff_response.update_growdiff(user_mods['growdiff_response']) except ValueError as valerr_msg: rtn_dict['growdiff_response']['errors'] = valerr_msg.__str__() # create Growfactors object growfactors = GrowFactors() gdiff_baseline.apply_to(growfactors) gdiff_response.apply_to(growfactors) # create Policy object pol = Policy(gfactors=growfactors) try: pol.implement_reform(user_mods['policy'], print_warnings=False, raise_errors=False) if using_puf: rtn_dict['policy']['warnings'] = pol.parameter_warnings rtn_dict['policy']['errors'] = pol.parameter_errors except ValueError as valerr_msg: rtn_dict['policy']['errors'] = valerr_msg.__str__() # create Behavior object behv = Behavior() try: behv.update_behavior(user_mods['behavior']) except ValueError as valerr_msg: rtn_dict['behavior']['errors'] = valerr_msg.__str__() # create Consumption object consump = Consumption() try: consump.update_consumption(user_mods['consumption']) except ValueError as valerr_msg: rtn_dict['consumption']['errors'] = valerr_msg.__str__() # return composite dictionary of warnings/errors return rtn_dict
def test_future_update_consumption(): consump = Consumption() assert consump.current_year == consump.start_year assert consump.has_response() is False cyr = 2020 consump.set_year(cyr) consump.update_consumption({cyr: {"_MPC_e20400": [0.01]}}) assert consump.current_year == cyr assert consump.has_response() is True consump.set_year(cyr - 1) assert consump.has_response() is False
def test_update_consumption(): consump = Consumption(start_year=2013) consump.update_consumption({2014: {"_MPC_e20400": [0.05]}, 2015: {"_MPC_e20400": [0.06]}}) expected_mpc_e20400 = np.full((Consumption.DEFAULT_NUM_YEARS,), 0.06) expected_mpc_e20400[0] = 0.0 expected_mpc_e20400[1] = 0.05 assert np.allclose(consump._MPC_e20400, expected_mpc_e20400, rtol=0.0) assert np.allclose(consump._MPC_e17500, np.zeros((Consumption.DEFAULT_NUM_YEARS,)), rtol=0.0) consump.set_year(2015) assert consump.current_year == 2015 assert consump.MPC_e20400 == 0.06 assert consump.MPC_e17500 == 0.0
def reform_warnings_errors(user_mods, using_puf): """ The reform_warnings_errors function assumes user_mods is a dictionary returned by the Calculator.read_json_param_objects() function. This function returns a dictionary containing five STR:STR subdictionaries, where the dictionary keys are: 'policy', 'consumption', 'growdiff_baseline' and 'growdiff_response'; and the subdictionaries are: {'warnings': '<empty-or-message(s)>', 'errors': '<empty-or-message(s)>'}. Note that non-policy parameters have no warnings, so the 'warnings' string for the non-policy parameters is always empty. """ rtn_dict = {'policy': {'warnings': '', 'errors': ''}, 'consumption': {'warnings': '', 'errors': ''}, 'growdiff_baseline': {'warnings': '', 'errors': ''}, 'growdiff_response': {'warnings': '', 'errors': ''}} # create GrowDiff objects gdiff_baseline = GrowDiff() try: gdiff_baseline.update_growdiff(user_mods['growdiff_baseline']) except ValueError as valerr_msg: rtn_dict['growdiff_baseline']['errors'] = valerr_msg.__str__() gdiff_response = GrowDiff() try: gdiff_response.update_growdiff(user_mods['growdiff_response']) except ValueError as valerr_msg: rtn_dict['growdiff_response']['errors'] = valerr_msg.__str__() # create Growfactors object growfactors = GrowFactors() gdiff_baseline.apply_to(growfactors) gdiff_response.apply_to(growfactors) # create Policy object pol = Policy(gfactors=growfactors) try: pol.implement_reform(user_mods['policy'], print_warnings=False, raise_errors=False) if using_puf: rtn_dict['policy']['warnings'] = pol.parameter_warnings rtn_dict['policy']['errors'] = pol.parameter_errors except ValueError as valerr_msg: rtn_dict['policy']['errors'] = valerr_msg.__str__() # create Consumption object consump = Consumption() try: consump.update_consumption(user_mods['consumption']) except ValueError as valerr_msg: rtn_dict['consumption']['errors'] = valerr_msg.__str__() # return composite dictionary of warnings/errors return rtn_dict
def test_update_consumption(): consump = Consumption(start_year=2013) consump.update_consumption({}) consump.update_consumption({ 2014: { '_MPC_e20400': [0.05], '_BEN_mcare_value': [0.75] }, 2015: { '_MPC_e20400': [0.06], '_BEN_mcare_value': [0.80] } }) expected_mpc_e20400 = np.full((Consumption.DEFAULT_NUM_YEARS, ), 0.06) expected_mpc_e20400[0] = 0.0 expected_mpc_e20400[1] = 0.05 assert np.allclose(consump._MPC_e20400, expected_mpc_e20400, rtol=0.0) assert np.allclose(consump._MPC_e17500, np.zeros((Consumption.DEFAULT_NUM_YEARS, )), rtol=0.0) expected_ben_mcare_value = np.full((Consumption.DEFAULT_NUM_YEARS, ), 0.80) expected_ben_mcare_value[0] = 1.0 expected_ben_mcare_value[1] = 0.75 assert np.allclose(consump._BEN_mcare_value, expected_ben_mcare_value, rtol=0.0) assert np.allclose(consump._BEN_snap_value, np.ones((Consumption.DEFAULT_NUM_YEARS, )), rtol=0.0) consump.set_year(2015) assert consump.current_year == 2015 assert consump.MPC_e20400 == 0.06 assert consump.MPC_e17500 == 0.0 assert consump.BEN_mcare_value == 0.80 assert consump.BEN_snap_value == 1.0
def test_consumption_response(cps_subsample): consump = Consumption() mpc = 0.5 consumption_response = {2013: {'_MPC_e20400': [mpc]}} consump.update_consumption(consumption_response) # test incorrect call to response method with pytest.raises(ValueError): consump.response(list(), 1) # test correct call to response method rec = Records.cps_constructor(data=cps_subsample) pre = copy.deepcopy(rec.e20400) consump.response(rec, 1.0) post = rec.e20400 actual_diff = post - pre expected_diff = np.ones(rec.dim) * mpc assert np.allclose(actual_diff, expected_diff) # compute earnings mtr with no consumption response rec = Records.cps_constructor(data=cps_subsample) ided0 = copy.deepcopy(rec.e20400) calc0 = Calculator(policy=Policy(), records=rec, consumption=None) (mtr0_ptax, mtr0_itax, _) = calc0.mtr(variable_str='e00200p', wrt_full_compensation=False) assert np.allclose(calc0.records.e20400, ided0) # compute earnings mtr with consumption response calc1 = Calculator(policy=Policy(), records=rec, consumption=consump) mtr1_ptax, mtr1_itax, _ = calc1.mtr(variable_str='e00200p', wrt_full_compensation=False) assert np.allclose(calc1.records.e20400, ided0) # confirm that payroll mtr values are no different assert np.allclose(mtr1_ptax, mtr0_ptax) # confirm that all mtr with cons-resp are no greater than without cons-resp assert np.all(np.less_equal(np.around(mtr1_itax, decimals=5), np.around(mtr0_itax, decimals=5))) # confirm that some mtr with cons-resp are less than without cons-resp assert np.any(np.less(mtr1_itax, mtr0_itax))
def test_consumption_default_data(): paramdata = Consumption.default_data() for param in paramdata: if param.startswith('_MPC'): assert paramdata[param] == [0.0] elif param.startswith('_BEN'): assert paramdata[param] == [1.0]
def test_consumption_default_data(): consump = Consumption() pdata = consump._vals for pname in pdata.keys(): if pname.startswith('MPC'): assert pdata[pname]['value'] == [0.0] elif pname.startswith('BEN'): assert pdata[pname]['value'] == [1.0]
def test_update_consumption(): consump = Consumption() consump.update_consumption({}) revision = { 'MPC_e20400': {2014: 0.05, 2015: 0.06}, 'BEN_mcare_value': {2014: 0.75, 2015: 0.80} } consump.update_consumption(revision) expected_mpc_e20400 = np.full((Consumption.DEFAULT_NUM_YEARS,), 0.06) expected_mpc_e20400[0] = 0.0 expected_mpc_e20400[1] = 0.05 assert np.allclose(consump._MPC_e20400, expected_mpc_e20400, rtol=0.0) assert np.allclose(consump._MPC_e17500, np.zeros((Consumption.DEFAULT_NUM_YEARS,)), rtol=0.0) expected_ben_mcare_value = np.full((Consumption.DEFAULT_NUM_YEARS,), 0.80) expected_ben_mcare_value[0] = 1.0 expected_ben_mcare_value[1] = 0.75 assert np.allclose(consump._BEN_mcare_value, expected_ben_mcare_value, rtol=0.0) assert np.allclose(consump._BEN_snap_value, np.ones((Consumption.DEFAULT_NUM_YEARS,)), rtol=0.0) consump.set_year(2015) assert consump.current_year == 2015 assert consump.MPC_e20400 == 0.06 assert consump.MPC_e17500 == 0.0 assert consump.BEN_mcare_value == 0.80 assert consump.BEN_snap_value == 1.0
def test_consumption_response(cps_subsample): consump = Consumption() mpc = 0.5 consumption_response = {'MPC_e20400': {2013: mpc}} consump.update_consumption(consumption_response) # test incorrect call to response method with pytest.raises(ValueError): consump.response(list(), 1) # test correct call to response method rec = Records.cps_constructor(data=cps_subsample) pre = copy.deepcopy(rec.e20400) consump.response(rec, 1.0) post = rec.e20400 actual_diff = post - pre expected_diff = np.ones(rec.array_length) * mpc assert np.allclose(actual_diff, expected_diff) # compute earnings mtr with no consumption response rec = Records.cps_constructor(data=cps_subsample) ided0 = copy.deepcopy(rec.e20400) calc0 = Calculator(policy=Policy(), records=rec, consumption=None) (mtr0_ptax, mtr0_itax, _) = calc0.mtr(variable_str='e00200p', wrt_full_compensation=False) assert np.allclose(calc0.array('e20400'), ided0) # compute earnings mtr with consumption response calc1 = Calculator(policy=Policy(), records=rec, consumption=consump) mtr1_ptax, mtr1_itax, _ = calc1.mtr(variable_str='e00200p', wrt_full_compensation=False) assert np.allclose(calc1.array('e20400'), ided0) # confirm that payroll mtr values are no different assert np.allclose(mtr1_ptax, mtr0_ptax) # confirm that all mtr with cons-resp are no greater than without cons-resp assert np.all(np.less_equal(np.around(mtr1_itax, decimals=5), np.around(mtr0_itax, decimals=5))) # confirm that some mtr with cons-resp are less than without cons-resp assert np.any(np.less(mtr1_itax, mtr0_itax))
def test_consumption_response(puf_1991, weights_1991): consump = Consumption() mpc = 0.5 consumption_response = {2013: {"_MPC_e20400": [mpc]}} consump.update_consumption(consumption_response) # test incorrect call to response method with pytest.raises(ValueError): consump.response(list(), 1) # test correct call to response method recs = Records(data=puf_1991, weights=weights_1991, start_year=2009) pre = copy.deepcopy(recs.e20400) consump.response(recs, 1.0) post = recs.e20400 actual_diff = post - pre expected_diff = np.ones(recs.dim) * mpc assert np.allclose(actual_diff, expected_diff) # compute earnings mtr with no consumption response recs0 = Records(data=puf_1991, weights=weights_1991, start_year=2009) calc0 = Calculator(policy=Policy(), records=recs0, consumption=None) ided0 = copy.deepcopy(recs0.e20400) (mtr0_ptax, mtr0_itax, _) = calc0.mtr(variable_str="e00200p", wrt_full_compensation=False) assert np.allclose(calc0.records.e20400, ided0) # compute earnings mtr with consumption response recs1 = Records(data=puf_1991, weights=weights_1991, start_year=2009) calc1 = Calculator(policy=Policy(), records=recs1, consumption=None) assert np.allclose(calc1.records.e20400, ided0) calc1.consumption.update_consumption(consumption_response) (mtr1_ptax, mtr1_itax, _) = calc1.mtr(variable_str="e00200p", wrt_full_compensation=False) assert np.allclose(calc1.records.e20400, ided0) # confirm that payroll mtr values are no different assert np.allclose(mtr1_ptax, mtr0_ptax) # confirm that all mtr with cons-resp are no greater than without cons-resp assert np.all(np.less_equal(mtr1_itax, mtr0_itax)) # confirm that some mtr with cons-resp are less than without cons-resp assert np.any(np.less(mtr1_itax, mtr0_itax))
def test_make_Calculator(cps_subsample): parm = Policy(start_year=2014, num_years=9) assert parm.current_year == 2014 recs = Records.cps_constructor(data=cps_subsample) consump = Consumption() consump.update_consumption({2014: {'_MPC_e20400': [0.05]}}) assert consump.current_year == 2013 calc = Calculator(policy=parm, records=recs, consumption=consump, behavior=Behavior()) assert calc.current_year == 2014 # test incorrect Calculator instantiation: with pytest.raises(ValueError): calc = Calculator(policy=None, records=recs) with pytest.raises(ValueError): calc = Calculator(policy=parm, records=None) with pytest.raises(ValueError): calc = Calculator(policy=parm, records=recs, behavior=list()) with pytest.raises(ValueError): calc = Calculator(policy=parm, records=recs, consumption=list())
def test_make_Calculator(records_2009): parm = Policy() assert parm.current_year == 2013 recs = records_2009 consump = Consumption() consump.update_consumption({2014: {'_MPC_e20400': [0.05]}}) assert consump.current_year == 2013 calc = Calculator(policy=parm, records=recs, consumption=consump) assert calc.current_year == 2013 # test incorrect Calculator instantiation: with pytest.raises(ValueError): calc = Calculator(policy=None, records=recs) with pytest.raises(ValueError): calc = Calculator(policy=parm, records=None) with pytest.raises(ValueError): calc = Calculator(policy=parm, records=recs, behavior=list()) with pytest.raises(ValueError): calc = Calculator(policy=parm, records=recs, growth=list()) with pytest.raises(ValueError): calc = Calculator(policy=parm, records=recs, consumption=list())
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_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({sim_year: {'_MPC_e20400': [0.05]}}) assert consump.current_year == start_year calc = Calculator(policy=pol, records=rec, consumption=consump) 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_incorrect_update_consumption(): with pytest.raises(ValueError): Consumption().update_consumption([]) with pytest.raises(ValueError): Consumption().update_consumption({'MPC_e17500': {'xyz': 0.2}}) with pytest.raises(ValueError): Consumption().update_consumption({'MPC_e17500': {2012: 0.2}}) with pytest.raises(ValueError): Consumption().update_consumption({'MPC_e17500': {2052: 0.2}}) with pytest.raises(ValueError): Consumption().update_consumption({'MPC_exxxxx': {2014: 0.2}}) with pytest.raises(ValueError): Consumption().update_consumption({'MPC_e17500': {2014: -0.1}}) with pytest.raises(ValueError): Consumption().update_consumption({'MPC_e17500-indexed': {2014: 0.1}})
def test_incorrect_update_consumption(): with pytest.raises(ValueError): Consumption().update_consumption([]) with pytest.raises(ValueError): Consumption().update_consumption({'xyz': {'_MPC_e17500': [0.2]}}) with pytest.raises(ValueError): Consumption().update_consumption({2012: {'_MPC_e17500': [0.2]}}) with pytest.raises(ValueError): Consumption().update_consumption({2052: {'_MPC_e17500': [0.2]}}) with pytest.raises(ValueError): Consumption().update_consumption({2014: {'_MPC_exxxxx': [0.2]}}) with pytest.raises(ValueError): Consumption().update_consumption({2014: {'_MPC_e17500': [-0.1]}})
def test_consumption_response(puf_1991, weights_1991): consump = Consumption() mpc = 0.5 consumption_response = {2013: {'_MPC_e20400': [mpc]}} consump.update_consumption(consumption_response) # test incorrect call to response method with pytest.raises(ValueError): consump.response(list(), 1) # test correct call to response method recs = Records(data=puf_1991, weights=weights_1991, start_year=2009) pre = copy.deepcopy(recs.e20400) consump.response(recs, 1.0) post = recs.e20400 actual_diff = post - pre expected_diff = np.ones(recs.dim) * mpc assert np.allclose(actual_diff, expected_diff) # compute earnings mtr with no consumption response recs0 = Records(data=puf_1991, weights=weights_1991, start_year=2009) calc0 = Calculator(policy=Policy(), records=recs0, consumption=None) ided0 = copy.deepcopy(recs0.e20400) (mtr0_ptax, mtr0_itax, _) = calc0.mtr(variable_str='e00200p', wrt_full_compensation=False) assert np.allclose(calc0.records.e20400, ided0) # compute earnings mtr with consumption response recs1 = Records(data=puf_1991, weights=weights_1991, start_year=2009) calc1 = Calculator(policy=Policy(), records=recs1, consumption=None) assert np.allclose(calc1.records.e20400, ided0) calc1.consumption.update_consumption(consumption_response) (mtr1_ptax, mtr1_itax, _) = calc1.mtr(variable_str='e00200p', wrt_full_compensation=False) assert np.allclose(calc1.records.e20400, ided0) # confirm that payroll mtr values are no different assert np.allclose(mtr1_ptax, mtr0_ptax) # confirm that all mtr with cons-resp are no greater than without cons-resp assert np.all(np.less_equal(mtr1_itax, mtr0_itax)) # confirm that some mtr with cons-resp are less than without cons-resp assert np.any(np.less(mtr1_itax, mtr0_itax))
def test_update_consumption(): consump = Consumption() consump.update_consumption({}) revision = { 'MPC_e20400': { 2014: 0.05, 2015: 0.06 }, 'BEN_mcare_value': { 2014: 0.75, 2015: 0.80 } } consump.update_consumption(revision) expected_mpc_e20400 = np.full((Consumption.DEFAULT_NUM_YEARS, ), 0.06) expected_mpc_e20400[0] = 0.0 expected_mpc_e20400[1] = 0.05 assert np.allclose(consump._MPC_e20400, expected_mpc_e20400, rtol=0.0) assert np.allclose(consump._MPC_e17500, np.zeros((Consumption.DEFAULT_NUM_YEARS, )), rtol=0.0) expected_ben_mcare_value = np.full((Consumption.DEFAULT_NUM_YEARS, ), 0.80) expected_ben_mcare_value[0] = 1.0 expected_ben_mcare_value[1] = 0.75 assert np.allclose(consump._BEN_mcare_value, expected_ben_mcare_value, rtol=0.0) assert np.allclose(consump._BEN_snap_value, np.ones((Consumption.DEFAULT_NUM_YEARS, )), rtol=0.0) consump.set_year(2015) assert consump.current_year == 2015 assert consump.MPC_e20400 == 0.06 assert consump.MPC_e17500 == 0.0 assert consump.BEN_mcare_value == 0.80 assert consump.BEN_snap_value == 1.0
def test_update_consumption(): consump = Consumption(start_year=2013) consump.update_consumption({2014: {'_MPC_e20400': [0.05]}, 2015: {'_MPC_e20400': [0.06]}}) expected_mpc_e20400 = np.full((Consumption.DEFAULT_NUM_YEARS,), 0.06) expected_mpc_e20400[0] = 0.0 expected_mpc_e20400[1] = 0.05 assert np.allclose(consump._MPC_e20400, expected_mpc_e20400, rtol=0.0) assert np.allclose(consump._MPC_e17500, np.zeros((Consumption.DEFAULT_NUM_YEARS,)), rtol=0.0) consump.set_year(2015) assert consump.current_year == 2015 assert consump.MPC_e20400 == 0.06 assert consump.MPC_e17500 == 0.0
def calculate(year_n, start_year, use_puf_not_cps, use_full_sample, user_mods, behavior_allowed): """ The calculate function assumes the specified user_mods is a dictionary returned by the Calculator.read_json_param_objects() function. The function returns (calc1, calc2, mask) where calc1 is pre-reform Calculator object calculated for year_n, calc2 is post-reform Calculator object calculated for year_n, and mask is boolean array marking records with reform-induced iitax diffs Set behavior_allowed to False when generating static results or set behavior_allowed to True when generating dynamic results. """ # pylint: disable=too-many-arguments,too-many-locals # pylint: disable=too-many-branches,too-many-statements check_user_mods(user_mods) # specify Consumption instance consump = Consumption() consump_assumptions = user_mods['consumption'] consump.update_consumption(consump_assumptions) # specify growdiff_baseline and growdiff_response growdiff_baseline = Growdiff() growdiff_response = Growdiff() growdiff_base_assumps = user_mods['growdiff_baseline'] growdiff_resp_assumps = user_mods['growdiff_response'] growdiff_baseline.update_growdiff(growdiff_base_assumps) growdiff_response.update_growdiff(growdiff_resp_assumps) # create pre-reform and post-reform Growfactors instances growfactors_pre = Growfactors() growdiff_baseline.apply_to(growfactors_pre) growfactors_post = Growfactors() growdiff_baseline.apply_to(growfactors_post) growdiff_response.apply_to(growfactors_post) # create sample pd.DataFrame from specified input file and sampling scheme stime = time.time() tbi_path = os.path.abspath(os.path.dirname(__file__)) if use_puf_not_cps: # first try TaxBrain deployment path input_path = 'puf.csv.gz' if not os.path.isfile(input_path): # otherwise try local Tax-Calculator deployment path input_path = os.path.join(tbi_path, '..', '..', 'puf.csv') sampling_frac = 0.05 sampling_seed = 180 else: # if using cps input not puf input # first try Tax-Calculator code path input_path = os.path.join(tbi_path, '..', 'cps.csv.gz') if not os.path.isfile(input_path): # otherwise read from taxcalc package "egg" input_path = None # pragma: no cover full_sample = read_egg_csv('cps.csv.gz') # pragma: no cover sampling_frac = 0.03 sampling_seed = 180 if input_path: full_sample = pd.read_csv(input_path) if use_full_sample: sample = full_sample else: sample = full_sample.sample( # pylint: disable=no-member frac=sampling_frac, random_state=sampling_seed) if use_puf_not_cps: print('puf-read-time= {:.1f}'.format(time.time() - stime)) else: print('cps-read-time= {:.1f}'.format(time.time() - stime)) # create pre-reform Calculator instance if use_puf_not_cps: recs1 = Records(data=copy.deepcopy(sample), gfactors=growfactors_pre) else: recs1 = Records.cps_constructor(data=copy.deepcopy(sample), gfactors=growfactors_pre) policy1 = Policy(gfactors=growfactors_pre) calc1 = Calculator(policy=policy1, records=recs1, consumption=consump) while calc1.current_year < start_year: calc1.increment_year() calc1.calc_all() assert calc1.current_year == start_year # compute mask array res1 = calc1.dataframe(DIST_VARIABLES) if use_puf_not_cps: # create pre-reform Calculator instance with extra income recs1p = Records(data=copy.deepcopy(sample), gfactors=growfactors_pre) # add one dollar to the income of each filing unit to determine # which filing units undergo a resulting change in tax liability recs1p.e00200 += 1.0 # pylint: disable=no-member recs1p.e00200p += 1.0 # pylint: disable=no-member policy1p = Policy(gfactors=growfactors_pre) # create Calculator with recs1p and calculate for start_year calc1p = Calculator(policy=policy1p, records=recs1p, consumption=consump) while calc1p.current_year < start_year: calc1p.increment_year() calc1p.calc_all() assert calc1p.current_year == start_year # compute mask showing which of the calc1 and calc1p results differ; # mask is true if a filing unit's income tax liability changed after # a dollar was added to the filing unit's wage and salary income res1p = calc1p.dataframe(DIST_VARIABLES) mask = np.logical_not( # pylint: disable=no-member np.isclose(res1.iitax, res1p.iitax, atol=0.001, rtol=0.0)) assert np.any(mask) else: # if use_cps_not_cps is False # indicate that no fuzzing of reform results is required mask = np.zeros(res1.shape[0], dtype=np.int8) # specify Behavior instance behv = Behavior() behavior_assumps = user_mods['behavior'] behv.update_behavior(behavior_assumps) # always prevent both behavioral response and growdiff response if behv.has_any_response() and growdiff_response.has_any_response(): msg = 'BOTH behavior AND growdiff_response HAVE RESPONSE' raise ValueError(msg) # optionally prevent behavioral response if behv.has_any_response() and not behavior_allowed: msg = 'A behavior RESPONSE IS NOT ALLOWED' raise ValueError(msg) # create post-reform Calculator instance if use_puf_not_cps: recs2 = Records(data=copy.deepcopy(sample), gfactors=growfactors_post) else: recs2 = Records.cps_constructor(data=copy.deepcopy(sample), gfactors=growfactors_post) policy2 = Policy(gfactors=growfactors_post) policy_reform = user_mods['policy'] policy2.implement_reform(policy_reform) calc2 = Calculator(policy=policy2, records=recs2, consumption=consump, behavior=behv) while calc2.current_year < start_year: calc2.increment_year() calc2.calc_all() assert calc2.current_year == start_year # increment Calculator objects for year_n years and calculate for _ in range(0, year_n): calc1.increment_year() calc2.increment_year() calc1.calc_all() if calc2.behavior_has_response(): calc2 = Behavior.response(calc1, calc2) else: calc2.calc_all() # return calculated Calculator objects and mask return (calc1, calc2, mask)
def calculators(year_n, start_year, use_puf_not_cps, use_full_sample, user_mods): """ This function assumes that the specified user_mods is a dictionary returned by the Calculator.read_json_param_objects() function. This function returns (calc1, calc2) where calc1 is pre-reform Calculator object for year_n, and calc2 is post-reform Calculator object for year_n. Neither Calculator object has had the calc_all() method executed. """ # pylint: disable=too-many-locals,too-many-branches,too-many-statements check_user_mods(user_mods) # specify Consumption instance consump = Consumption() consump_assumptions = user_mods['consumption'] consump.update_consumption(consump_assumptions) # specify growdiff_baseline and growdiff_response growdiff_baseline = GrowDiff() growdiff_response = GrowDiff() growdiff_base_assumps = user_mods['growdiff_baseline'] growdiff_resp_assumps = user_mods['growdiff_response'] growdiff_baseline.update_growdiff(growdiff_base_assumps) growdiff_response.update_growdiff(growdiff_resp_assumps) # create pre-reform and post-reform GrowFactors instances growfactors_pre = GrowFactors() growdiff_baseline.apply_to(growfactors_pre) growfactors_post = GrowFactors() growdiff_baseline.apply_to(growfactors_post) growdiff_response.apply_to(growfactors_post) # create sample pd.DataFrame from specified input file and sampling scheme tbi_path = os.path.abspath(os.path.dirname(__file__)) if use_puf_not_cps: # first try TaxBrain deployment path input_path = 'puf.csv.gz' if not os.path.isfile(input_path): # otherwise try local Tax-Calculator deployment path input_path = os.path.join(tbi_path, '..', '..', 'puf.csv') sampling_frac = 0.05 sampling_seed = 2222 else: # if using cps input not puf input # first try Tax-Calculator code path input_path = os.path.join(tbi_path, '..', 'cps.csv.gz') if not os.path.isfile(input_path): # otherwise read from taxcalc package "egg" input_path = None # pragma: no cover full_sample = read_egg_csv('cps.csv.gz') # pragma: no cover sampling_frac = 0.03 sampling_seed = 180 if input_path: full_sample = pd.read_csv(input_path) if use_full_sample: sample = full_sample else: sample = full_sample.sample(frac=sampling_frac, random_state=sampling_seed) # create pre-reform Calculator instance if use_puf_not_cps: recs1 = Records(data=sample, gfactors=growfactors_pre) else: recs1 = Records.cps_constructor(data=sample, gfactors=growfactors_pre) policy1 = Policy(gfactors=growfactors_pre) calc1 = Calculator(policy=policy1, records=recs1, consumption=consump) while calc1.current_year < start_year: calc1.increment_year() assert calc1.current_year == start_year # create post-reform Calculator instance if use_puf_not_cps: recs2 = Records(data=sample, gfactors=growfactors_post) else: recs2 = Records.cps_constructor(data=sample, gfactors=growfactors_post) policy2 = Policy(gfactors=growfactors_post) policy_reform = user_mods['policy'] policy2.implement_reform(policy_reform) calc2 = Calculator(policy=policy2, records=recs2, consumption=consump) while calc2.current_year < start_year: calc2.increment_year() assert calc2.current_year == start_year # delete objects now embedded in calc1 and calc2 del sample del full_sample del consump del growdiff_baseline del growdiff_response del growfactors_pre del growfactors_post del recs1 del recs2 del policy1 del policy2 # increment Calculator objects for year_n years for _ in range(0, year_n): calc1.increment_year() calc2.increment_year() # return Calculator objects return (calc1, calc2)
def test_incorrect_Consumption_instantiation(): with pytest.raises(ValueError): consump = Consumption(start_year=2000) with pytest.raises(ValueError): consump = Consumption(num_years=0)
def calculator_objects(year_n, start_year, use_puf_not_cps, use_full_sample, user_mods, behavior_allowed): """ This function assumes that the specified user_mods is a dictionary returned by the Calculator.read_json_param_objects() function. This function returns (calc1, calc2) where calc1 is pre-reform Calculator object calculated for year_n, and calc2 is post-reform Calculator object calculated for year_n. Set behavior_allowed to False when generating static results or set behavior_allowed to True when generating dynamic results. """ # pylint: disable=too-many-arguments,too-many-locals # pylint: disable=too-many-branches,too-many-statements check_user_mods(user_mods) # specify Consumption instance consump = Consumption() consump_assumptions = user_mods['consumption'] consump.update_consumption(consump_assumptions) # specify growdiff_baseline and growdiff_response growdiff_baseline = GrowDiff() growdiff_response = GrowDiff() growdiff_base_assumps = user_mods['growdiff_baseline'] growdiff_resp_assumps = user_mods['growdiff_response'] growdiff_baseline.update_growdiff(growdiff_base_assumps) growdiff_response.update_growdiff(growdiff_resp_assumps) # create pre-reform and post-reform GrowFactors instances growfactors_pre = GrowFactors() growdiff_baseline.apply_to(growfactors_pre) growfactors_post = GrowFactors() growdiff_baseline.apply_to(growfactors_post) growdiff_response.apply_to(growfactors_post) # create sample pd.DataFrame from specified input file and sampling scheme tbi_path = os.path.abspath(os.path.dirname(__file__)) if use_puf_not_cps: # first try TaxBrain deployment path input_path = 'puf.csv.gz' if not os.path.isfile(input_path): # otherwise try local Tax-Calculator deployment path input_path = os.path.join(tbi_path, '..', '..', 'puf.csv') sampling_frac = 0.05 sampling_seed = 2222 else: # if using cps input not puf input # first try Tax-Calculator code path input_path = os.path.join(tbi_path, '..', 'cps.csv.gz') if not os.path.isfile(input_path): # otherwise read from taxcalc package "egg" input_path = None # pragma: no cover full_sample = read_egg_csv('cps.csv.gz') # pragma: no cover sampling_frac = 0.03 sampling_seed = 180 if input_path: full_sample = pd.read_csv(input_path) if use_full_sample: sample = full_sample else: sample = full_sample.sample(frac=sampling_frac, random_state=sampling_seed) # create pre-reform Calculator instance if use_puf_not_cps: recs1 = Records(data=sample, gfactors=growfactors_pre) else: recs1 = Records.cps_constructor(data=sample, gfactors=growfactors_pre) policy1 = Policy(gfactors=growfactors_pre) calc1 = Calculator(policy=policy1, records=recs1, consumption=consump) while calc1.current_year < start_year: calc1.increment_year() calc1.calc_all() assert calc1.current_year == start_year # specify Behavior instance behv = Behavior() behavior_assumps = user_mods['behavior'] behv.update_behavior(behavior_assumps) # always prevent both behavioral response and growdiff response if behv.has_any_response() and growdiff_response.has_any_response(): msg = 'BOTH behavior AND growdiff_response HAVE RESPONSE' raise ValueError(msg) # optionally prevent behavioral response if behv.has_any_response() and not behavior_allowed: msg = 'A behavior RESPONSE IS NOT ALLOWED' raise ValueError(msg) # create post-reform Calculator instance if use_puf_not_cps: recs2 = Records(data=sample, gfactors=growfactors_post) else: recs2 = Records.cps_constructor(data=sample, gfactors=growfactors_post) policy2 = Policy(gfactors=growfactors_post) policy_reform = user_mods['policy'] policy2.implement_reform(policy_reform) calc2 = Calculator(policy=policy2, records=recs2, consumption=consump, behavior=behv) while calc2.current_year < start_year: calc2.increment_year() assert calc2.current_year == start_year # delete objects now embedded in calc1 and calc2 del sample del full_sample del consump del growdiff_baseline del growdiff_response del growfactors_pre del growfactors_post del behv del recs1 del recs2 del policy1 del policy2 # increment Calculator objects for year_n years and calculate for _ in range(0, year_n): calc1.increment_year() calc2.increment_year() calc1.calc_all() if calc2.behavior_has_response(): calc2 = Behavior.response(calc1, calc2) else: calc2.calc_all() # return calculated Calculator objects return (calc1, calc2)
def dropq_calculate(year_n, start_year, taxrec_df, user_mods, behavior_allowed, mask_computed): """ The dropq_calculate function assumes specified user_mods is a dictionary returned by the Calculator.read_json_parameter_files() function with an extra key:value pair that is specified as 'gdp_elasticity': {'value': <float_value>}. The function returns (calc1, calc2, mask) where calc1 is pre-reform Calculator object calculated for year_n, calc2 is post-reform Calculator object calculated for year_n, and mask is boolean array if compute_mask=True or None otherwise """ # pylint: disable=too-many-arguments,too-many-locals,too-many-statements check_user_mods(user_mods) # specify Consumption instance consump = Consumption() consump_assumptions = user_mods['consumption'] consump.update_consumption(consump_assumptions) # specify growdiff_baseline and growdiff_response growdiff_baseline = Growdiff() growdiff_response = Growdiff() growdiff_base_assumps = user_mods['growdiff_baseline'] growdiff_resp_assumps = user_mods['growdiff_response'] growdiff_baseline.update_growdiff(growdiff_base_assumps) growdiff_response.update_growdiff(growdiff_resp_assumps) # create pre-reform and post-reform Growfactors instances growfactors_pre = Growfactors() growdiff_baseline.apply_to(growfactors_pre) growfactors_post = Growfactors() growdiff_baseline.apply_to(growfactors_post) growdiff_response.apply_to(growfactors_post) # create pre-reform Calculator instance recs1 = Records(data=taxrec_df.copy(deep=True), gfactors=growfactors_pre) policy1 = Policy(gfactors=growfactors_pre) calc1 = Calculator(policy=policy1, records=recs1, consumption=consump) while calc1.current_year < start_year: calc1.increment_year() calc1.calc_all() assert calc1.current_year == start_year # optionally compute mask if mask_computed: # create pre-reform Calculator instance with extra income recs1p = Records(data=taxrec_df.copy(deep=True), gfactors=growfactors_pre) # add one dollar to total wages and salaries of each filing unit recs1p.e00200 += 1.0 # pylint: disable=no-member recs1p.e00200p += 1.0 # pylint: disable=no-member policy1p = Policy(gfactors=growfactors_pre) # create Calculator with recs1p and calculate for start_year calc1p = Calculator(policy=policy1p, records=recs1p, consumption=consump) while calc1p.current_year < start_year: calc1p.increment_year() calc1p.calc_all() assert calc1p.current_year == start_year # compute mask that shows which of the calc1 and calc1p results differ res1 = results(calc1.records) res1p = results(calc1p.records) mask = (res1.iitax != res1p.iitax) else: mask = None # specify Behavior instance behv = Behavior() behavior_assumps = user_mods['behavior'] behv.update_behavior(behavior_assumps) # always prevent both behavioral response and growdiff response if behv.has_any_response() and growdiff_response.has_any_response(): msg = 'BOTH behavior AND growdiff_response HAVE RESPONSE' raise ValueError(msg) # optionally prevent behavioral response if behv.has_any_response() and not behavior_allowed: msg = 'A behavior RESPONSE IS NOT ALLOWED' raise ValueError(msg) # create post-reform Calculator instance recs2 = Records(data=taxrec_df.copy(deep=True), gfactors=growfactors_post) policy2 = Policy(gfactors=growfactors_post) policy_reform = user_mods['policy'] policy2.implement_reform(policy_reform) calc2 = Calculator(policy=policy2, records=recs2, consumption=consump, behavior=behv) while calc2.current_year < start_year: calc2.increment_year() calc2.calc_all() assert calc2.current_year == start_year # increment Calculator objects for year_n years and calculate for _ in range(0, year_n): calc1.increment_year() calc2.increment_year() calc1.calc_all() if calc2.behavior.has_response(): calc2 = Behavior.response(calc1, calc2) else: calc2.calc_all() # return calculated Calculator objects and mask return (calc1, calc2, mask)
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_ptax, mtr0_itax, _) = calc0.mtr(variable_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_ptax, mtr1_itax, _) = calc1.mtr(variable_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_ptax, mtr0_ptax, 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_json_file_contents(tests_path, fname): """ Check contents of JSON parameter files in Tax-Calculator/taxcalc directory. """ first_year = Policy.JSON_START_YEAR last_known_year = Policy.LAST_KNOWN_YEAR # for indexed parameter values known_years = set(range(first_year, last_known_year + 1)) long_params = [ 'II_brk1', 'II_brk2', 'II_brk3', 'II_brk4', 'II_brk5', 'II_brk6', 'II_brk7', 'PT_brk1', 'PT_brk2', 'PT_brk3', 'PT_brk4', 'PT_brk5', 'PT_brk6', 'PT_brk7', 'PT_qbid_taxinc_thd', 'ALD_BusinessLosses_c', 'STD', 'II_em', 'II_em_ps', 'AMT_em', 'AMT_em_ps', 'AMT_em_pe', 'ID_ps', 'ID_AllTaxes_c' ] # for TCJA-reverting long_params long_known_years = set(range(first_year, last_known_year + 1)) long_known_years.add(2026) # check elements in each parameter sub-dictionary failures = '' with open(os.path.join(tests_path, "..", fname)) as f: allparams = json.loads(f.read()) for pname in allparams: if pname == "schema": continue # check that param contains required keys param = allparams[pname] # check that indexable and indexed are False in many files if fname != 'policy_current_law.json': assert param.get('indexable', False) is False assert param.get('indexed', False) is False # check that indexable is True when indexed is True if param.get('indexed', False) and not param.get('indexable', False): msg = 'param:<{}>; indexed={}; indexable={}' fail = msg.format(pname, param.get('indexed', False), param.get('indexable', False)) failures += fail + '\n' # check that indexable param has value_type float if param.get('indexable', False) and param['type'] != 'float': msg = 'param:<{}>; type={}; indexable={}' fail = msg.format(pname, param['type'], param.get('indexable', False)) failures += fail + '\n' # ensure that indexable is False when value_type is not real if param.get('indexable', False) and param['type'] != 'float': msg = 'param:<{}>; indexable={}; type={}' fail = msg.format(pname, param.get('indexable', False), param['value_type']) failures += fail + '\n' if fname == "consumption.json": o = Consumption() elif fname == "policy_current_law.json": o = Policy() elif fname == "growdiff.json": o = GrowDiff() param_list = [] for k in o: if k[0].isupper(): # find parameters by case of first letter param_list.append(k) for param in param_list: for y in known_years: o.set_year(y) if np.isnan(getattr(o, param)).any(): msg = 'param:<{}>; not found in year={}' fail = msg.format(param, y) failures += fail + '\n' if failures: raise ValueError(failures)
def test_consumption_default_data(): paramdata = Consumption.default_data() for param in paramdata: assert paramdata[param] == [0.0]
def test_future_update_consumption(): consump = Consumption() assert consump.current_year == consump.start_year assert consump.has_response() is False cyr = 2020 consump.set_year(cyr) consump.update_consumption({cyr: {'_MPC_e20400': [0.01]}}) assert consump.current_year == cyr assert consump.has_response() is True consump.set_year(cyr - 1) assert consump.has_response() is False # test future updates for benefits consump_ben = Consumption() assert consump_ben.current_year == consump_ben.start_year assert consump_ben.has_response() is False consump_ben.set_year(cyr) consump_ben.update_consumption({cyr: {'_BEN_vet_value': [0.95]}}) assert consump_ben.current_year == cyr assert consump_ben.has_response() is True consump_ben.set_year(cyr - 1) assert consump_ben.has_response() is False
def test_correct_but_not_recommended_Consumption_instantiation(): consump = Consumption(consumption_dict={}) assert consump
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_incorrect_Consumption_instantiation(): with pytest.raises(ValueError): consump = Consumption(consumption_dict=list()) with pytest.raises(ValueError): consump = Consumption(num_years=0)
def test_future_update_consumption(): consump = Consumption() assert consump.current_year == consump.start_year assert consump.has_response() is False cyr = 2020 consump.set_year(cyr) consump.update_consumption({'MPC_e20400': {cyr: 0.01}}) assert consump.current_year == cyr assert consump.has_response() is True consump.set_year(cyr - 1) assert consump.has_response() is False # test future updates for benefits consump_ben = Consumption() assert consump_ben.current_year == consump_ben.start_year assert consump_ben.has_response() is False consump_ben.set_year(cyr) consump_ben.update_consumption({'BEN_vet_value': {cyr: 0.95}}) assert consump_ben.current_year == cyr assert consump_ben.has_response() is True consump_ben.set_year(cyr - 1) assert consump_ben.has_response() is False
def test_future_update_consumption(): consump = Consumption() assert consump.current_year == consump.start_year assert consump.has_response() is False cyr = 2020 consump.set_year(cyr) consump.update_consumption({cyr: {'_MPC_e20400': [0.01]}}) assert consump.current_year == cyr assert consump.has_response() is True consump.set_year(cyr - 1) assert consump.has_response() is False