Пример #1
0
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
Пример #2
0
def test_incorrect_behavior_instantiation():
    with pytest.raises(ValueError):
        Behavior(start_year=2000)
    with pytest.raises(ValueError):
        Behavior(num_years=0)
    with pytest.raises(FloatingPointError):
        np.divide(1., 0.)
def test_Calculator_diagnostic_table():
    puf = Records(data=TAXDATA, weights=WEIGHTS, start_year=Records.PUF_YEAR)
    beh = Behavior()
    beh.update_behavior({2013: {'_BE_sub': [0.4]}})
    assert beh.has_response()
    calc = Calculator(policy=Policy(), records=puf, behavior=beh)
    calc.diagnostic_table(base_calc=calc)
Пример #4
0
def run_reform(name, reform, behave):

    puf = pd.read_csv("../tax-calculator/puf.csv")
    policy_base = Policy(start_year=2013)
    records_base = Records(puf)
    policy_reform = Policy()
    records_reform = Records(puf)
    bhv = Behavior()
    calcbase = Calculator(policy=policy_base, records=records_base)
    calcreform = Calculator(policy=policy_reform,
                            records=records_reform,
                            behavior=bhv)
    policy_reform.implement_reform(reform)
    calcbase.advance_to_year(CURRENT_YEAR)
    calcreform.advance_to_year(CURRENT_YEAR)
    calcbase.calc_all()
    calcreform.calc_all()
    bhv.update_behavior(behave)
    calc_behav = Behavior.response(calcbase, calcreform)
    calc_behav.calc_all()
    base_list = multiyear_diagnostic_table(calcbase, 10)
    reform_list = multiyear_diagnostic_table(calc_behav, 10)
    difflist = (reform_list.iloc[18] - base_list.iloc[18])

    return difflist
Пример #5
0
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
Пример #6
0
def test_incorrect_Behavior_instantiation():
    with pytest.raises(ValueError):
        behv = Behavior(behavior_dict=list())
    bad_behv_dict = {'_BE_bad': {'start_year': 2013, 'value': [0.0]}}
    with pytest.raises(ValueError):
        behv = Behavior(behavior_dict=bad_behv_dict)
    with pytest.raises(ValueError):
        behv = Behavior(num_years=0)
Пример #7
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', '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
Пример #8
0
def reform_warnings_errors(user_mods):
    """
    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 two STR:STR pairs:
    {'warnings': '<empty-or-message(s)>', 'errors': '<empty-or-message(s)>'}
    In each pair the second string is empty if there are no messages.
    Any returned messages are generated using current_law_policy.json
    information on known policy parameter names and parameter value ranges.

    Note that this function will return one or more error messages if
    the user_mods['policy'] dictionary contains any unknown policy
    parameter names or if any *_cpi parameters have values other than
    True or False.  These situations prevent implementing the policy
    reform specified in user_mods, and therefore, no range-related
    warnings or errors will be returned in this case.
    """
    rtn_dict = {
        'policy': {
            'warnings': '',
            'errors': ''
        },
        'behavior': {
            'warnings': '',
            'errors': ''
        }
    }
    # create Growfactors object
    gdiff_baseline = Growdiff()
    gdiff_baseline.update_growdiff(user_mods['growdiff_baseline'])
    gdiff_response = Growdiff()
    gdiff_response.update_growdiff(user_mods['growdiff_response'])
    growfactors = Growfactors()
    gdiff_baseline.apply_to(growfactors)
    gdiff_response.apply_to(growfactors)
    # create Policy object and implement reform
    pol = Policy(gfactors=growfactors)
    try:
        pol.implement_reform(user_mods['policy'],
                             print_warnings=False,
                             raise_errors=False)
        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 and implement revisions
    # Note that Behavior does not have a `parameter_warnings`
    # attribute.
    behv = Behavior()
    try:
        behv.update_behavior(user_mods['behavior'])
        rtn_dict['behavior']['errors'] = behv.parameter_errors
    except ValueError as valerr_msg:
        rtn_dict['behavior']['errors'] = valerr_msg.__str__()
    return rtn_dict
Пример #9
0
def test_future_update_behavior():
    behv = Behavior()
    assert behv.current_year == behv.start_year
    assert behv.has_response() is False
    cyr = 2020
    behv.set_year(cyr)
    behv.update_behavior({cyr: {'_BE_cg': [1.0]}})
    assert behv.current_year == cyr
    assert behv.has_response() is True
    behv.set_year(cyr - 1)
    assert behv.has_response() is False
Пример #10
0
def reform_results(reform_dict, puf_data, reform_2017_law):
    """
    Return actual results of the reform specified in reform_dict.
    """
    # pylint: disable=too-many-locals
    rec = Records(data=puf_data)
    # create baseline Calculator object, calc1
    pol = Policy()
    if reform_dict['baseline'] == '2017_law.json':
        pol.implement_reform(reform_2017_law)
    elif reform_dict['baseline'] == 'current_law_policy.json':
        pass
    else:
        msg = 'illegal baseline value {}'
        raise ValueError(msg.format(reform_dict['baseline']))
    calc1 = Calculator(policy=pol, records=rec, verbose=False, behavior=None)
    # create reform Calculator object, calc2, with possible behavioral response
    start_year = reform_dict['start_year']
    beh = Behavior()
    if '_BE_cg' in reform_dict['value']:
        elasticity = reform_dict['value']['_BE_cg']
        del reform_dict['value']['_BE_cg']  # in order to have a valid reform
        beh_assump = {start_year: {'_BE_cg': elasticity}}
        beh.update_behavior(beh_assump)
    reform = {start_year: reform_dict['value']}
    pol.implement_reform(reform)
    calc2 = Calculator(policy=pol, records=rec, verbose=False, behavior=beh)
    # increment both Calculator objects to reform's start_year
    calc1.advance_to_year(start_year)
    calc2.advance_to_year(start_year)
    # calculate prereform and postreform output for several years
    output_type = reform_dict['output_type']
    num_years = 4
    results = list()
    for _ in range(0, num_years):
        calc1.calc_all()
        prereform = calc1.array(output_type)
        if calc2.behavior_has_response():
            calc2_br = Behavior.response(calc1, calc2)
            postreform = calc2_br.array(output_type)
        else:
            calc2.calc_all()
            postreform = calc2.array(output_type)
        diff = postreform - prereform
        weighted_sum_diff = (diff * calc1.array('s006')).sum() * 1.0e-9
        results.append(weighted_sum_diff)
        calc1.increment_year()
        calc2.increment_year()
    # write actual results to actual_str
    actual_str = 'Tax-Calculator'
    for iyr in range(0, num_years):
        actual_str += ',{:.1f}'.format(results[iyr])
    return actual_str
Пример #11
0
def test_correct_update_behavior():
    beh = Behavior(start_year=2013)
    beh.update_behavior({2014: {"_BE_sub": [0.5]}, 2015: {"_BE_cg": [-1.2]}})
    should_be = np.full((Behavior.DEFAULT_NUM_YEARS,), 0.5)
    should_be[0] = 0.0
    assert np.allclose(beh._BE_sub, should_be, rtol=0.0)
    assert np.allclose(beh._BE_inc, np.zeros((Behavior.DEFAULT_NUM_YEARS,)), rtol=0.0)
    beh.set_year(2015)
    assert beh.current_year == 2015
    assert beh.BE_sub == 0.5
    assert beh.BE_inc == 0.0
    assert beh.BE_cg == -1.2
Пример #12
0
def test_multiyear_diagnostic_table(records_2009):
    behv = Behavior()
    calc = Calculator(policy=Policy(), records=records_2009, behavior=behv)
    with pytest.raises(ValueError):
        adt = multiyear_diagnostic_table(calc, 0)
    with pytest.raises(ValueError):
        adt = multiyear_diagnostic_table(calc, 20)
    adt = multiyear_diagnostic_table(calc, 3)
    assert isinstance(adt, DataFrame)
    behv.update_behavior({2013: {'_BE_sub': [0.3]}})
    assert calc.behavior.has_response()
    adt = multiyear_diagnostic_table(calc, 3)
    assert isinstance(adt, DataFrame)
Пример #13
0
def test_multiyear_diagnostic_table(records_2009):
    behv = Behavior()
    calc = Calculator(policy=Policy(), records=records_2009, behavior=behv)
    with pytest.raises(ValueError):
        adt = multiyear_diagnostic_table(calc, 0)
    with pytest.raises(ValueError):
        adt = multiyear_diagnostic_table(calc, 20)
    adt = multiyear_diagnostic_table(calc, 3)
    assert isinstance(adt, DataFrame)
    behv.update_behavior({2013: {"_BE_sub": [0.3]}})
    assert calc.behavior.has_response()
    adt = multiyear_diagnostic_table(calc, 3)
    assert isinstance(adt, DataFrame)
Пример #14
0
def reform_results(reform_dict, puf_data):
    """
    Return actual results of the reform specified in reform_dict.
    """
    # pylint: disable=too-many-locals
    # create current-law-policy Calculator object
    pol1 = Policy()
    rec1 = Records(data=puf_data)
    calc1 = Calculator(policy=pol1, records=rec1, verbose=False, behavior=None)
    # create reform Calculator object with possible behavioral responses
    start_year = reform_dict['start_year']
    beh2 = Behavior()
    if '_BE_cg' in reform_dict['value']:
        elasticity = reform_dict['value']['_BE_cg']
        del reform_dict['value']['_BE_cg']  # in order to have a valid reform
        beh_assump = {start_year: {'_BE_cg': elasticity}}
        beh2.update_behavior(beh_assump)
    reform = {start_year: reform_dict['value']}
    pol2 = Policy()
    pol2.implement_reform(reform)
    rec2 = Records(data=puf_data)
    calc2 = Calculator(policy=pol2, records=rec2, verbose=False, behavior=beh2)
    # increment both calculators to reform's start_year
    calc1.advance_to_year(start_year)
    calc2.advance_to_year(start_year)
    # calculate prereform and postreform output for several years
    output_type = reform_dict['output_type']
    num_years = 4
    results = list()
    for _ in range(0, num_years):
        calc1.calc_all()
        prereform = getattr(calc1.records, output_type)
        if calc2.behavior.has_response():
            calc_clp = calc2.current_law_version()
            calc2_br = Behavior.response(calc_clp, calc2)
            postreform = getattr(calc2_br.records, output_type)
        else:
            calc2.calc_all()
            postreform = getattr(calc2.records, output_type)
        diff = postreform - prereform
        weighted_sum_diff = (diff * calc1.records.s006).sum() * 1.0e-9
        results.append(weighted_sum_diff)
        calc1.increment_year()
        calc2.increment_year()
    # write actual results to actual_str
    reform_description = reform_dict['name']
    actual_str = '{}\n'.format(reform_description)
    actual_str += 'Tax-Calculator'
    for iyr in range(0, num_years):
        actual_str += ',{:.1f}'.format(results[iyr])
    return actual_str
Пример #15
0
def test_make_behavioral_Calculator():
    # create Records objects
    records_x = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009)
    records_y = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009)
    # create Policy objects
    policy_x = Policy()
    policy_y = Policy()
    # implement policy_y reform
    reform = {2013: {"_II_rt7": [0.496]}}
    policy_y.implement_reform(reform)
    # create two Calculator objects
    behavior_y = Behavior()
    calc_x = Calculator(policy=policy_x, records=records_x)
    calc_y = Calculator(policy=policy_y,
                        records=records_y,
                        behavior=behavior_y)
    # create behavioral calculators and vary substitution and income effects
    behavior1 = {2013: {"_BE_sub": [0.4], "_BE_inc": [0.15]}}
    behavior_y.update_behavior(behavior1)
    calc_y_behavior1 = behavior(calc_x, calc_y)
    behavior2 = {2013: {"_BE_sub": [0.5], "_BE_inc": [0.15]}}
    behavior_y.update_behavior(behavior2)
    calc_y_behavior2 = behavior(calc_x, calc_y)
    behavior3 = {2013: {"_BE_sub": [0.4], "_BE_inc": [0.0]}}
    behavior_y.update_behavior(behavior3)
    calc_y_behavior3 = behavior(calc_x, calc_y)
    # check that total income tax liability differs across the three behaviors
    assert (calc_y_behavior1.records._iitax.sum() !=
            calc_y_behavior2.records._iitax.sum() !=
            calc_y_behavior3.records._iitax.sum())
Пример #16
0
def test_update_behavior():
    beh = Behavior(start_year=2013)
    beh.update_behavior({2014: {'_BE_sub': [0.5]}})
    policy = Policy()
    should_be = np.full((Behavior.DEFAULT_NUM_YEARS,), 0.5)
    should_be[0] = 0.0
    assert np.allclose(beh._BE_sub, should_be, rtol=0.0)
    assert np.allclose(beh._BE_inc,
                       np.zeros((Behavior.DEFAULT_NUM_YEARS,)),
                       rtol=0.0)
    beh.set_year(2015)
    assert beh.current_year == 2015
    assert beh.BE_sub == 0.5
    assert beh.BE_inc == 0.0
Пример #17
0
def main(reform_year, calc_year, sub_elasticity, inc_elasticity, cg_elasticity):
    """
    Highest-level logic of behavior.py script that produces Tax-Calculator
    behavioral-response results running the taxcalc package on this computer.
    """
    # pylint: disable=too-many-locals
    # pylint: disable=protected-access
    if not os.path.isfile(PUFCSV_PATH):
        sys.stderr.write("ERROR: file {} does not exist\n".format(PUFCSV_PATH))
        return 1
    # specify policy reform
    reform_dict = {
        reform_year: {
            "_SS_Earnings_c": [1.0e99],
            "_CG_rt1": [0.01],  # clp ==> 0.00
            "_CG_rt2": [0.16],  # clp ==> 0.15
            "_CG_rt3": [0.21],
        }
    }  # clp ==> 0.20
    msg = "REFORM: pop-the-cap + cg-rate-up-one-percent in {}\n"
    sys.stdout.write(msg.format(reform_year))
    # create reform-policy object
    ref = Policy()
    ref.implement_reform(reform_dict)
    # create behavioral-response object
    behv = Behavior()
    # create reform-policy Calculator object with behavioral responses
    calc_ref = Calculator(policy=ref, verbose=False, behavior=behv, records=Records(data=PUFCSV_PATH))
    cyr = calc_year
    # (a) with all behavioral-reponse parameters set to zero
    assert not calc_ref.behavior.has_response()
    itax_s, ptax_s, ltcg_s = results(cyr, calc_ref)
    # (b) with behavioral-reponse parameters set to those specified in call
    behv_params = {
        behv.start_year: {"_BE_sub": [sub_elasticity], "_BE_inc": [inc_elasticity], "_BE_cg": [cg_elasticity]}
    }
    behv.update_behavior(behv_params)  # now used by calc_ref object
    itax_d, ptax_d, ltcg_d = results(cyr, calc_ref)  # dynamic analysis
    # write results to stdout
    bhv = "{},SUB_ELAST,INC_ELAST,CG_ELAST= {} {} {}\n"
    yridx = cyr - behv.start_year
    sys.stdout.write(bhv.format(cyr, behv._BE_sub[yridx], behv._BE_inc[yridx], behv._BE_cg[yridx]))
    res = "{},{},{}_STATIC(S),{}_DYNAMIC(D),D-S= {:.1f} {:.1f} {:.1f}\n"
    sys.stdout.write(res.format(cyr, "ITAX", "REV", "REV", itax_s, itax_d, itax_d - itax_s))
    sys.stdout.write(res.format(cyr, "PTAX", "REV", "REV", ptax_s, ptax_d, ptax_d - ptax_s))
    sys.stdout.write(res.format(cyr, "LTCG", "AGG", "AGG", ltcg_s, ltcg_d, ltcg_d - ltcg_s))
    # return no-error exit code
    return 0
Пример #18
0
def test_xtr_graph_plot(cps_subsample):
    calc = Calculator(policy=Policy(),
                      records=Records.cps_constructor(data=cps_subsample),
                      behavior=Behavior())
    mtr = 0.20 * np.ones_like(cps_subsample['e00200'])
    vdf = calc.dataframe(['s006', 'MARS', 'c00100'])
    vdf['mtr1'] = mtr
    vdf['mtr2'] = mtr
    gdata = mtr_graph_data(vdf,
                           calc.current_year,
                           mtr_measure='ptax',
                           income_measure='agi',
                           dollar_weighting=False)
    gplot = xtr_graph_plot(gdata)
    assert gplot
    vdf = calc.dataframe(['s006', 'expanded_income'])
    vdf['mtr1'] = mtr
    vdf['mtr2'] = mtr
    gdata = mtr_graph_data(vdf,
                           calc.current_year,
                           mtr_measure='itax',
                           alt_e00200p_text='Taxpayer Earnings',
                           income_measure='expanded_income',
                           dollar_weighting=False)
    assert isinstance(gdata, dict)
Пример #19
0
def test_multiyear_diagnostic_table(cps_subsample):
    rec = Records.cps_constructor(data=cps_subsample)
    pol = Policy()
    beh = Behavior()
    calc = Calculator(policy=pol, records=rec, behavior=beh)
    with pytest.raises(ValueError):
        multiyear_diagnostic_table(calc, 0)
    with pytest.raises(ValueError):
        multiyear_diagnostic_table(calc, 20)
    adt = multiyear_diagnostic_table(calc, 3)
    assert isinstance(adt, pd.DataFrame)
    beh.update_behavior({2013: {'_BE_sub': [0.3]}})
    calc = Calculator(policy=pol, records=rec, behavior=beh)
    assert calc.behavior.has_response()
    adt = multiyear_diagnostic_table(calc, 3)
    assert isinstance(adt, pd.DataFrame)
Пример #20
0
def test_validate_param_names_types_errors():
    behv0 = Behavior()
    specs0 = {2020: {'_BE_bad': [-1.0]}}
    with pytest.raises(ValueError):
        behv0.update_behavior(specs0)
    behv1 = Behavior()
    specs1 = {2019: {'_BE_inc': [True]}}
    with pytest.raises(ValueError):
        behv1.update_behavior(specs1)
Пример #21
0
def main(reform_year, calc_year, sub_elasticity, inc_elasticity):
    """
    Highest-level logic of behavior.py script that produces Tax-Calculator
    behavioral-response results running the taxcalc package on this computer.
    """
    # pylint: disable=too-many-locals
    # pylint: disable=protected-access
    if not os.path.isfile(PUFCSV_PATH):
        sys.stderr.write('ERROR: file {} does not exist\n'.format(PUFCSV_PATH))
        return 1
    # create current-law-policy object
    cur = Policy()
    # specify policy reform
    reform_dict = {reform_year: {'_SS_Earnings_c': [1.0e99]}}
    sys.stdout.write('REFORM: pop-the-cap in {}\n'.format(reform_year))
    # create reform-policy object
    ref = Policy()
    ref.implement_reform(reform_dict)
    # create behavioral-response object
    behv = Behavior()  # default object has all response parameters set to zero
    # create current-law-policy Calculator object
    calc_cur = Calculator(policy=cur, verbose=False,
                          records=Records(data=PUFCSV_PATH))
    # create reform-policy Calculator object with behavioral responses
    calc_ref = Calculator(policy=ref, verbose=False, behavior=behv,
                          records=Records(data=PUFCSV_PATH))
    # compute behavorial-reponse effect on income and fica tax revenues
    cyr = calc_year
    # (a) with all behavioral-reponse parameters set to zero
    itax_s, fica_s = revenue(cyr, calc_ref, None)  # static analysis
    itax_d, fica_d = revenue(cyr, calc_cur, calc_ref)  # dynamic analysis
    assert itax_d == itax_s
    assert fica_d == fica_s
    # (b) with both substitution- and income-effect behavioral-reponse params
    behv_params = {behv.start_year: {'_BE_sub': [sub_elasticity],
                                     '_BE_inc': [inc_elasticity]}}
    behv.update_behavior(behv_params)
    itax_s, fica_s = revenue(cyr, calc_ref, None)  # static analysis
    itax_d, fica_d = revenue(cyr, calc_cur, calc_ref)  # dynamic analysis
    bhv = '{},SUB_ELASTICITY,INC_ELASTICITY= {} {}\n'
    yridx = cyr - behv.start_year
    sys.stdout.write(bhv.format(cyr, behv._BE_sub[yridx], behv._BE_inc[yridx]))
    res = '{},{},REV_STATIC(S),REV_DYNAMIC(D),D-S= {:.1f} {:.1f} {:.1f}\n'
    sys.stdout.write(res.format(cyr, 'ITAX', itax_s, itax_d, itax_d - itax_s))
    sys.stdout.write(res.format(cyr, 'FICA', fica_s, fica_d, fica_d - fica_s))
    # return no-error exit code
    return 0
Пример #22
0
def test_incorrect_behavior_instantiation():
    with pytest.raises(ValueError):
        Behavior(behavior_dict=list())
    bad_behv_dict = {
        '_BE_bad': {'start_year': 2013, 'value': [0.0]}
    }
    with pytest.raises(ValueError):
        Behavior(behavior_dict=bad_behv_dict)
    with pytest.raises(ValueError):
        Behavior(num_years=0)
    with pytest.raises(FloatingPointError):
        np.divide(1., 0.)
    with pytest.raises(ValueError):
        Behavior(behavior_dict={})
    bad_behv_dict = {
        '_BE_subinc_wrt_earnings': {'start_year': 2013, 'value': [True]}
    }
    with pytest.raises(ValueError):
        Behavior(behavior_dict=bad_behv_dict)
    bad_behv_dict = {
        '_BE_subinc_wrt_earnings': {'start_year': 2013, 'value': [True]},
        '_BE_sub': {'start_year': 2017, 'value': [0.25]}
    }
    with pytest.raises(ValueError):
        Behavior(behavior_dict=bad_behv_dict)
    bad_behv_dict = {
        54321: {'start_year': 2013, 'value': [0.0]}
    }
    with pytest.raises(ValueError):
        Behavior(behavior_dict=bad_behv_dict)
Пример #23
0
def test_incorrect_update_behavior():
    behv = Behavior()
    with pytest.raises(ValueError):
        behv.update_behavior({2013: {'_BE_inc': [+0.2]}})
        behv.update_behavior({2013: {'_BE_sub': [-0.2]}})
        behv.update_behavior({2013: {'_BE_cg': [-0.8]}})
        behv.update_behavior({2013: {'_BE_xx': [0.0]}})
Пример #24
0
def test_multiyear_diagnostic_table_w_behv(records_2009):
    pol = Policy()
    behv = Behavior()
    calc = Calculator(policy=pol, records=records_2009, behavior=behv)
    assert calc.current_year == 2013
    reform = {2013: {"_II_rt7": [0.33], "_PT_rt7": [0.33]}}
    pol.implement_reform(reform)
    reform_be = {2013: {"_BE_sub": [0.4], "_BE_cg": [-3.67]}}
    behv.update_behavior(reform_be)
    calc_clp = calc.current_law_version()
    calc_behv = Behavior.response(calc_clp, calc)
    calc_behv.calc_all()
    liabilities_x = (calc_behv.records._combined * calc_behv.records.s006).sum()
    adt = multiyear_diagnostic_table(calc_behv, 1)
    # extract combined liabilities as a float and
    # adopt units of the raw calculator data in liabilities_x
    liabilities_y = adt.iloc[18].tolist()[0] * 1000000000
    npt.assert_almost_equal(liabilities_x, liabilities_y, 2)
Пример #25
0
def test_xtr_graph_plot_no_bokeh(records_2009):
    import taxcalc
    taxcalc.utils.BOKEH_AVAILABLE = False
    calc = Calculator(policy=Policy(),
                      records=records_2009,
                      behavior=Behavior())
    gdata = mtr_graph_data(calc, calc)
    with pytest.raises(RuntimeError):
        gplot = xtr_graph_plot(gdata)
    taxcalc.utils.BOKEH_AVAILABLE = True
Пример #26
0
def test_behavioral_response_Calculator():
    # create Records objects
    records_x = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009)
    records_y = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009)
    # create Policy objects
    policy_x = Policy()
    policy_y = Policy()
    # implement policy_y reform
    reform = {
        2013: {
            "_II_rt7": [0.496]
        }
    }
    policy_y.implement_reform(reform)
    # create two Calculator objects
    behavior_y = Behavior()
    calc_x = Calculator(policy=policy_x, records=records_x)
    calc_y = Calculator(policy=policy_y, records=records_y,
                        behavior=behavior_y)
    # vary substitution and income effects in calc_y
    behavior1 = {
        2013: {
            "_BE_sub": [0.4],
            "_BE_inc": [-0.15]
        }
    }
    behavior_y.update_behavior(behavior1)
    assert behavior_y.has_response()
    assert behavior_y.BE_sub == 0.4
    assert behavior_y.BE_inc == -0.15
    calc_y_behavior1 = calc_y.behavior.response(calc_x, calc_y)
    behavior2 = {
        2013: {
            "_BE_sub": [0.5],
            "_BE_inc": [-0.15]
        }
    }
    behavior_y.update_behavior(behavior2)
    calc_y_behavior2 = calc_y.behavior.response(calc_x, calc_y)
    behavior3 = {
        2013: {
            "_BE_sub": [0.4],
            "_BE_inc": [0.0]
        }
    }
    behavior_y.update_behavior(behavior3)
    calc_y_behavior3 = calc_y.behavior.response(calc_x, calc_y)
    # check that total income tax liability differs across the
    # three sets of behavioral-response elasticities
    assert (calc_y_behavior1.records._iitax.sum() !=
            calc_y_behavior2.records._iitax.sum() !=
            calc_y_behavior3.records._iitax.sum())
Пример #27
0
def test_myr_diag_table_w_behv(cps_subsample):
    pol = Policy()
    rec = Records.cps_constructor(data=cps_subsample)
    year = rec.current_year
    beh = Behavior()
    calc = Calculator(policy=pol, records=rec, behavior=beh)
    assert calc.current_year == year
    reform = {year: {'_II_rt7': [0.33], '_PT_rt7': [0.33]}}
    pol.implement_reform(reform)
    reform_behav = {year: {'_BE_sub': [0.4], '_BE_cg': [-3.67]}}
    beh.update_behavior(reform_behav)
    calc_clp = calc.current_law_version()
    calc_beh = Behavior.response(calc_clp, calc)
    calc_beh.calc_all()
    liabilities_x = (calc_beh.records.combined * calc_beh.records.s006).sum()
    adt = multiyear_diagnostic_table(calc_beh, 1)
    # extract combined liabilities as a float and
    # adopt units of the raw calculator data in liabilities_x
    liabilities_y = adt.iloc[19].tolist()[0] * 1e9
    assert np.allclose(liabilities_x, liabilities_y, atol=0.01, rtol=0.0)
Пример #28
0
def only_behavior_assumptions(user_mods, start_year):
    """
    Extract any reform parameters that are pertinent to behavior
    assumptions
    """
    beh_dd = Behavior.default_data(start_year=start_year)
    ba = {}
    for year, reforms in user_mods.items():
        overlap = set(beh_dd.keys()) & set(reforms.keys())
        if overlap:
            ba[year] = {param:reforms[param] for param in overlap}
    return ba
Пример #29
0
def test_correct_update_behavior():
    beh = Behavior(start_year=2013)
    beh.update_behavior({
        2014: {
            '_BE_sub': [0.5]
        },
        2015: {
            '_BE_cg': [-1.2]
        },
        2016: {
            '_BE_charity': [[-0.5, -0.5, -0.5]]
        }
    })
    should_be = np.full((Behavior.DEFAULT_NUM_YEARS, ), 0.5)
    should_be[0] = 0.0
    assert np.allclose(beh._BE_sub, should_be, rtol=0.0)
    assert np.allclose(beh._BE_inc,
                       np.zeros((Behavior.DEFAULT_NUM_YEARS, )),
                       rtol=0.0)
    beh.set_year(2017)
    assert beh.current_year == 2017
    assert beh.BE_sub == 0.5
    assert beh.BE_inc == 0.0
    assert beh.BE_cg == -1.2
    assert beh.BE_charity.tolist() == [-0.5, -0.5, -0.5]
Пример #30
0
def test_myr_diag_table_w_behv(records_2009):
    pol = Policy()
    behv = Behavior()
    calc = Calculator(policy=pol, records=records_2009, behavior=behv)
    assert calc.current_year == 2013
    reform = {
        2013: {
            '_II_rt7': [0.33],
            '_PT_rt7': [0.33],
        }
    }
    pol.implement_reform(reform)
    reform_be = {2013: {'_BE_sub': [0.4], '_BE_cg': [-3.67]}}
    behv.update_behavior(reform_be)
    calc_clp = calc.current_law_version()
    calc_behv = Behavior.response(calc_clp, calc)
    calc_behv.calc_all()
    liabilities_x = (calc_behv.records.combined * calc_behv.records.s006).sum()
    adt = multiyear_diagnostic_table(calc_behv, 1)
    # extract combined liabilities as a float and
    # adopt units of the raw calculator data in liabilities_x
    liabilities_y = adt.iloc[19].tolist()[0] * 1000000000
    assert_almost_equal(liabilities_x, liabilities_y, 2)
Пример #31
0
def test_incorrect_update_behavior():
    with pytest.raises(ValueError):
        Behavior().update_behavior({2013: {'_BE_inc': [+0.2]}})
    with pytest.raises(ValueError):
        Behavior().update_behavior({2013: {'_BE_sub': [-0.2]}})
    with pytest.raises(ValueError):
        Behavior().update_behavior({2017: {'_BE_subinc_wrt_earnings': [2]}})
    with pytest.raises(ValueError):
        Behavior().update_behavior({2020: {'_BE_subinc_wrt_earnings': [True]}})
    with pytest.raises(ValueError):
        Behavior().update_behavior({2013: {'_BE_charity': [[0.2, -0.2, 0.2]]}})
    with pytest.raises(ValueError):
        Behavior().update_behavior({2013: {'_BE_cg': [+0.8]}})
    with pytest.raises(ValueError):
        Behavior().update_behavior({2013: {'_BE_xx': [0.0]}})
    with pytest.raises(ValueError):
        Behavior().update_behavior({2013: {'_BE_xx_cpi': [True]}})
Пример #32
0
def test_xtr_graph_plot(records_2009):
    calc = Calculator(policy=Policy(),
                      records=records_2009,
                      behavior=Behavior())
    gdata = mtr_graph_data(calc,
                           calc,
                           mtr_measure='ptax',
                           income_measure='agi',
                           dollar_weighting=False)
    gplot = xtr_graph_plot(gdata)
    assert gplot
    gdata = mtr_graph_data(calc,
                           calc,
                           mtr_measure='itax',
                           income_measure='expanded_income',
                           dollar_weighting=False)
    assert type(gdata) == dict
Пример #33
0
def only_reform_mods(user_mods, start_year):
    """
    Extract parameters that are just for policy reforms
    """
    pol_refs = {}
    beh_dd = Behavior.default_data(start_year=start_year)
    growth_dd = taxcalc.growth.Growth.default_data(start_year=start_year)
    policy_dd = taxcalc.policy.Policy.default_data(start_year=start_year)
    for year, reforms in user_mods.items():
        all_cpis = {p for p in reforms.keys() if p.endswith("_cpi") and
                    p[:-4] in policy_dd.keys()}
        pols = set(reforms.keys()) - set(beh_dd.keys()) - set(growth_dd.keys())
        pols &= set(policy_dd.keys())
        pols ^= all_cpis
        if pols:
            pol_refs[year] = {param:reforms[param] for param in pols}
    return pol_refs
def test_make_behavioral_Calculator():
    # create Records objects
    records_x = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009)
    records_y = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009)
    # create Policy objects
    policy_x = Policy()
    policy_y = Policy()
    # implement policy_y reform
    reform = {
        2013: {
            "_II_rt7": [0.496]
        }
    }
    policy_y.implement_reform(reform)
    # create two Calculator objects
    behavior_y = Behavior()
    calc_x = Calculator(policy=policy_x, records=records_x)
    calc_y = Calculator(policy=policy_y, records=records_y,
                        behavior=behavior_y)
    # create behavioral calculators and vary substitution and income effects
    behavior1 = {
        2013: {
            "_BE_sub": [0.4],
            "_BE_inc": [0.15]
        }
    }
    behavior_y.update_behavior(behavior1)
    calc_y_behavior1 = behavior(calc_x, calc_y)
    behavior2 = {
        2013: {
            "_BE_sub": [0.5],
            "_BE_inc": [0.15]
        }
    }
    behavior_y.update_behavior(behavior2)
    calc_y_behavior2 = behavior(calc_x, calc_y)
    behavior3 = {
        2013: {
            "_BE_sub": [0.4],
            "_BE_inc": [0.0]
        }
    }
    behavior_y.update_behavior(behavior3)
    calc_y_behavior3 = behavior(calc_x, calc_y)
    # check that total income tax liability differs across the three behaviors
    assert (calc_y_behavior1.records._iitax.sum() !=
            calc_y_behavior2.records._iitax.sum() !=
            calc_y_behavior3.records._iitax.sum())
Пример #35
0
def test_xtr_graph_plot(cps_subsample):
    calc = Calculator(policy=Policy(),
                      records=Records.cps_constructor(data=cps_subsample),
                      behavior=Behavior())
    gdata = mtr_graph_data(calc,
                           calc,
                           mtr_measure='ptax',
                           income_measure='agi',
                           dollar_weighting=False)
    gplot = xtr_graph_plot(gdata)
    assert gplot
    gdata = mtr_graph_data(calc,
                           calc,
                           mtr_measure='itax',
                           alt_e00200p_text='Taxpayer Earnings',
                           income_measure='expanded_income',
                           dollar_weighting=False)
    assert isinstance(gdata, dict)
Пример #36
0
def results(year, calc):
    """
    Return aggregate, weighted income and payroll tax revenue (in billions).
    """
    calc.advance_to_year(year)
    if calc.behavior.has_response():
        calc_clp = calc.current_law_version()
        calc_br = Behavior.response(calc_clp, calc)
        # pylint: disable=protected-access
        itax_rev = (calc_br.records._iitax * calc.records.s006).sum()
        ptax_rev = (calc_br.records._payrolltax * calc.records.s006).sum()
        ltcg_amt = (calc_br.records.p23250 * calc.records.s006).sum()
    else:
        calc.calc_all()
        # pylint: disable=protected-access
        itax_rev = (calc.records._iitax * calc.records.s006).sum()
        ptax_rev = (calc.records._payrolltax * calc.records.s006).sum()
        ltcg_amt = (calc.records.p23250 * calc.records.s006).sum()
    return (round(itax_rev * 1.0e-9, 3), round(ptax_rev * 1.0e-9, 3), round(ltcg_amt * 1.0e-9, 3))
Пример #37
0
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())
Пример #38
0
def results(year, calc):
    """
    Return aggregate, weighted income and payroll tax revenue (in billions).
    """
    calc.advance_to_year(year)
    if calc.behavior.has_response():
        calc_clp = calc.current_law_version()
        calc_br = Behavior.response(calc_clp, calc)
        # pylint: disable=protected-access
        itax_rev = (calc_br.records._iitax * calc.records.s006).sum()
        ptax_rev = (calc_br.records._payrolltax * calc.records.s006).sum()
        ltcg_amt = (calc_br.records.p23250 * calc.records.s006).sum()
    else:
        calc.calc_all()
        # pylint: disable=protected-access
        itax_rev = (calc.records._iitax * calc.records.s006).sum()
        ptax_rev = (calc.records._payrolltax * calc.records.s006).sum()
        ltcg_amt = (calc.records.p23250 * calc.records.s006).sum()
    return (round(itax_rev * 1.0e-9, 3), round(ptax_rev * 1.0e-9,
                                               3), round(ltcg_amt * 1.0e-9, 3))
Пример #39
0
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())
Пример #40
0
def get_unknown_parameters(user_mods, start_year):
    """
    Extract parameters that are just for policy reforms
    """
    pol_refs = {}
    beh_dd = Behavior.default_data(start_year=start_year)
    growth_dd = taxcalc.growth.Growth.default_data(start_year=start_year)
    policy_dd = taxcalc.policy.Policy.default_data(start_year=start_year)
    unknown_params = []
    for year, reforms in user_mods.items():
        everything = set(reforms.keys())
        all_cpis = {p for p in reforms.keys() if p.endswith("_cpi")}
        all_good_cpis = {p for p in reforms.keys() if p.endswith("_cpi") and
                         p[:-4] in policy_dd.keys()}
        bad_cpis = all_cpis - all_good_cpis
        remaining = everything - all_cpis
        if bad_cpis:
            unknown_params += list(bad_cpis)
        pols = (remaining - set(beh_dd.keys()) - set(growth_dd.keys()) -
                set(policy_dd.keys()))
        if pols:
            unknown_params += list(pols)

    return unknown_params
Пример #41
0
def test_update_behavior():
    beh = Behavior(start_year=2013)
    beh.update_behavior({
        2014: {
            '_BE_sub': [0.5]
        },
        2015: {
            '_BE_CG_per': [1.2]
        }
    })
    policy = Policy()
    should_be = np.full((Behavior.DEFAULT_NUM_YEARS, ), 0.5)
    should_be[0] = 0.0
    assert np.allclose(beh._BE_sub, should_be, rtol=0.0)
    assert np.allclose(beh._BE_inc,
                       np.zeros((Behavior.DEFAULT_NUM_YEARS, )),
                       rtol=0.0)
    beh.set_year(2015)
    assert beh.current_year == 2015
    assert beh.BE_sub == 0.5
    assert beh.BE_inc == 0.0
    assert beh.BE_CG_per == 1.2
Пример #42
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)
Пример #43
0
def test_behavioral_response(use_puf_not_cps, puf_subsample, cps_fullsample):
    """
    Test that behavioral-response results are the same
    when generated from standard Tax-Calculator calls and
    when generated from tbi.run_nth_year_taxcalc_model() calls
    """
    # specify reform and assumptions
    reform_json = """
    {"policy": {
        "_II_rt5": {"2020": [0.25]},
        "_II_rt6": {"2020": [0.25]},
        "_II_rt7": {"2020": [0.25]},
        "_PT_rt5": {"2020": [0.25]},
        "_PT_rt6": {"2020": [0.25]},
        "_PT_rt7": {"2020": [0.25]},
        "_II_em": {"2020": [1000]}
    }}
    """
    assump_json = """
    {"behavior": {"_BE_sub": {"2013": [0.25]}},
     "growdiff_baseline": {},
     "growdiff_response": {},
     "consumption": {},
     "growmodel": {}
    }
    """
    params = Calculator.read_json_param_objects(reform_json, assump_json)
    # specify keyword arguments used in tbi function call
    kwargs = {
        'start_year': 2019,
        'year_n': 0,
        'use_puf_not_cps': use_puf_not_cps,
        'use_full_sample': False,
        'user_mods': {
            'policy': params['policy'],
            'behavior': params['behavior'],
            'growdiff_baseline': params['growdiff_baseline'],
            'growdiff_response': params['growdiff_response'],
            'consumption': params['consumption'],
            'growmodel': params['growmodel']
        },
        'return_dict': False
    }
    # generate aggregate results two ways: using tbi and standard calls
    num_years = 9
    std_res = dict()
    tbi_res = dict()
    if use_puf_not_cps:
        rec = Records(data=puf_subsample)
    else:
        # IMPORTANT: must use same subsample as used in test_cpscsv.py because
        #            that is the subsample used by run_nth_year_taxcalc_model
        std_cps_subsample = cps_fullsample.sample(frac=0.03, random_state=180)
        rec = Records.cps_constructor(data=std_cps_subsample)
    for using_tbi in [True, False]:
        for year in range(0, num_years):
            cyr = year + kwargs['start_year']
            if using_tbi:
                kwargs['year_n'] = year
                tables = run_nth_year_taxcalc_model(**kwargs)
                tbi_res[cyr] = dict()
                for tbl in ['aggr_1', 'aggr_2', 'aggr_d']:
                    tbi_res[cyr][tbl] = tables[tbl]
            else:
                pol = Policy()
                calc1 = Calculator(policy=pol, records=rec)
                pol.implement_reform(params['policy'])
                assert not pol.parameter_errors
                beh = Behavior()
                beh.update_behavior(params['behavior'])
                calc2 = Calculator(policy=pol, records=rec, behavior=beh)
                assert calc2.behavior_has_response()
                calc1.advance_to_year(cyr)
                calc2.advance_to_year(cyr)
                calc2 = Behavior.response(calc1, calc2)
                std_res[cyr] = dict()
                for tbl in ['aggr_1', 'aggr_2', 'aggr_d']:
                    if tbl.endswith('_1'):
                        itax = calc1.weighted_total('iitax')
                        ptax = calc1.weighted_total('payrolltax')
                        ctax = calc1.weighted_total('combined')
                    elif tbl.endswith('_2'):
                        itax = calc2.weighted_total('iitax')
                        ptax = calc2.weighted_total('payrolltax')
                        ctax = calc2.weighted_total('combined')
                    elif tbl.endswith('_d'):
                        itax = (calc2.weighted_total('iitax') -
                                calc1.weighted_total('iitax'))
                        ptax = (calc2.weighted_total('payrolltax') -
                                calc1.weighted_total('payrolltax'))
                        ctax = (calc2.weighted_total('combined') -
                                calc1.weighted_total('combined'))
                    cols = ['0_{}'.format(year)]
                    rows = ['ind_tax', 'payroll_tax', 'combined_tax']
                    datalist = [itax, ptax, ctax]
                    std_res[cyr][tbl] = pd.DataFrame(data=datalist,
                                                     index=rows,
                                                     columns=cols)
                    for col in std_res[cyr][tbl].columns:
                        val = std_res[cyr][tbl][col] * 1e-9
                        std_res[cyr][tbl][col] = round(val, 3)

    # compare the two sets of results
    # NOTE that the PUF tbi results have been "fuzzed" for privacy reasons,
    #      so there is no expectation that those results should be identical.
    no_diffs = True
    cps_dump = False  # setting to True produces dump output and test failure
    if use_puf_not_cps:
        reltol = 0.004  # std and tbi differ if more than 0.4 percent different
        dataset = 'PUF'
        dumping = False
    else:  # CPS results are not "fuzzed", so
        reltol = 1e-9  # std and tbi should be virtually identical
        dataset = 'CPS'
        dumping = cps_dump
    for year in range(0, num_years):
        cyr = year + kwargs['start_year']
        do_dump = bool(dumping and cyr >= 2019 and cyr <= 2020)
        col = '0_{}'.format(year)
        for tbl in ['aggr_1', 'aggr_2', 'aggr_d']:
            tbi = tbi_res[cyr][tbl][col]
            if do_dump:
                txt = 'DUMP of {} {} table for year {}:'
                print(txt.format(dataset, tbl, cyr))
                print(tbi)
            std = std_res[cyr][tbl][col]
            if not np.allclose(tbi, std, atol=0.0, rtol=reltol):
                no_diffs = False
                txt = '***** {} diff in {} table for year {} (year_n={}):'
                print(txt.format(dataset, tbl, cyr, year))
                print('TBI RESULTS:')
                print(tbi)
                print('STD RESULTS:')
                print(std)
    assert no_diffs
    assert not dumping
def test_behavior_default_data():
    paramdata = Behavior.default_data()
    assert paramdata['_BE_sub'] == [0.0]
Пример #45
0
def test_incorrect_update_behavior():
    behv = Behavior()
    with pytest.raises(ValueError):
        behv.update_behavior({2013: {'_BE_inc': [+0.2]}})
    with pytest.raises(ValueError):
        behv.update_behavior({2013: {'_BE_sub': [-0.2]}})
    with pytest.raises(ValueError):
        behv.update_behavior({2013: {'_BE_cg': [+0.8]}})
    with pytest.raises(ValueError):
        behv.update_behavior({2013: {'_BE_xx': [0.0]}})
    with pytest.raises(ValueError):
        behv.update_behavior({2013: {'_BE_xx_cpi': [True]}})
Пример #46
0
def run_nth_year(year_n, start_year, is_strict, tax_dta="", user_mods="", return_json=True):


    #########################################################################
    #   Create Calculators and Masks
    #########################################################################
    records = Records(tax_dta.copy(deep=True))
    records2 = copy.deepcopy(records)
    records3 = copy.deepcopy(records)
    # add 1 dollar to gross income
    records2.e00200 += 1
    # Default Plans
    # Create a default Policy object
    params = Policy(start_year=2013)
    # Create a Calculator
    calc1 = Calculator(policy=params, records=records)

    if is_strict:
        unknown_params = get_unknown_parameters(user_mods, start_year)
        if unknown_params:
            raise ValueError("Unknown parameters: {}".format(unknown_params))

    growth_assumptions = only_growth_assumptions(user_mods, start_year)
    if growth_assumptions:
        calc1.growth.update_economic_growth(growth_assumptions)

    while calc1.current_year < start_year:
        calc1.increment_year()
    calc1.calc_all()
    assert calc1.current_year == start_year

    params2 = Policy(start_year=2013)
    # Create a Calculator with one extra dollar of income
    calc2 = Calculator(policy=params2, records=records2)
    if growth_assumptions:
        calc2.growth.update_economic_growth(growth_assumptions)

    while calc2.current_year < start_year:
        calc2.increment_year()
    calc2.calc_all()
    assert calc2.current_year == start_year

    # where do the results differ..
    soit1 = results(calc1)
    soit2 = results(calc2)
    mask = (soit1._iitax != soit2._iitax)

    # User specified Plans
    behavior_assumptions = only_behavior_assumptions(user_mods, start_year)

    reform_mods = only_reform_mods(user_mods, start_year)

    params3 = Policy(start_year=2013)
    params3.implement_reform(reform_mods)

    behavior3 = Behavior(start_year=2013)
    # Create a Calculator for the user specified plan
    calc3 = Calculator(policy=params3, records=records3, behavior=behavior3)
    if growth_assumptions:
        calc3.growth.update_economic_growth(growth_assumptions)

    if behavior_assumptions:
        calc3.behavior.update_behavior(behavior_assumptions)

    while calc3.current_year < start_year:
        calc3.increment_year()
    assert calc3.current_year == start_year

    calc3.calc_all()
    # Get a random seed based on user specified plan
    seed = random_seed_from_plan(calc3)
    np.random.seed(seed)

    start_time = time.time()
    for i in range(0, year_n):
        calc1.increment_year()
        calc3.increment_year()

    calc1.calc_all()
    if calc3.behavior.has_response():
        calc3 = Behavior.response(calc1, calc3)
    else:
        calc3.calc_all()
    soit1 = results(calc1)
    soit3 = results(calc3)
    # Means of plan Y by decile
    # diffs of plan Y by decile
    # Means of plan Y by income bin
    # diffs of plan Y by income bin
    mY_dec, mX_dec, df_dec, pdf_dec, cdf_dec, mY_bin, mX_bin, df_bin, \
        pdf_bin, cdf_bin, diff_sum, payrolltax_diff_sum, combined_diff_sum = \
        groupby_means_and_comparisons(soit1, soit3, mask)

    elapsed_time = time.time() - start_time
    print("elapsed time for this run: ", elapsed_time)
    start_year += 1

    #num_fiscal_year_total = format_print(diff_sum)
    #fica_fiscal_year_total = format_print(payrolltax_diff_sum)
    #combined_fiscal_year_total = format_print(combined_diff_sum)
    tots = [diff_sum, payrolltax_diff_sum, combined_diff_sum]
    fiscal_tots= pd.DataFrame(data=tots, index=total_row_names)

    # Get rid of negative incomes
    df_bin.drop(df_bin.index[0], inplace=True)
    pdf_bin.drop(pdf_bin.index[0], inplace=True)
    cdf_bin.drop(cdf_bin.index[0], inplace=True)
    mY_bin.drop(mY_bin.index[0], inplace=True)
    mX_bin.drop(mX_bin.index[0], inplace=True)

    if not return_json:
        return (mY_dec, mX_dec, df_dec, pdf_dec, cdf_dec, mY_bin, mX_bin,
                df_bin, pdf_bin, cdf_bin, fiscal_tots)


    decile_row_names_i = [x+'_'+str(year_n) for x in decile_row_names]

    bin_row_names_i = [x+'_'+str(year_n) for x in bin_row_names]

    total_row_names_i = [x+'_'+str(year_n) for x in total_row_names]

    mY_dec_table_i = create_json_table(mY_dec,
                                        row_names=decile_row_names_i,
                                        column_types=planY_column_types)
    mX_dec_table_i = create_json_table(mX_dec,
                                        row_names=decile_row_names_i,
                                        column_types=planY_column_types)
    df_dec_table_i = create_json_table(df_dec,
                                        row_names=decile_row_names_i,
                                        column_types=diff_column_types)

    pdf_dec_table_i = create_json_table(pdf_dec,
                                        row_names=decile_row_names_i,
                                        column_types=diff_column_types)

    cdf_dec_table_i = create_json_table(cdf_dec,
                                        row_names=decile_row_names_i,
                                        column_types=diff_column_types)

    mY_bin_table_i = create_json_table(mY_bin,
                                        row_names=bin_row_names_i,
                                        column_types=planY_column_types)
    mX_bin_table_i = create_json_table(mX_bin,
                                        row_names=bin_row_names_i,
                                        column_types=planY_column_types)

    df_bin_table_i = create_json_table(df_bin,
                                        row_names=bin_row_names_i,
                                        column_types=diff_column_types)

    pdf_bin_table_i = create_json_table(pdf_bin,
                                        row_names=bin_row_names_i,
                                        column_types=diff_column_types)

    cdf_bin_table_i = create_json_table(cdf_bin,
                                        row_names=bin_row_names_i,
                                        column_types=diff_column_types)

    fiscal_yr_total = create_json_table(fiscal_tots, row_names=total_row_names_i)
    # Make the one-item lists of strings just strings
    fiscal_yr_total = dict((k, v[0]) for k,v in fiscal_yr_total.items())

    return (mY_dec_table_i, mX_dec_table_i, df_dec_table_i, pdf_dec_table_i,
            cdf_dec_table_i, mY_bin_table_i, mX_bin_table_i, df_bin_table_i,
            pdf_bin_table_i, cdf_bin_table_i, fiscal_yr_total)
Пример #47
0
# create a dictionary of all reform results
RESULTS = {}

# analyze one reform a time, simulating each reform for four years
NUM_YEARS = 4
for i in range(1, NUM_REFORMS + 1):
    # create current-law-policy calculator
    pol1 = Policy()
    rec1 = Records(data=PUF_DATA)
    calc1 = Calculator(policy=pol1, records=rec1, verbose=False, behavior=None)

    # create reform calculator with possible behavioral responses
    this_reform = "r" + str(i)
    start_year = REFORMS_JSON.get(this_reform).get("start_year")
    beh2 = Behavior()
    if "_BE_cg" in REFORMS_JSON.get(this_reform).get("value"):
        elasticity = REFORMS_JSON[this_reform]["value"]["_BE_cg"]
        del REFORMS_JSON[this_reform]["value"]["_BE_cg"]  # to not break reform
        beh_assump = {start_year: {"_BE_cg": elasticity}}
        beh2.update_behavior(beh_assump)
    reform = {start_year: REFORMS_JSON.get(this_reform).get("value")}
    pol2 = Policy()
    pol2.implement_reform(reform)
    rec2 = Records(data=PUF_DATA)
    calc2 = Calculator(policy=pol2, records=rec2, verbose=False, behavior=beh2)
    output_type = REFORMS_JSON.get(this_reform).get("output_type")
    reform_name = REFORMS_JSON.get(this_reform).get("name")

    # increment both calculators to reform's start_year
    calc1.advance_to_year(start_year)
Пример #48
0
def test_incorrect_update_behavior():
    behv = Behavior()
    with pytest.raises(ValueError):
        behv.update_behavior({2013: {"_BE_inc": [+0.2]}})
    with pytest.raises(ValueError):
        behv.update_behavior({2013: {"_BE_sub": [-0.2]}})
    with pytest.raises(ValueError):
        behv.update_behavior({2013: {"_BE_cg": [+0.8]}})
    with pytest.raises(ValueError):
        behv.update_behavior({2013: {"_BE_xx": [0.0]}})
    with pytest.raises(ValueError):
        behv.update_behavior({2013: {"_BE_xx_cpi": [True]}})
def test_behavioral_response_Calculator():
    # create Records objects
    records_x = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009)
    records_y = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009)
    # create Policy objects
    policy_x = Policy()
    policy_y = Policy()
    # implement policy_y reform
    reform = {2013: {'_II_rt7': [0.496]}}
    policy_y.implement_reform(reform)
    # create two Calculator objects
    behavior_y = Behavior()
    calc_x = Calculator(policy=policy_x, records=records_x)
    calc_y = Calculator(policy=policy_y, records=records_y,
                        behavior=behavior_y)
    # test incorrect use of Behavior._mtr_xy method
    with pytest.raises(ValueError):
        behv = Behavior._mtr_xy(calc_x, calc_y,
                                mtr_of='e00200p',
                                tax_type='nonsense')
    # vary substitution and income effects in calc_y
    behavior1 = {2013: {'_BE_sub': [0.4], '_BE_inc': [-0.1]}}
    behavior_y.update_behavior(behavior1)
    assert behavior_y.has_response() is True
    assert behavior_y.BE_sub == 0.4
    assert behavior_y.BE_inc == -0.1
    calc_y_behavior1 = Behavior.response(calc_x, calc_y)
    behavior2 = {2013: {'_BE_sub': [0.5], '_BE_cg': [0.8]}}
    behavior_y.update_behavior(behavior2)
    calc_y_behavior2 = Behavior.response(calc_x, calc_y)
    behavior3 = {2013: {'_BE_inc': [-0.2], '_BE_cg': [0.6]}}
    behavior_y.update_behavior(behavior3)
    calc_y_behavior3 = Behavior.response(calc_x, calc_y)
    # check that total income tax liability differs across the
    # three sets of behavioral-response elasticities
    assert (calc_y_behavior1.records._iitax.sum() !=
            calc_y_behavior2.records._iitax.sum() !=
            calc_y_behavior3.records._iitax.sum())
    # test incorrect _mtr_xy() usage
    with pytest.raises(ValueError):
        Behavior._mtr_xy(calc_x, calc_y, mtr_of='e00200p', tax_type='?')
Пример #50
0
def test_behavioral_response_Calculator(puf_1991, weights_1991):
    # create Records objects
    records_x = Records(data=puf_1991, weights=weights_1991, start_year=2009)
    records_y = Records(data=puf_1991, weights=weights_1991, start_year=2009)
    # create Policy objects
    policy_x = Policy()
    policy_y = Policy()
    # implement policy_y reform
    reform = {2013: {"_II_rt7": [0.496], "_PT_rt7": [0.496]}}
    policy_y.implement_reform(reform)
    # create two Calculator objects
    behavior_y = Behavior()
    calc_x = Calculator(policy=policy_x, records=records_x)
    calc_y = Calculator(policy=policy_y, records=records_y, behavior=behavior_y)
    # test incorrect use of Behavior._mtr_xy method
    with pytest.raises(ValueError):
        behv = Behavior._mtr_xy(calc_x, calc_y, mtr_of="e00200p", tax_type="nonsense")
    # vary substitution and income effects in calc_y
    behavior1 = {2013: {"_BE_sub": [0.3], "_BE_cg": [0.0]}}
    behavior_y.update_behavior(behavior1)
    assert behavior_y.has_response() is True
    assert behavior_y.BE_sub == 0.3
    assert behavior_y.BE_inc == 0.0
    assert behavior_y.BE_cg == 0.0
    calc_y_behavior1 = Behavior.response(calc_x, calc_y)
    behavior2 = {2013: {"_BE_sub": [0.5], "_BE_cg": [-0.8]}}
    behavior_y.update_behavior(behavior2)
    calc_y_behavior2 = Behavior.response(calc_x, calc_y)
    behavior3 = {2013: {"_BE_inc": [-0.2], "_BE_cg": [-0.8]}}
    behavior_y.update_behavior(behavior3)
    calc_y_behavior3 = Behavior.response(calc_x, calc_y)
    behavior4 = {2013: {"_BE_cg": [-0.8]}}
    behavior_y.update_behavior(behavior4)
    calc_y_behavior4 = Behavior.response(calc_x, calc_y)
    # check that total income tax liability differs across the
    # four sets of behavioral-response elasticities
    assert (
        calc_y_behavior1.records._iitax.sum()
        != calc_y_behavior2.records._iitax.sum()
        != calc_y_behavior3.records._iitax.sum()
        != calc_y_behavior4.records._iitax.sum()
    )
    # test incorrect _mtr_xy() usage
    with pytest.raises(ValueError):
        Behavior._mtr_xy(calc_x, calc_y, mtr_of="e00200p", tax_type="?")
Пример #51
0
def test_behavior_default_data():
    paramdata = Behavior.default_data()
    assert paramdata["_BE_inc"] == [0.0]
    assert paramdata["_BE_sub"] == [0.0]
    assert paramdata["_BE_cg"] == [0.0]
Пример #52
0
def test_behavioral_response_Calculator(puf_1991, weights_1991):
    # create Records objects
    records_x = Records(data=puf_1991, weights=weights_1991, start_year=2009)
    records_y = Records(data=puf_1991, weights=weights_1991, start_year=2009)
    # create Policy objects
    policy_x = Policy()
    policy_y = Policy()
    # implement policy_y reform
    reform = {2013: {'_II_rt7': [0.496], '_PT_rt7': [0.496]}}
    policy_y.implement_reform(reform)
    # create two Calculator objects
    behavior_y = Behavior()
    calc_x = Calculator(policy=policy_x, records=records_x)
    calc_y = Calculator(policy=policy_y,
                        records=records_y,
                        behavior=behavior_y)
    # test incorrect use of Behavior._mtr_xy method
    with pytest.raises(ValueError):
        behv = Behavior._mtr_xy(calc_x,
                                calc_y,
                                mtr_of='e00200p',
                                tax_type='nonsense')
    # vary substitution and income effects in calc_y
    behavior1 = {2013: {'_BE_sub': [0.3], '_BE_cg': [0.0]}}
    behavior_y.update_behavior(behavior1)
    assert behavior_y.has_response() is True
    assert behavior_y.BE_sub == 0.3
    assert behavior_y.BE_inc == 0.0
    assert behavior_y.BE_cg == 0.0
    calc_y_behavior1 = Behavior.response(calc_x, calc_y)
    behavior2 = {2013: {'_BE_sub': [0.5], '_BE_cg': [-0.8]}}
    behavior_y.update_behavior(behavior2)
    calc_y_behavior2 = Behavior.response(calc_x, calc_y)
    behavior3 = {2013: {'_BE_inc': [-0.2], '_BE_cg': [-0.8]}}
    behavior_y.update_behavior(behavior3)
    calc_y_behavior3 = Behavior.response(calc_x, calc_y)
    behavior4 = {2013: {'_BE_cg': [-0.8]}}
    behavior_y.update_behavior(behavior4)
    calc_y_behavior4 = Behavior.response(calc_x, calc_y)
    # check that total income tax liability differs across the
    # four sets of behavioral-response elasticities
    assert (calc_y_behavior1.records._iitax.sum() !=
            calc_y_behavior2.records._iitax.sum() !=
            calc_y_behavior3.records._iitax.sum() !=
            calc_y_behavior4.records._iitax.sum())
    # test incorrect _mtr_xy() usage
    with pytest.raises(ValueError):
        Behavior._mtr_xy(calc_x, calc_y, mtr_of='e00200p', tax_type='?')