def test_make_calculator_increment_years_first(cps_subsample):
    """
    Test Calculator inflation indexing of policy parameters.
    """
    # pylint: disable=too-many-locals
    # create Policy object with policy reform
    pol = Policy()
    reform = {2015: {}, 2016: {}}
    std5 = 2000
    reform[2015]['_STD_Aged'] = [[std5, std5, std5, std5, std5]]
    reform[2015]['_II_em'] = [5000]
    reform[2016]['_II_em'] = [6000]
    reform[2016]['_II_em_cpi'] = False
    pol.implement_reform(reform)
    # create Calculator object with Policy object as modified by reform
    rec = Records.cps_constructor(data=cps_subsample)
    calc = Calculator(policy=pol, records=rec)
    # compare expected policy parameter values with those embedded in calc
    irates = pol.inflation_rates()
    syr = Policy.JSON_START_YEAR
    irate2015 = irates[2015 - syr]
    irate2016 = irates[2016 - syr]
    std6 = std5 * (1.0 + irate2015)
    std7 = std6 * (1.0 + irate2016)
    exp_STD_Aged = np.array([[1500, 1200, 1200, 1500, 1500],
                             [1550, 1200, 1200, 1550, 1550],
                             [std5, std5, std5, std5, std5],
                             [std6, std6, std6, std6, std6],
                             [std7, std7, std7, std7, std7]])
    act_STD_Aged = calc.policy_param('_STD_Aged')
    assert np.allclose(act_STD_Aged[:5], exp_STD_Aged)
    exp_II_em = np.array([3900, 3950, 5000, 6000, 6000])
    act_II_em = calc.policy_param('_II_em')
    assert np.allclose(act_II_em[:5], exp_II_em)
Example #2
0
def test_make_Calculator_with_reform_after_start_year():
    # create Policy object using custom indexing rates
    irates = {2013: 0.01, 2014: 0.01, 2015: 0.02, 2016: 0.01, 2017: 0.03}
    parm = Policy(start_year=2013, num_years=len(irates),
                  inflation_rates=irates)
    # specify reform in 2015, which is two years after Policy start_year
    reform = {2015: {}, 2016: {}}
    reform[2015]['_STD_Aged'] = [[1600, 1300, 1600, 1300, 1600, 1300]]
    reform[2015]['_II_em'] = [5000]
    reform[2016]['_II_em'] = [6000]
    reform[2016]['_II_em_cpi'] = False
    parm.implement_reform(reform)
    recs = Records(data=TAX_DTA, weights=WEIGHTS, start_year=2009)
    calc = Calculator(policy=parm, records=recs)
    # compare actual and expected parameter values over all years
    exp_STD_Aged = np.array([[1500, 1200, 1200, 1500, 1500, 1200],
                             [1550, 1200, 1200, 1550, 1550, 1200],
                             [1600, 1300, 1600, 1300, 1600, 1300],
                             [1632, 1326, 1632, 1326, 1632, 1326],
                             [1648, 1339, 1648, 1339, 1648, 1339]])
    exp_II_em = np.array([3900, 3950, 5000, 6000, 6000])
    assert_array_equal(calc.policy._STD_Aged, exp_STD_Aged)
    assert_array_equal(calc.policy._II_em, exp_II_em)
    # compare actual and expected values for 2015
    calc.increment_year()
    calc.increment_year()
    assert calc.current_year == 2015
    exp_2015_II_em = 5000
    assert_array_equal(calc.policy.II_em, exp_2015_II_em)
    exp_2015_STD_Aged = np.array([1600, 1300, 1600, 1300, 1600, 1300])
    assert_array_equal(calc.policy.STD_Aged, exp_2015_STD_Aged)
def test_calculator_mtr_when_PT_rates_differ():
    """
    Test Calculator mtr method in special case.
    """
    reform = {2013: {'_II_rt1': [0.40],
                     '_II_rt2': [0.40],
                     '_II_rt3': [0.40],
                     '_II_rt4': [0.40],
                     '_II_rt5': [0.40],
                     '_II_rt6': [0.40],
                     '_II_rt7': [0.40],
                     '_PT_rt1': [0.30],
                     '_PT_rt2': [0.30],
                     '_PT_rt3': [0.30],
                     '_PT_rt4': [0.30],
                     '_PT_rt5': [0.30],
                     '_PT_rt6': [0.30],
                     '_PT_rt7': [0.30]}}
    funit = (
        u'RECID,MARS,FLPDYR,e00200,e00200p,e00900,e00900p,extraneous\n'
        u'1,    1,   2009,  200000,200000, 100000,100000, 9999999999\n'
    )
    rec = Records(pd.read_csv(StringIO(funit)))
    pol = Policy()
    calc1 = Calculator(policy=pol, records=rec)
    (_, mtr1, _) = calc1.mtr(variable_str='p23250')
    pol.implement_reform(reform)
    calc2 = Calculator(policy=pol, records=rec)
    (_, mtr2, _) = calc2.mtr(variable_str='p23250')
    assert np.allclose(mtr1, mtr2, rtol=0.0, atol=1e-06)
Example #4
0
def diff_in_revenue(reform_on_II, orig_reform):
    policy_func = Policy()
    puf = pd.read_csv("./puf.csv")
    records_func = Records(puf)
    calc_func = Calculator(policy = policy_func, records = records_func)
    policy_bench = Policy()
    records_bench = Records(puf)
    calc_bench = Calculator(policy = policy_bench, records = records_bench)
    reform = {
        CURRENT_YEAR:{
        "_II_rt1":[max(policy_bench._II_rt1[0] *(1 - reform_on_II),0.0)],
        "_II_rt2":[max(policy_bench._II_rt2[0] *(1 - reform_on_II),0.0)],
        "_II_rt3":[max(policy_bench._II_rt3[0] *(1 - reform_on_II),0.0)],
        "_II_rt4":[max(policy_bench._II_rt4[0] *(1 - reform_on_II),0.0)],
        "_II_rt5":[max(policy_bench._II_rt5[0] *(1 - reform_on_II),0.0)],
        "_II_rt6":[max(policy_bench._II_rt6[0] *(1 - reform_on_II),0.0)],
        "_II_rt7":[max(policy_bench._II_rt7[0] *(1 - reform_on_II),0.0)]}
    }
    policy_func.implement_reform(reform)
    policy_func.implement_reform(orig_reform)
    calc_func.advance_to_year(CURRENT_YEAR)
    calc_bench.advance_to_year(CURRENT_YEAR)
    calc_func.calc_all()
    calc_bench.calc_all()
    ans = ((calc_bench.records._combined*calc_bench.records.s006).sum()-(calc_func.records._combined*calc_func.records.s006).sum())
    print("diff in revenue is ", ans)
    return ans
def test_make_Calculator_with_reform_after_start_year(records_2009):
    # create Policy object using custom indexing rates
    irates = {2013: 0.01, 2014: 0.01, 2015: 0.02, 2016: 0.01, 2017: 0.03}
    parm = Policy(start_year=2013, num_years=len(irates),
                  inflation_rates=irates)
    # specify reform in 2015, which is two years after Policy start_year
    reform = {2015: {}, 2016: {}}
    reform[2015]['_STD_Aged'] = [[1600, 1300, 1600, 1300, 1600, 1300]]
    reform[2015]['_II_em'] = [5000]
    reform[2016]['_II_em'] = [6000]
    reform[2016]['_II_em_cpi'] = False
    parm.implement_reform(reform)
    calc = Calculator(policy=parm, records=records_2009)
    # compare actual and expected parameter values over all years
    assert np.allclose(calc.policy._STD_Aged,
                       np.array([[1500, 1200, 1200, 1500, 1500, 1200],
                                 [1550, 1200, 1200, 1550, 1550, 1200],
                                 [1600, 1300, 1600, 1300, 1600, 1300],
                                 [1632, 1326, 1632, 1326, 1632, 1326],
                                 [1648, 1339, 1648, 1339, 1648, 1339]]),
                       atol=0.5, rtol=0.0)  # handles rounding to dollars
    assert np.allclose(calc.policy._II_em,
                       np.array([3900, 3950, 5000, 6000, 6000]))
    # compare actual and expected values for 2015
    calc.increment_year()
    calc.increment_year()
    assert calc.current_year == 2015
    assert np.allclose(calc.policy.II_em, 5000)
    assert np.allclose(calc.policy.STD_Aged,
                       np.array([1600, 1300, 1600, 1300, 1600, 1300]))
def test_write_graph_file(cps_subsample):
    recs = Records.cps_constructor(data=cps_subsample)
    calc = Calculator(policy=Policy(), records=recs)
    mtr = 0.20 * np.ones_like(cps_subsample['e00200'])
    vdf = calc.dataframe(['s006', 'e00200', 'c00100'])
    vdf['mtr1'] = mtr
    vdf['mtr2'] = mtr
    gdata = mtr_graph_data(vdf, calc.current_year, mtr_measure='ptax',
                           alt_e00200p_text='Taxpayer Earnings',
                           income_measure='agi',
                           dollar_weighting=False)
    gplot = xtr_graph_plot(gdata)
    assert gplot
    htmlfname = temporary_filename(suffix='.html')
    try:
        write_graph_file(gplot, htmlfname, 'title')
    except Exception:  # pylint: disable=broad-except
        if os.path.isfile(htmlfname):
            try:
                os.remove(htmlfname)
            except OSError:
                pass  # sometimes we can't remove a generated temporary file
        assert 'write_graph_file()_ok' == 'no'
    # if try was successful, try to remove the file
    if os.path.isfile(htmlfname):
        try:
            os.remove(htmlfname)
        except OSError:
            pass  # sometimes we can't remove a generated temporary file
def test_Calculator_advance_to_year(records_2009):
    policy = Policy()
    calc = Calculator(policy=policy, records=records_2009)
    calc.advance_to_year(2016)
    assert calc.current_year == 2016
    with pytest.raises(ValueError):
        calc.advance_to_year(2015)
def test_mtr_graph_data(cps_subsample):
    recs = Records.cps_constructor(data=cps_subsample)
    calc = Calculator(policy=Policy(), records=recs)
    year = calc.current_year
    with pytest.raises(ValueError):
        mtr_graph_data(None, year, mars='bad',
                       income_measure='agi',
                       dollar_weighting=True)
    with pytest.raises(ValueError):
        mtr_graph_data(None, year, mars=0,
                       income_measure='expanded_income',
                       dollar_weighting=True)
    with pytest.raises(ValueError):
        mtr_graph_data(None, year, mars=list())
    with pytest.raises(ValueError):
        mtr_graph_data(None, year, mars='ALL', mtr_variable='e00200s')
    with pytest.raises(ValueError):
        mtr_graph_data(None, year, mtr_measure='badtax')
    with pytest.raises(ValueError):
        mtr_graph_data(None, year, income_measure='badincome')
    mtr = 0.20 * np.ones_like(cps_subsample['e00200'])
    vdf = calc.dataframe(['s006', 'MARS', 'e00200'])
    vdf['mtr1'] = mtr
    vdf['mtr2'] = mtr
    vdf = vdf[vdf['MARS'] == 1]
    gdata = mtr_graph_data(vdf, year, mars=1,
                           mtr_wrt_full_compen=True,
                           income_measure='wages',
                           dollar_weighting=True)
    assert isinstance(gdata, dict)
def test_Calculator_mtr_when_PT_rates_differ():
    reform = {2013: {'_II_rt1': [0.40],
                     '_II_rt2': [0.40],
                     '_II_rt3': [0.40],
                     '_II_rt4': [0.40],
                     '_II_rt5': [0.40],
                     '_II_rt6': [0.40],
                     '_II_rt7': [0.40],
                     '_PT_rt1': [0.30],
                     '_PT_rt2': [0.30],
                     '_PT_rt3': [0.30],
                     '_PT_rt4': [0.30],
                     '_PT_rt5': [0.30],
                     '_PT_rt6': [0.30],
                     '_PT_rt7': [0.30]}}
    funit = (
        u'RECID,MARS,FLPDYR,e00200,e00200p,e00900,e00900p\n'
        u'1,    1,   2015,  200000,200000, 100000,100000\n'
    )
    pol1 = Policy()
    rec1 = Records(pd.read_csv(StringIO(funit)))
    calc1 = Calculator(policy=pol1, records=rec1)
    (_, mtr1, _) = calc1.mtr(variable_str='p23250')
    pol2 = Policy()
    pol2.implement_reform(reform)
    rec2 = Records(pd.read_csv(StringIO(funit)))
    calc2 = Calculator(policy=pol2, records=rec2)
    (_, mtr2, _) = calc2.mtr(variable_str='p23250')
    assert np.allclose(mtr1, mtr2, rtol=0.0, atol=1e-06)
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)
def test_make_calculator_with_policy_reform(cps_subsample):
    """
    Test Calculator class ctor with policy reform.
    """
    rec = Records.cps_constructor(data=cps_subsample)
    year = rec.current_year
    # create a Policy object and apply a policy reform
    pol = Policy()
    reform = {2013: {'_II_em': [4000], '_II_em_cpi': False,
                     '_STD_Aged': [[1600, 1300, 1300, 1600, 1600]],
                     '_STD_Aged_cpi': False}}
    pol.implement_reform(reform)
    # create a Calculator object using this policy reform
    calc = Calculator(policy=pol, records=rec)
    # check that Policy object embedded in Calculator object is correct
    assert calc.current_year == year
    assert calc.policy_param('II_em') == 4000
    assert np.allclose(calc.policy_param('_II_em'),
                       np.array([4000] * Policy.DEFAULT_NUM_YEARS))
    exp_STD_Aged = [[1600, 1300, 1300,
                     1600, 1600]] * Policy.DEFAULT_NUM_YEARS
    assert np.allclose(calc.policy_param('_STD_Aged'),
                       np.array(exp_STD_Aged))
    assert np.allclose(calc.policy_param('STD_Aged'),
                       np.array([1600, 1300, 1300, 1600, 1600]))
def test_json_reform_url():
    """
    Test reading a JSON reform from a URL. Results from the URL are expected
    to match the results from the string.
    """
    reform_str = """
    {
    "policy": {
        // raise FICA payroll tax rate in 2018 and 2020
        "FICA_ss_trt": {
            "2018": 0.130,
            "2020": 0.140
        },
        // raise Medicare payroll tax rate in 2019 and 2021
        "FICA_mc_trt": {
            "2019": 0.030,
            "2021": 0.032
        }
      }
    }
    """
    reform_url = ('https://raw.githubusercontent.com/PSLmodels/'
                  'Tax-Calculator/master/taxcalc/reforms/ptaxes0.json')
    params_str = Calculator.read_json_param_objects(reform_str, None)
    params_url = Calculator.read_json_param_objects(reform_url, None)
    assert params_str == params_url
def test_translate_json_reform_suffixes_eic():
    """
    Test read_json_param_objects method using EIC-indexed parameter suffixes.
    """
    json1 = """{"policy": {
      "_II_em": {"2020": [20000], "2015": [15000]},
      "_EITC_c_0kids": {"2018": [510], "2019": [510]},
      "_EITC_c_1kid": {"2019": [3400], "2018": [3400]},
      "_EITC_c_2kids": {"2018": [5616], "2019": [5616]},
      "_EITC_c_3+kids": {"2019": [6318], "2018": [6318]}
    }}"""
    pdict1 = Calculator.read_json_param_objects(reform=json1, assump=None)
    rdict1 = pdict1['policy']
    json2 = """{"policy": {
      "_EITC_c": {"2019": [[510, 3400, 5616, 6318]],
                  "2018": [[510, 3400, 5616, 6318]]},
      "_II_em": {"2020": [20000], "2015": [15000]}
    }}"""
    pdict2 = Calculator.read_json_param_objects(reform=json2, assump=None)
    rdict2 = pdict2['policy']
    assert len(rdict2) == len(rdict1)
    for year in rdict2.keys():
        if '_II_em' in rdict2[year].keys():
            assert np.allclose(rdict1[year]['_II_em'],
                               rdict2[year]['_II_em'],
                               atol=0.01, rtol=0.0)
        if '_EITC_c' in rdict2[year].keys():
            assert np.allclose(rdict1[year]['_EITC_c'],
                               rdict2[year]['_EITC_c'],
                               atol=0.01, rtol=0.0)
def test_translate_json_reform_suffixes_mars_non_indexed():
    """
    Test read_json_param_objects method using MARS-indexed parameter suffixes.
    """
    json1 = """{"policy": {
      "_II_em": {"2020": [20000], "2015": [15000]},
      "_AMEDT_ec_joint": {"2018": [400000], "2016": [300000]},
      "_AMEDT_ec_separate": {"2017": [150000], "2019": [200000]}
    }}"""
    pdict1 = Calculator.read_json_param_objects(reform=json1, assump=None)
    rdict1 = pdict1['policy']
    json2 = """{"policy": {
      "_AMEDT_ec": {"2016": [[200000, 300000, 125000, 200000, 200000]],
                    "2017": [[200000, 300000, 150000, 200000, 200000]],
                    "2018": [[200000, 400000, 150000, 200000, 200000]],
                    "2019": [[200000, 400000, 200000, 200000, 200000]]},
      "_II_em": {"2015": [15000], "2020": [20000]}
    }}"""
    pdict2 = Calculator.read_json_param_objects(reform=json2, assump=None)
    rdict2 = pdict2['policy']
    assert len(rdict2) == len(rdict1)
    for year in rdict2.keys():
        if '_II_em' in rdict2[year].keys():
            assert np.allclose(rdict1[year]['_II_em'],
                               rdict2[year]['_II_em'],
                               atol=0.01, rtol=0.0)
        if '_AMEDT_ec' in rdict2[year].keys():
            assert np.allclose(rdict1[year]['_AMEDT_ec'],
                               rdict2[year]['_AMEDT_ec'],
                               atol=0.01, rtol=0.0)
def test_noreform_documentation():
    """
    Test automatic documentation creation.
    """
    reform_json = """
    {
    "policy": {}
    }
    """
    assump_json = """
    {
    "consumption": {},
    "growdiff_baseline": {},
    "growdiff_response": {}
    }
    """
    params = Calculator.read_json_param_objects(reform_json, assump_json)
    assert isinstance(params, dict)
    actual_doc = Calculator.reform_documentation(params)
    expected_doc = (
        'REFORM DOCUMENTATION\n'
        'Baseline Growth-Difference Assumption Values by Year:\n'
        'none: using default baseline growth assumptions\n'
        'Policy Reform Parameter Values by Year:\n'
        'none: using current-law policy parameters\n'
    )
    assert actual_doc == expected_doc
def test_itax_compare(tests_path, using_puf, puf_fullsample, cps_fullsample):
    """
    Conduct income tax comparisons using ITAX data.
    """
    using_puf_adjust_ratios = True
    # generate 2015 estimates by AGI category using Tax-Calculator
    if using_puf:
        if using_puf_adjust_ratios:
            recs = Records(data=puf_fullsample)
        else:
            recs = Records(data=puf_fullsample, adjust_ratios=None)
    else:
        recs = Records.cps_constructor(data=cps_fullsample)
    calc = Calculator(policy=Policy(), records=recs, verbose=False)
    calc.advance_to_year(2015)
    calc.calc_all()
    # open actual output file
    if using_puf:
        afilename = os.path.join(tests_path, 'cmpi_puf_actual.txt')
    else:
        afilename = os.path.join(tests_path, 'cmpi_cps_actual.txt')
    afile = open(afilename, 'w')
    # write compare results to afile
    for cname in sorted(ITAX.keys()):
        comparison(cname, calc, ITAX, afile)
    # close actual output file
    afile.close()
    # check for differences between actual and expect output files
    efilename = afilename.replace('actual', 'expect')
    differences(afilename, efilename)
def test_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_n65(cps_subsample):
    """
    Test n65 method.
    """
    recs = Records.cps_constructor(data=cps_subsample)
    calc = Calculator(policy=Policy(), records=recs)
    assert calc.n65().sum() > 1500
def test_diagnostic_table(cps_subsample):
    """
    Test diagnostic_table method.
    """
    recs = Records.cps_constructor(data=cps_subsample)
    calc = Calculator(policy=Policy(), records=recs)
    adt = calc.diagnostic_table(3)
    assert isinstance(adt, pd.DataFrame)
def test_Calculator_advance_to_year():
    policy = Policy()
    puf = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009)
    calc = Calculator(policy=policy, records=puf)
    calc.advance_to_year(2016)
    assert calc.current_year == 2016
    with pytest.raises(ValueError):
        calc.advance_to_year(2015)
Example #21
0
def test_mtr_plot(records_2009):
    pol = Policy()
    behv = Behavior()
    calc = Calculator(policy=pol, records=records_2009, behavior=behv)
    calc.calc_all()
    source = get_mtr_data(calc, calc, weighting='wage_weighted',
                          weight_by_income_measure=True)
    plot = mtr_plot(source)
Example #22
0
def test_Calculator_mtr():
    policy = Policy()
    puf = Records(TAX_DTA, weights=WEIGHTS, start_year=2009)
    calc = Calculator(policy=policy, records=puf)
    (mtr_FICA, mtr_IIT, mtr) = calc.mtr()
    assert type(mtr) == np.ndarray
    assert np.array_equal(mtr, mtr_FICA) is False
    assert np.array_equal(mtr_FICA, mtr_IIT) is False
def test_dist_table_sum_row(cps_subsample):
    rec = Records.cps_constructor(data=cps_subsample)
    calc = Calculator(policy=Policy(), records=rec)
    calc.calc_all()
    tb1 = create_distribution_table(calc.distribution_table_dataframe(),
                                    'standard_income_bins', 'expanded_income')
    tb2 = create_distribution_table(calc.distribution_table_dataframe(),
                                    'soi_agi_bins', 'expanded_income')
    assert np.allclose(tb1[-1:], tb2[-1:])
Example #24
0
def test_convert_reform_dict():
    with pytest.raises(ValueError):
        rdict = Calculator.convert_reform_dict({2013: {'2013': [40000]}})
    with pytest.raises(ValueError):
        rdict = Calculator.convert_reform_dict({'_II_em': {2013: [40000]}})
    with pytest.raises(ValueError):
        rdict = Calculator.convert_reform_dict({4567: {2013: [40000]}})
    with pytest.raises(ValueError):
        rdict = Calculator.convert_reform_dict({'_II_em': 40000})
Example #25
0
def test_Calculator_current_law_version(records_2009):
    policy = Policy()
    reform = {2013: {'_II_rt7': [0.45]}}
    policy.implement_reform(reform)
    calc = Calculator(policy=policy, records=records_2009)
    calc_clp = calc.current_law_version()
    assert isinstance(calc_clp, Calculator)
    assert calc.policy.II_rt6 == calc_clp.policy.II_rt6
    assert calc.policy.II_rt7 != calc_clp.policy.II_rt7
Example #26
0
def test_dist_table_sum_row(records_2009):
    # Create a default Policy object
    policy1 = Policy()
    # Create a Calculator
    calc1 = Calculator(policy=policy1, records=records_2009)
    calc1.calc_all()
    t1 = create_distribution_table(calc1.records, groupby="small_income_bins", result_type="weighted_sum")
    t2 = create_distribution_table(calc1.records, groupby="large_income_bins", result_type="weighted_sum")
    npt.assert_allclose(t1[-1:], t2[-1:])
    t3 = create_distribution_table(calc1.records, groupby="small_income_bins", result_type="weighted_avg")
def test_atr_graph(cps_subsample):
    """
    Test atr_graph method.
    """
    recs = Records.cps_constructor(data=cps_subsample)
    calc = Calculator(policy=Policy(), records=recs)
    fig = calc.atr_graph(calc, mars=2, atr_measure='itax')
    assert fig
    fig = calc.atr_graph(calc, atr_measure='ptax')
    assert fig
def test_distribution_tables(cps_subsample):
    """
    Test distribution_tables method.
    """
    pol = Policy()
    recs = Records.cps_constructor(data=cps_subsample)
    calc1 = Calculator(policy=pol, records=recs)
    assert calc1.current_year == 2014
    calc1.calc_all()
    dt1, dt2 = calc1.distribution_tables(None, 'weighted_deciles')
    assert isinstance(dt1, pd.DataFrame)
    assert dt2 is None
    dt1, dt2 = calc1.distribution_tables(calc1, 'weighted_deciles')
    assert isinstance(dt1, pd.DataFrame)
    assert isinstance(dt2, pd.DataFrame)
    reform = {2014: {'_UBI_u18': [1000],
                     '_UBI_1820': [1000],
                     '_UBI_21': [1000]}}
    pol.implement_reform(reform)
    assert not pol.parameter_errors
    calc2 = Calculator(policy=pol, records=recs)
    calc2.calc_all()
    dt1, dt2 = calc1.distribution_tables(calc2, 'weighted_deciles')
    assert isinstance(dt1, pd.DataFrame)
    assert isinstance(dt2, pd.DataFrame)
def test_calculator_using_nonstd_input(rawinputfile):
    """
    Test Calculator using non-standard input records.
    """
    # check Calculator handling of raw, non-standard input data with no aging
    pol = Policy()
    pol.set_year(RAWINPUTFILE_YEAR)  # set policy params to input data year
    nonstd = Records(data=rawinputfile.name,
                     gfactors=None,  # keeps raw data unchanged
                     weights=None,
                     start_year=RAWINPUTFILE_YEAR)  # set raw input data year
    assert nonstd.array_length == RAWINPUTFILE_FUNITS
    calc = Calculator(policy=pol, records=nonstd,
                      sync_years=False)  # keeps raw data unchanged
    assert calc.current_year == RAWINPUTFILE_YEAR
    calc.calc_all()
    assert calc.weighted_total('e00200') == 0
    assert calc.total_weight() == 0
    varlist = ['RECID', 'MARS']
    dframe = calc.dataframe(varlist)
    assert isinstance(dframe, pd.DataFrame)
    assert dframe.shape == (RAWINPUTFILE_FUNITS, len(varlist))
    mars = calc.array('MARS')
    assert isinstance(mars, np.ndarray)
    assert mars.shape == (RAWINPUTFILE_FUNITS,)
    exp_iitax = np.zeros((nonstd.array_length,))
    assert np.allclose(calc.array('iitax'), exp_iitax)
    mtr_ptax, _, _ = calc.mtr(wrt_full_compensation=False)
    exp_mtr_ptax = np.zeros((nonstd.array_length,))
    exp_mtr_ptax.fill(0.153)
    assert np.allclose(mtr_ptax, exp_mtr_ptax)
def test_calculator_advance_to_year(cps_subsample):
    """
    Test Calculator advance_to_year method.
    """
    rec = Records.cps_constructor(data=cps_subsample)
    pol = Policy()
    calc = Calculator(policy=pol, records=rec)
    calc.advance_to_year(2016)
    assert calc.current_year == 2016
    with pytest.raises(ValueError):
        calc.advance_to_year(2015)
def test_Calculator_attr_access_to_policy(records_2009):
    policy = Policy()
    calc = Calculator(policy=policy, records=records_2009)
    assert hasattr(calc.records, 'c01000')
    assert hasattr(calc.policy, '_AMT_Child_em')
    assert hasattr(calc, 'policy')
Example #32
0
def test_create_tables(cps_subsample):
    # pylint: disable=too-many-statements,too-many-branches
    # create a current-law Policy object and Calculator object calc1
    rec = Records.cps_constructor(data=cps_subsample)
    pol = Policy()
    calc1 = Calculator(policy=pol, records=rec)
    calc1.calc_all()
    # create a policy-reform Policy object and Calculator object calc2
    reform = {2013: {'_II_rt1': [0.15]}}
    pol.implement_reform(reform)
    calc2 = Calculator(policy=pol, records=rec)
    calc2.calc_all()

    test_failure = False

    # test creating various difference tables

    diff = create_difference_table(calc1.dataframe(DIFF_VARIABLES),
                                   calc2.dataframe(DIFF_VARIABLES),
                                   'standard_income_bins', 'combined')
    assert isinstance(diff, pd.DataFrame)
    tabcol = 'pc_aftertaxinc'
    expected = [
        np.nan, np.nan, -0.16, -0.57, -0.72, -0.69, -0.82, -0.80, -0.75, -0.65,
        -0.23, -0.09, -0.06, -0.59
    ]
    if not np.allclose(
            diff[tabcol].values, expected, atol=0.005, rtol=0.0,
            equal_nan=True):
        test_failure = True
        print('diff xbin', tabcol)
        for val in diff[tabcol].values:
            print('{:.2f},'.format(val))

    diff = create_difference_table(calc1.dataframe(DIFF_VARIABLES),
                                   calc2.dataframe(DIFF_VARIABLES),
                                   'weighted_deciles', 'combined')
    assert isinstance(diff, pd.DataFrame)
    tabcol = 'tot_change'
    expected = [
        0, 0, 1219678, 15503037, 25922077, 35000592, 48336897, 62637728,
        79750078, 93136108, 116996252, 102458801, 580961247, 63156380,
        33664610, 5637811
    ]
    if not np.allclose(diff[tabcol].values, expected, atol=0.51, rtol=0.0):
        test_failure = True
        print('diff xdec', tabcol)
        for val in diff[tabcol].values:
            print('{:.0f},'.format(val))

    tabcol = 'share_of_change'
    expected = [
        0.00, 0.00, 0.21, 2.67, 4.46, 6.02, 8.32, 10.78, 13.73, 16.03, 20.14,
        17.64, 100.00, 10.87, 5.79, 0.97
    ]
    if not np.allclose(diff[tabcol].values, expected, atol=0.005, rtol=0.0):
        test_failure = True
        print('diff xdec', tabcol)
        for val in diff[tabcol].values:
            print('{:.2f},'.format(val))

    tabcol = 'pc_aftertaxinc'
    expected = [
        np.nan, np.nan, -0.15, -0.62, -0.70, -0.73, -0.78, -0.80, -0.80, -0.74,
        -0.71, -0.30, -0.59, -0.55, -0.25, -0.06
    ]
    if not np.allclose(
            diff[tabcol].values, expected, atol=0.005, rtol=0.0,
            equal_nan=True):
        test_failure = True
        print('diff xdec', tabcol)
        for val in diff[tabcol].values:
            print('{:.2f},'.format(val))

    tabcol = 'pc_aftertaxinc'
    expected = [
        np.nan, np.nan, -0.15, -0.62, -0.70, -0.73, -0.78, -0.80, -0.80, -0.74,
        -0.71, -0.30, -0.59, -0.55, -0.25, -0.06
    ]
    if not np.allclose(
            diff[tabcol].values, expected, atol=0.005, rtol=0.0,
            equal_nan=True):
        test_failure = True
        print('diff xdec', tabcol)
        for val in diff[tabcol].values:
            print('{:.2f},'.format(val))

    # test creating various distribution tables

    dist, _ = calc2.distribution_tables(None, 'weighted_deciles')
    assert isinstance(dist, pd.DataFrame)
    tabcol = 'iitax'
    expected = [
        0, 0, -53644343, -65258622, -57617119, 37391333, 200879230, 329784586,
        553827330, 1015854407, 1731283600, 7090603505, 10783103907, 1638192777,
        2213960052, 3238450675
    ]
    if not np.allclose(dist[tabcol].values, expected, atol=0.5, rtol=0.0):
        test_failure = True
        print('dist xdec', tabcol)
        for val in dist[tabcol].values:
            print('{:.0f},'.format(val))

    tabcol = 'num_returns_ItemDed'
    expected = [
        0, 0, 2561, 12610, 21936, 29172, 50890, 61563, 78247, 91823, 118523,
        128886, 596211, 63986, 51634, 13266
    ]
    if not np.allclose(dist[tabcol].tolist(), expected, atol=0.5, rtol=0.0):
        test_failure = True
        print('dist xdec', tabcol)
        for val in dist[tabcol].values:
            print('{:.0f},'.format(val))

    tabcol = 'expanded_income'
    expected = [
        0, 0, 835224673, 2639667638, 3940559051, 5286856071, 6972849344,
        8881099529, 11467767759, 14761195525, 19832126806, 44213000235,
        118830346631, 14399218059, 16868648076, 12945134101
    ]
    if not np.allclose(dist[tabcol].tolist(), expected, atol=0.5, rtol=0.0):
        test_failure = True
        print('dist xdec', tabcol)
        for val in dist[tabcol].values:
            print('{:.0f},'.format(val))

    tabcol = 'aftertax_income'
    expected = [
        0, 0, 818813684, 2466000535, 3671150517, 4790979126, 6173998985,
        7754183496, 9907604744, 12510477225, 16273592612, 33915377411,
        98282178334, 11345456373, 13400757263, 9169163776
    ]
    if not np.allclose(dist[tabcol].tolist(), expected, atol=0.5, rtol=0.0):
        test_failure = True
        print('dist xdec', tabcol)
        for val in dist[tabcol].values:
            print('{:.0f},'.format(val))

    dist, _ = calc2.distribution_tables(None, 'standard_income_bins')
    assert isinstance(dist, pd.DataFrame)
    tabcol = 'iitax'
    expected = [
        0, 0, -42244205, -76727831, -62581860, 53797887, 217016689, 723516183,
        1108097059, 3272479928, 2818979541, 950296405, 1820474110, 10783103907
    ]
    if not np.allclose(dist[tabcol], expected, atol=0.5, rtol=0.0):
        test_failure = True
        print('dist xbin', tabcol)
        for val in dist[tabcol].values:
            print('{:.0f},'.format(val))

    tabcol = 'num_returns_ItemDed'
    expected = [
        0, 0, 1202, 13614, 27272, 34407, 48265, 117225, 103319, 181885, 61014,
        5126, 2882, 596211
    ]
    if not np.allclose(dist[tabcol].tolist(), expected, atol=0.5, rtol=0.0):
        test_failure = True
        print('dist xbin', tabcol)
        for val in dist[tabcol].values:
            print('{:.0f},'.format(val))

    if test_failure:
        assert 1 == 2
def test_Calculator_create_difference_table(puf_1991, weights_1991):
    # create current-law Policy object and use to create Calculator calc1
    policy1 = Policy()
    puf1 = Records(data=puf_1991, weights=weights_1991, start_year=2009)
    calc1 = Calculator(policy=policy1, records=puf1)
    calc1.advance_to_year(2013)
    calc1.calc_all()
    # create policy-reform Policy object and use to create Calculator calc2
    policy2 = Policy()
    reform = {2013: {'_II_rt7': [0.45]}}
    policy2.implement_reform(reform)
    puf2 = Records(data=puf_1991, weights=weights_1991, start_year=2009)
    calc2 = Calculator(policy=policy2, records=puf2)
    calc2.advance_to_year(2013)
    calc2.calc_all()
    # create difference table and check that it is a Pandas DataFrame
    dtable = create_difference_table(calc1.records,
                                     calc2.records,
                                     groupby="weighted_deciles")
    assert isinstance(dtable, pd.DataFrame)
Example #34
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
    pol = Policy()
    rec = Records(data=puf_data)
    calc1 = Calculator(policy=pol, records=rec, verbose=False, behavior=None)
    # create reform Calculator object with possible behavioral responses
    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 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 = calc1.array(output_type)
        if calc2.behavior.has_response():
            calc_clp = calc2.current_law_version()
            calc2_br = Behavior.response(calc_clp, 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
Example #35
0
def test_ID_HC_vs_BS(cps_subsample):
    """
    Test that complete haircut of itemized deductions produces same
    results as a 100% benefit surtax with no benefit deduction.
    """
    rec = Records.cps_constructor(data=cps_subsample)
    # specify complete-haircut reform policy and Calculator object
    hc_reform = {2013: {'_ID_Medical_hc': [1.0],
                        '_ID_StateLocalTax_hc': [1.0],
                        '_ID_RealEstate_hc': [1.0],
                        '_ID_Casualty_hc': [1.0],
                        '_ID_Miscellaneous_hc': [1.0],
                        '_ID_InterestPaid_hc': [1.0],
                        '_ID_Charity_hc': [1.0]}}
    hc_policy = Policy()
    hc_policy.implement_reform(hc_reform)
    hc_calc = Calculator(policy=hc_policy, records=rec)
    hc_calc.calc_all()
    # specify benefit-surtax reform policy and Calculator object
    bs_reform = {2013: {'_ID_BenefitSurtax_crt': [0.0],
                        '_ID_BenefitSurtax_trt': [1.0]}}
    bs_policy = Policy()
    bs_policy.implement_reform(bs_reform)
    bs_calc = Calculator(policy=bs_policy, records=rec)
    bs_calc.calc_all()
    # compare calculated tax results generated by the two reforms
    assert np.allclose(hc_calc.array('payrolltax'),
                       bs_calc.array('payrolltax'))
    assert np.allclose(hc_calc.array('iitax'),
                       bs_calc.array('iitax'))
Example #36
0
def test_agg(tests_path, cps_fullsample):
    """
    Test current-law aggregate taxes using cps.csv file.
    """
    # pylint: disable=too-many-statements,too-many-locals
    nyrs = 10
    # create a baseline Policy object with current-law policy parameters
    baseline_policy = Policy()
    # create a Records object (rec) containing all cps.csv input records
    recs = Records.cps_constructor(data=cps_fullsample)
    # create a Calculator object using baseline policy and cps records
    calc = Calculator(policy=baseline_policy, records=recs)
    calc.advance_to_year(START_YEAR)
    calc_start_year = calc.current_year
    # create aggregate diagnostic table (adt) as a Pandas DataFrame object
    adt = calc.diagnostic_table(nyrs).round(1)  # column labels are int
    taxes_fullsample = adt.loc["Combined Liability ($b)"]
    # compare actual DataFrame, adt, with the expected DataFrame, edt
    aggres_path = os.path.join(tests_path, 'cpscsv_agg_expect.csv')
    edt = pd.read_csv(aggres_path, index_col=False)  # column labels are str
    edt.drop('Unnamed: 0', axis='columns', inplace=True)
    assert len(adt.columns.values) == len(edt.columns.values)
    diffs = False
    for icol in adt.columns.values:
        if not np.allclose(adt[icol], edt[str(icol)]):
            diffs = True
    if diffs:
        new_filename = '{}{}'.format(aggres_path[:-10], 'actual.csv')
        adt.to_csv(new_filename, float_format='%.1f')
        msg = 'CPSCSV AGG RESULTS DIFFER\n'
        msg += '-------------------------------------------------\n'
        msg += '--- NEW RESULTS IN cpscsv_agg_actual.csv FILE ---\n'
        msg += '--- if new OK, copy cpscsv_agg_actual.csv to  ---\n'
        msg += '---                 cpscsv_agg_expect.csv     ---\n'
        msg += '---            and rerun test.                ---\n'
        msg += '---       (both are in taxcalc/tests)         ---\n'
        msg += '-------------------------------------------------\n'
        raise ValueError(msg)
    # create aggregate diagnostic table using unweighted sub-sample of records
    rn_seed = 180  # to ensure sub-sample is always the same
    subfrac = 0.07# 0.03  # sub-sample fraction
    subsample = cps_fullsample.sample(frac=subfrac, random_state=rn_seed)
    recs_subsample = Records.cps_constructor(data=subsample)
    calc_subsample = Calculator(policy=baseline_policy, records=recs_subsample)
    calc_subsample.advance_to_year(START_YEAR)
    adt_subsample = calc_subsample.diagnostic_table(nyrs)
    # compare combined tax liability from full and sub samples for each year
    taxes_subsample = adt_subsample.loc["Combined Liability ($b)"]
    print('taxes_submsampe = ', taxes_subsample)
    print('TAXES full sample = ', taxes_fullsample)
    msg = ''
    for cyr in range(calc_start_year, calc_start_year + nyrs):
        if cyr == calc_start_year:
            reltol = 0.0232
        else:
            reltol = 0.0270
        if not np.allclose(taxes_subsample[cyr], taxes_fullsample[cyr],
                           atol=0.0, rtol=reltol):
            reldiff = (taxes_subsample[cyr] / taxes_fullsample[cyr]) - 1.
            line1 = '\nCPSCSV AGG SUB-vs-FULL RESULTS DIFFER IN {}'
            line2 = '\n  when subfrac={:.3f}, rtol={:.4f}, seed={}'
            line3 = '\n  with sub={:.3f}, full={:.3f}, rdiff={:.4f}'
            msg += line1.format(cyr)
            msg += line2.format(subfrac, reltol, rn_seed)
            msg += line3.format(taxes_subsample[cyr],
                                taxes_fullsample[cyr],
                                reldiff)
    if msg:
        raise ValueError(msg)
def test_make_calculator_raises_on_no_policy(cps_subsample):
    rec = Records.cps_constructor(data=cps_subsample)
    with pytest.raises(ValueError):
        Calculator(records=rec)
def test_diagnostic_table(cps_subsample):
    recs = Records.cps_constructor(data=cps_subsample)
    calc = Calculator(policy=Policy(), records=recs)
    adt = calc.diagnostic_table(3)
    assert isinstance(adt, pd.DataFrame)
Example #39
0
def test_json_assump_url():
    assump_str = """
    {
        "consumption": {
            "_BEN_housing_value": {"2017": [1.0]},
            "_BEN_snap_value": {"2017": [1.0]},
            "_BEN_tanf_value": {"2017": [1.0]},
            "_BEN_vet_value": {"2017": [1.0]},
            "_BEN_wic_value": {"2017": [1.0]},
            "_BEN_mcare_value": {"2017": [1.0]},
            "_BEN_mcaid_value": {"2017": [1.0]},
            "_BEN_other_value": {"2017": [1.0]},
            "_MPC_e17500": {"2017": [0.0]},
            "_MPC_e18400": {"2017": [0.0]},
            "_MPC_e19800": {"2017": [0.0]},
            "_MPC_e20400": {"2017": [0.0]}
        },
        "behavior": {
            "_BE_inc": {"2017": [0.0]},
            "_BE_sub": {"2017": [0.0]},
            "_BE_cg": {"2017": [0.0]}
        },
        "growdiff_baseline": {
            "_ABOOK": {"2017": [0.0]},
            "_ACGNS": {"2017": [0.0]},
            "_ACPIM": {"2017": [0.0]},
            "_ACPIU": {"2017": [0.0]},
            "_ADIVS": {"2017": [0.0]},
            "_AINTS": {"2017": [0.0]},
            "_AIPD": {"2017": [0.0]},
            "_ASCHCI": {"2017": [0.0]},
            "_ASCHCL": {"2017": [0.0]},
            "_ASCHEI": {"2017": [0.0]},
            "_ASCHEL": {"2017": [0.0]},
            "_ASCHF": {"2017": [0.0]},
            "_ASOCSEC": {"2017": [0.0]},
            "_ATXPY": {"2017": [0.0]},
            "_AUCOMP": {"2017": [0.0]},
            "_AWAGE": {"2017": [0.0]},
            "_ABENOTHER": {"2017": [0.0]},
            "_ABENMCARE": {"2017": [0.0]},
            "_ABENMCAID": {"2017": [0.0]},
            "_ABENSSI": {"2017": [0.0]},
            "_ABENSNAP": {"2017": [0.0]},
            "_ABENWIC": {"2017": [0.0]},
            "_ABENHOUSING": {"2017": [0.0]},
            "_ABENTANF": {"2017": [0.0]},
            "_ABENVET": {"2017": [0.0]}
        },
        "growdiff_response": {
            "_ABOOK": {"2017": [0.0]},
            "_ACGNS": {"2017": [0.0]},
            "_ACPIM": {"2017": [0.0]},
            "_ACPIU": {"2017": [0.0]},
            "_ADIVS": {"2017": [0.0]},
            "_AINTS": {"2017": [0.0]},
            "_AIPD": {"2017": [0.0]},
            "_ASCHCI": {"2017": [0.0]},
            "_ASCHCL": {"2017": [0.0]},
            "_ASCHEI": {"2017": [0.0]},
            "_ASCHEL": {"2017": [0.0]},
            "_ASCHF": {"2017": [0.0]},
            "_ASOCSEC": {"2017": [0.0]},
            "_ATXPY": {"2017": [0.0]},
            "_AUCOMP": {"2017": [0.0]},
            "_AWAGE": {"2017": [0.0]},
            "_ABENOTHER": {"2017": [0.0]},
            "_ABENMCARE": {"2017": [0.0]},
            "_ABENMCAID": {"2017": [0.0]},
            "_ABENSSI": {"2017": [0.0]},
            "_ABENSNAP": {"2017": [0.0]},
            "_ABENWIC": {"2017": [0.0]},
            "_ABENHOUSING": {"2017": [0.0]},
            "_ABENTANF": {"2017": [0.0]},
            "_ABENVET": {"2017": [0.0]}
        },
        "growmodel": {
            "_active": {"2017": [false]}
        }
    }
    """
    assump_url = ('https://raw.githubusercontent.com/open-source-economics/'
                  'Tax-Calculator/master/taxcalc/assumptions/'
                  'economic_assumptions_template.json')
    params_str = Calculator.read_json_param_objects(None, assump_str)
    params_url = Calculator.read_json_param_objects(None, assump_url)
    assert params_str == params_url
def test_read_json_param_with_suffixes_and_errors():
    # test interaction of policy parameter suffixes and reform errors
    # (fails without 0.10.2 bug fix as reported by Hank Doupe in PB PR#641)
    reform = {
        u'policy': {
            u'_II_brk4_separate': {
                u'2017': [5000.0]
            },
            u'_STD_separate': {
                u'2017': [8000.0]
            },
            u'_STD_single': {
                u'2018': [1000.0]
            },
            u'_II_brk2_headhousehold': {
                u'2017': [1000.0]
            },
            u'_II_brk4_single': {
                u'2017': [500.0]
            },
            u'_STD_joint': {
                u'2017': [10000.0],
                u'2020': [150.0]
            },
            u'_II_brk2_separate': {
                u'2017': [1000.0]
            },
            u'_II_brk2_single': {
                u'2017': [1000.0]
            },
            u'_II_brk2_joint': {
                u'2017': [1000.0]
            },
            u'_FICA_ss_trt': {
                u'2017': [-1.0],
                u'2019': [0.1]
            },
            u'_II_brk4_headhousehold': {
                u'2017': [500.0]
            },
            u'_STD_headhousehold': {
                u'2017': [10000.0],
                u'2020': [150.0]
            },
            u'_ID_Medical_frt': {
                u'2019': [0.06]
            },
            u'_II_brk4_joint': {
                u'2017': [500.0]
            },
            u'_ID_BenefitSurtax_Switch_medical': {
                u'2017': [True]
            }
        }
    }
    json_reform = json.dumps(reform)
    params = Calculator.read_json_param_objects(json_reform, None)
    assert isinstance(params, dict)
    pol = Policy()
    pol.ignore_reform_errors()
    pol.implement_reform(params['policy'],
                         print_warnings=False,
                         raise_errors=False)
    assert len(pol.parameter_errors) > 0
    assert len(pol.parameter_warnings) > 0
def test_distribution_tables(cps_subsample):
    pol = Policy()
    recs = Records.cps_constructor(data=cps_subsample)
    calc1 = Calculator(policy=pol, records=recs)
    assert calc1.current_year == 2014
    calc1.calc_all()
    dt1, dt2 = calc1.distribution_tables(None, 'weighted_deciles')
    assert isinstance(dt1, pd.DataFrame)
    assert dt2 is None
    dt1, dt2 = calc1.distribution_tables(calc1, 'weighted_deciles')
    assert isinstance(dt1, pd.DataFrame)
    assert isinstance(dt2, pd.DataFrame)
    reform = {
        2014: {
            '_UBI_u18': [1000],
            '_UBI_1820': [1000],
            '_UBI_21': [1000]
        }
    }
    pol.implement_reform(reform)
    assert not pol.parameter_errors
    calc2 = Calculator(policy=pol, records=recs)
    calc2.calc_all()
    dt1, dt2 = calc1.distribution_tables(calc2, 'weighted_deciles')
    assert isinstance(dt1, pd.DataFrame)
    assert isinstance(dt2, pd.DataFrame)
def test_make_calculator_deepcopy(cps_subsample):
    pol = Policy()
    rec = Records.cps_constructor(data=cps_subsample)
    calc1 = Calculator(policy=pol, records=rec)
    calc2 = copy.deepcopy(calc1)
    assert isinstance(calc2, Calculator)
def test_ID_RealEstate_HC_vs_CRT(cps_subsample):
    """
    Test that a cap on all state, local, and foreign real estate tax deductions
    at 0 percent of AGI is equivalent to a complete haircut on the same real
    estate tax deductions.
    """
    rec = Records.cps_constructor(data=cps_subsample)
    # specify real estate complete haircut reform policy and Calculator object
    hc_reform = {2013: {'_ID_RealEstate_hc': [1.0]}}
    hc_policy = Policy()
    hc_policy.implement_reform(hc_reform)
    hc_calc = Calculator(policy=hc_policy, records=rec)
    hc_calc.calc_all()
    # specify AGI cap reform policy and Calculator object
    crt_reform = {2013: {'_ID_RealEstate_crt': [0.0]}}
    crt_policy = Policy()
    crt_policy.implement_reform(crt_reform)
    crt_calc = Calculator(policy=crt_policy, records=rec)
    crt_calc.calc_all()
    # compare calculated tax results generated by the two reforms
    assert np.allclose(hc_calc.array('payrolltax'),
                       crt_calc.array('payrolltax'))
    assert np.allclose(hc_calc.array('iitax'), crt_calc.array('iitax'))
def test_calculator_mtr(cps_subsample):
    rec = Records.cps_constructor(data=cps_subsample)
    calcx = Calculator(policy=Policy(), records=rec)
    calcx.calc_all()
    combinedx = calcx.array('combined')
    c00100x = calcx.array('c00100')
    calc = Calculator(policy=Policy(), records=rec)
    recs_pre_e00200p = copy.deepcopy(calc.array('e00200p'))
    (mtr_ptx, mtr_itx, mtr_cmb) = calc.mtr(variable_str='e00200p',
                                           zero_out_calculated_vars=True)
    recs_post_e00200p = calc.array('e00200p')
    assert np.allclose(recs_post_e00200p, recs_pre_e00200p)
    assert np.allclose(calc.array('combined'), combinedx)
    assert np.allclose(calc.array('c00100'), c00100x)
    assert np.array_equal(mtr_cmb, mtr_ptx) is False
    assert np.array_equal(mtr_ptx, mtr_itx) is False
    with pytest.raises(ValueError):
        calc.mtr(variable_str='bad_income_type')
    (_, _, mtr_combined) = calc.mtr(variable_str='e00200s',
                                    calc_all_already_called=True)
    assert isinstance(mtr_combined, np.ndarray)
    (_, _, mtr_combined) = calc.mtr(variable_str='e00650',
                                    negative_finite_diff=True,
                                    calc_all_already_called=True)
    assert isinstance(mtr_combined, np.ndarray)
    (_, _, mtr_combined) = calc.mtr(variable_str='e00900p',
                                    calc_all_already_called=True)
    assert isinstance(mtr_combined, np.ndarray)
    (_, _, mtr_combined) = calc.mtr(variable_str='e01700',
                                    calc_all_already_called=True)
    assert isinstance(mtr_combined, np.ndarray)
    (_, _, mtr_combined) = calc.mtr(variable_str='e26270',
                                    calc_all_already_called=True)
    assert isinstance(mtr_combined, np.ndarray)
    (_, _, mtr_combined) = calc.mtr(variable_str='e00200p',
                                    calc_all_already_called=True)
    assert np.allclose(mtr_combined, mtr_cmb)
    assert np.allclose(calc.array('combined'), combinedx)
    assert np.allclose(calc.array('c00100'), c00100x)
def test_make_Calculator_raises_on_no_policy(records_2009):
    with pytest.raises(ValueError):
        calc = Calculator(records=records_2009)
Example #46
0
def test_read_bad_json_reform_file(bad1reformfile, bad2reformfile,
                                   bad3reformfile):
    with pytest.raises(ValueError):
        Calculator.read_json_param_objects(bad1reformfile.name, None)
    with pytest.raises(ValueError):
        Calculator.read_json_param_objects(bad2reformfile.name, None)
    with pytest.raises(ValueError):
        Calculator.read_json_param_objects(bad3reformfile.name, None)
    with pytest.raises(ValueError):
        Calculator.read_json_param_objects(list(), None)
    with pytest.raises(ValueError):
        Calculator.read_json_param_objects(None, 'unknown_file_name')
    with pytest.raises(ValueError):
        Calculator.read_json_param_objects(None, list())
Example #47
0
def test_ce_aftertax_income(cps_subsample):
    # test certainty_equivalent() function with con>cmin
    con = 5000
    cmin = 1000
    assert con == round(certainty_equivalent(con, 0, cmin), 6)
    assert con > round(certainty_equivalent((math.log(con) - 0.1), 1, cmin), 6)
    # test certainty_equivalent() function with con<cmin
    con = 500
    cmin = 1000
    assert con == round(certainty_equivalent(con, 0, cmin), 6)
    # test with require_no_agg_tax_change equal to False
    rec = Records.cps_constructor(data=cps_subsample, no_benefits=True)
    cyr = 2020
    # specify calc1 and calc_all() for cyr
    pol = Policy()
    calc1 = Calculator(policy=pol, records=rec)
    calc1.advance_to_year(cyr)
    calc1.calc_all()
    # specify calc2 and calc_all() for cyr
    reform = {2019: {'_II_em': [1000]}}
    pol.implement_reform(reform)
    calc2 = Calculator(policy=pol, records=rec)
    calc2.advance_to_year(cyr)
    calc2.calc_all()
    df1 = calc1.dataframe(['s006', 'combined', 'expanded_income'])
    df2 = calc2.dataframe(['s006', 'combined', 'expanded_income'])
    cedict = ce_aftertax_expanded_income(df1,
                                         df2,
                                         require_no_agg_tax_change=False)
    assert isinstance(cedict, dict)
    np.allclose(cedict['ceeu1'], [55641, 27167, 5726, 2229, 1565],
                atol=0.5,
                rtol=0.0)
    np.allclose(cedict['ceeu2'], [54629, 26698, 5710, 2229, 1565],
                atol=0.5,
                rtol=0.0)
    # test with require_no_agg_tax_change equal to True
    with pytest.raises(ValueError):
        ce_aftertax_expanded_income(df1, df2, require_no_agg_tax_change=True)
    # test with require_no_agg_tax_change equal to False and custom_params
    params = {'crra_list': [0, 2], 'cmin_value': 2000}
    with pytest.raises(ValueError):
        ce_aftertax_expanded_income(df1,
                                    df2,
                                    require_no_agg_tax_change=True,
                                    custom_params=params)
Example #48
0
def test_dec_graph_plots(cps_subsample):
    pol = Policy()
    rec = Records.cps_constructor(data=cps_subsample, no_benefits=True)
    calc1 = Calculator(policy=pol, records=rec)
    year = 2020
    calc1.advance_to_year(year)
    reform = {
        year: {
            '_SS_Earnings_c': [9e99],  # OASDI FICA tax on all earnings
            '_FICA_ss_trt': [0.107484]  # lower rate to keep revenue unchanged
        }
    }
    pol.implement_reform(reform)
    calc2 = Calculator(policy=pol, records=rec)
    calc2.advance_to_year(year)
    assert calc1.current_year == calc2.current_year
    calc1.calc_all()
    calc2.calc_all()
    fig = calc1.decile_graph(calc2)
    assert fig
    dt1, dt2 = calc1.distribution_tables(calc2, 'weighted_deciles')
    dta = dec_graph_data(dt1,
                         dt2,
                         year,
                         include_zero_incomes=True,
                         include_negative_incomes=False)
    assert isinstance(dta, dict)
    dta = dec_graph_data(dt1,
                         dt2,
                         year,
                         include_zero_incomes=False,
                         include_negative_incomes=True)
    assert isinstance(dta, dict)
    dta = dec_graph_data(dt1,
                         dt2,
                         year,
                         include_zero_incomes=False,
                         include_negative_incomes=False)
    assert isinstance(dta, dict)
def test_reform_json_and_output(tests_path):
    """
    Check that each JSON reform file can be converted into a reform dictionary
    that can then be passed to the Policy class implement_reform method that
    generates no parameter_errors.
    Then use each reform to generate static tax results for small set of
    filing units in a single tax_year and compare those results with
    expected results from a CSV-formatted file.
    """

    # pylint: disable=too-many-statements,too-many-locals

    # embedded function used only in test_reform_json_and_output
    def write_res_file(calc, resfilename):
        """
        Write calc output to CSV-formatted file with resfilename.
        """
        varlist = [
            'RECID', 'c00100', 'standard', 'c04800', 'iitax', 'payrolltax'
        ]
        # varnames  AGI    STD         TaxInc    ITAX     PTAX
        stats = calc.dataframe(varlist)
        stats['RECID'] = stats['RECID'].astype(int)
        with open(resfilename, 'w') as resfile:
            stats.to_csv(resfile, index=False, float_format='%.2f')

    # embedded function used only in test_reform_json_and_output
    def res_and_out_are_same(base):
        """
        Return True if base.res.csv and base.out.csv file contents are same;
        return False if base.res.csv and base.out.csv file contents differ.
        """
        resdf = pd.read_csv(base + '.res.csv')
        outdf = pd.read_csv(base + '.out.csv')
        diffs = False
        for col in resdf:
            if col in outdf:
                if not np.allclose(resdf[col], outdf[col]):
                    diffs = True
            else:
                diffs = True
        return not diffs

    # specify Records object containing cases data
    tax_year = 2020
    cases_path = os.path.join(tests_path, '..', 'reforms', 'cases.csv')
    cases = Records(
        data=cases_path,
        start_year=tax_year,  # set raw input data year
        gfactors=None,  # keeps raw data unchanged
        weights=None,
        adjust_ratios=None)
    # specify list of reform failures
    failures = list()
    # specify current-law-policy Calculator object
    calc = Calculator(policy=Policy(), records=cases, verbose=False)
    calc.advance_to_year(tax_year)
    calc.calc_all()
    res_path = cases_path.replace('cases.csv', 'clp.res.csv')
    write_res_file(calc, res_path)
    if res_and_out_are_same(res_path.replace('.res.csv', '')):
        os.remove(res_path)
    else:
        failures.append(res_path)
    del calc
    # read 2017_law.json reform file and specify its parameters dictionary
    pre_tcja_jrf = os.path.join(tests_path, '..', 'reforms', '2017_law.json')
    pre_tcja = Policy.read_json_reform(pre_tcja_jrf)
    # check reform file contents and reform results for each reform
    reforms_path = os.path.join(tests_path, '..', 'reforms', '*.json')
    json_reform_files = glob.glob(reforms_path)
    for jrf in json_reform_files:
        # determine reform's baseline by reading contents of jrf
        with open(jrf, 'r') as rfile:
            jrf_text = rfile.read()
        pre_tcja_baseline = 'Reform_Baseline: 2017_law.json' in jrf_text
        # implement the reform relative to its baseline
        reform = Policy.read_json_reform(jrf_text)
        pol = Policy()  # current-law policy
        if pre_tcja_baseline:
            pol.implement_reform(pre_tcja)
            assert not pol.parameter_errors
        pol.implement_reform(reform)
        assert not pol.parameter_errors
        calc = Calculator(policy=pol, records=cases, verbose=False)
        calc.advance_to_year(tax_year)
        calc.calc_all()
        res_path = jrf.replace('.json', '.res.csv')
        write_res_file(calc, res_path)
        if res_and_out_are_same(res_path.replace('.res.csv', '')):
            os.remove(res_path)
        else:
            failures.append(res_path)
        del calc
    if failures:
        msg = 'Following reforms have res-vs-out differences:\n'
        for ref in failures:
            msg += '{}\n'.format(os.path.basename(ref))
        raise ValueError(msg)
def reform_results(rid, reform_dict, puf_data, reform_2017_law):
    """
    Return actual results of the reform specified by rid and reform_dict.
    """
    # pylint: disable=too-many-locals
    rec = Records(data=puf_data)
    # create baseline Calculator object, calc1
    pol = Policy()
    if reform_dict['baseline'] == '2017_law.json':
        pol.implement_reform(reform_2017_law)
    elif reform_dict['baseline'] == 'policy_current_law.json':
        pass
    else:
        msg = 'illegal baseline value {}'
        raise ValueError(msg.format(reform_dict['baseline']))
    calc1 = Calculator(policy=pol, records=rec, verbose=False)
    # create reform Calculator object, calc2
    start_year = reform_dict['start_year']
    reform = dict()
    for name, value in reform_dict['value'].items():
        reform[name] = {start_year: value}
    pol.implement_reform(reform)
    calc2 = Calculator(policy=pol, records=rec, verbose=False)
    # increment both Calculator objects to reform's start_year
    calc1.advance_to_year(start_year)
    calc2.advance_to_year(start_year)
    # calculate baseline and reform output for several years
    output_type = reform_dict['output_type']
    num_years = 4
    results = list()
    for _ in range(0, num_years):
        calc1.calc_all()
        baseline = calc1.array(output_type)
        calc2.calc_all()
        reform = calc2.array(output_type)
        diff = reform - baseline
        weighted_sum_diff = (diff * calc1.array('s006')).sum() * 1.0e-9
        results.append(weighted_sum_diff)
        calc1.increment_year()
        calc2.increment_year()
    # write actual results to actual_str
    actual_str = '{}'.format(rid)
    for iyr in range(0, num_years):
        actual_str += ',{:.1f}'.format(results[iyr])
    return actual_str
Example #51
0
def test_mtr():
    """
    Test Tax-Calculator marginal tax rates with no policy reform using puf.csv

    Compute histograms for each marginal tax rate income type using
    sample input from the puf.csv file and writing output to a string,
    which is then compared for differences with EXPECTED_MTR_RESULTS.
    """
    # pylint: disable=too-many-locals
    assert len(FICA_MTR_BIN_EDGES) == len(IIT_MTR_BIN_EDGES)
    # construct actual results string, res
    res = ''
    if MTR_NEG_DIFF:
        res += 'MTR computed using NEGATIVE finite_diff.\n'
    else:
        res += 'MTR computed using POSITIVE finite_diff.\n'
    # create a Policy object (clp) containing current-law policy parameters
    clp = Policy()
    clp.set_year(MTR_TAX_YEAR)
    # create a Records object (puf) containing puf.csv input records
    puf = Records(data=PUFCSV_PATH)
    recid = puf.RECID  # pylint: disable=no-member
    # create a Calculator object using clp policy and puf records
    calc = Calculator(policy=clp, records=puf)
    res += '{} = {}\n'.format('Total number of data records', puf.dim)
    res += 'FICA mtr histogram bin edges:\n'
    res += '     {}\n'.format(FICA_MTR_BIN_EDGES)
    res += 'IIT mtr histogram bin edges:\n'
    res += '     {}\n'.format(IIT_MTR_BIN_EDGES)
    inctype_header = 'FICA and IIT mtr histogram bin counts for'
    # compute marginal tax rate (mtr) histograms for each mtr income type
    for inctype in Calculator.MTR_VALID_INCOME_TYPES:
        (mtr_fica, mtr_iit, _) = calc.mtr(income_type_str=inctype,
                                          negative_finite_diff=MTR_NEG_DIFF,
                                          wrt_full_compensation=False)
        res += '{} {}:\n'.format(inctype_header, inctype)
        res += mtr_bin_counts(mtr_fica, FICA_MTR_BIN_EDGES, recid)
        res += mtr_bin_counts(mtr_iit, IIT_MTR_BIN_EDGES, recid)
    # generate differences between actual and expected results
    actual = res.splitlines(True)
    with open(MTRRES_PATH, 'r') as expected_file:
        txt = expected_file.read()
    expected_results = txt.rstrip('\n\t ') + '\n'  # cleanup end of file txt
    expected = expected_results.splitlines(True)
    diff = difflib.unified_diff(expected,
                                actual,
                                fromfile='expected',
                                tofile='actual',
                                n=0)
    # convert diff generator into a list of lines:
    diff_lines = list()
    for line in diff:
        diff_lines.append(line)
    # test failure if there are any diff_lines
    if len(diff_lines) > 0:
        new_filename = '{}{}'.format(MTRRES_PATH[:-10], 'actual.txt')
        with open(new_filename, 'w') as new_file:
            new_file.write(res)
        sys.stdout.write('*************************************************\n')
        sys.stdout.write('*** NEW RESULTS IN pufcsv_mtr_actual.txt FILE ***\n')
        sys.stdout.write('*** if new OK, copy pufcsv_mtr_actual.txt to  ***\n')
        sys.stdout.write('***                 pufcsv_mtr_expect.txt     ***\n')
        sys.stdout.write('***            and rerun test.                ***\n')
        sys.stdout.write('*************************************************\n')
        assert False
Example #52
0
def test_compatible_data(cps_subsample, puf_subsample,
                         allparams, reform_xx,
                         tc_objs, allparams_batch):
    """
    Test that the compatible_data attribute in current_law_policy.json
    is accurate by implementing the min and max values of each parameter
    as reforms and ensuring that revenue differs from baseline when for
    at least one of these reforms when using datasets marked compatible
    and does not differ when using datasets marked as incompatible.
    """
    # pylint: disable=too-many-arguments,too-many-locals
    # pylint: disable=too-many-statements,too-many-branches

    # Get taxcalc objects from tc_objs fixture
    rec_xx, c_xx, puftest = tc_objs

    # These parameters are exempt because they are not active under
    # current law and activating them would deactivate other parameters.
    exempt_from_testing = ['_CG_ec', '_CG_reinvest_ec_rt']

    # Loop through the parameters in allparams_batch
    errmsg = 'ERROR: {} not {} for {}\n'
    errors = ''
    for pname in allparams_batch:
        param = allparams_batch[pname]
        max_listed = param['range']['max']
        # handle links to other params or self
        if isinstance(max_listed, six.string_types):
            if max_listed == 'default':
                max_val = param['value'][-1]
            else:
                max_val = allparams[max_listed]['value'][0]
        if not isinstance(max_listed, six.string_types):
            if isinstance(param['value'][0], list):
                max_val = [max_listed] * len(param['value'][0])
            else:
                max_val = max_listed
        min_listed = param['range']['min']
        if isinstance(min_listed, six.string_types):
            if min_listed == 'default':
                min_val = param['value'][-1]
            else:
                min_val = allparams[min_listed]['value'][0]
        if not isinstance(min_listed, six.string_types):
            if isinstance(param['value'][0], list):
                min_val = [min_listed] * len(param['value'][0])
            else:
                min_val = min_listed
        # create reform dictionaries
        max_reform = copy.deepcopy(reform_xx)
        min_reform = copy.deepcopy(reform_xx)
        max_reform[XX_YEAR][str(pname)] = [max_val]
        min_reform[XX_YEAR][str(pname)] = [min_val]
        # assess whether max reform changes results
        if puftest:
            rec_yy = Records(data=puf_subsample)
        else:
            rec_yy = Records.cps_constructor(data=cps_subsample)
        p_yy = Policy()
        p_yy.implement_reform(max_reform)
        c_yy = Calculator(policy=p_yy, records=rec_yy, verbose=False)
        c_yy.advance_to_year(TEST_YEAR)
        c_yy.calc_all()
        if pname.startswith('_BEN') and pname.endswith('_repeal'):
            max_reform_change = (
                c_yy.weighted_total('benefit_cost_total') -
                c_xx.weighted_total('benefit_cost_total')
            )
        else:
            max_reform_change = (
                c_yy.weighted_total('combined') -
                c_xx.weighted_total('combined')
            )
        min_reform_change = 0
        # assess whether min reform changes results, if max reform did not
        if max_reform_change == 0:
            p_yy = Policy()
            p_yy.implement_reform(min_reform)
            c_yy = Calculator(policy=p_yy, records=rec_xx)
            c_yy.advance_to_year(TEST_YEAR)
            c_yy.calc_all()
            if pname.startswith('_BEN') and pname.endswith('_repeal'):
                min_reform_change = (
                    c_yy.weighted_total('benefit_cost_total') -
                    c_xx.weighted_total('benefit_cost_total')
                )
            else:
                min_reform_change = (
                    c_yy.weighted_total('combined') -
                    c_xx.weighted_total('combined')
                )
            if min_reform_change == 0 and pname not in exempt_from_testing:
                if puftest:
                    if param['compatible_data']['puf'] is not False:
                        errors += errmsg.format(pname, 'False', 'puf')
                else:
                    if param['compatible_data']['cps'] is not False:
                        errors += errmsg.format(pname, 'False', 'cps')
        if max_reform_change != 0 or min_reform_change != 0:
            if puftest:
                if param['compatible_data']['puf'] is not True:
                    errors += errmsg.format(pname, 'True', 'puf')
            else:
                if param['compatible_data']['cps'] is not True:
                    errors += errmsg.format(pname, 'True', 'cps')
    # test failure if any errors
    if errors:
        print(errors)
        assert 'compatible_data' == 'invalid'
Example #53
0
def test_n65(cps_subsample):
    recs = Records.cps_constructor(data=cps_subsample)
    calc = Calculator(policy=Policy(), records=recs)
    assert calc.n65().sum() > 1500
def get_calculator(baseline,
                   calculator_start_year,
                   reform=None,
                   data='cps',
                   gfactors=None,
                   weights=None,
                   records_start_year=RECORDS_START_YEAR):
    '''
    This function creates the tax calculator object for the microsim

    Args:
        baseline (bool): `True` if baseline tax policy
        calculator_start_year (integer): first year of budget window
        reform (dictionary): IIT reform parameters
        data (string or Pandas DataFrame): path to file or DataFrame
            for Tax-Calculator Records object (optional)
        weights (DataFrame): weights DataFrame for Tax-Calculator
            Records object (optional)
        records_start_year (integer): the start year for the data and
            weights dfs

    Returns:
        calc1 (Tax Calculator Calculator object): TC Calculator object
            with a current_year equal to calculator_start_year
    '''
    # create a calculator
    policy1 = Policy()
    if data is not None and "cps" in data:
        records1 = Records.cps_constructor()
        # impute short and long term capital gains if using CPS data
        # in 2012 SOI data 6.587% of CG as short-term gains
        records1.p22250 = 0.06587 * records1.e01100
        records1.p23250 = (1 - 0.06587) * records1.e01100
        # set total capital gains to zero
        records1.e01100 = np.zeros(records1.e01100.shape[0])
    elif data is not None:  # pragma: no cover
        records1 = Records(data=data,
                           gfactors=gfactors,
                           weights=weights,
                           start_year=records_start_year)  # pragma: no cover
    else:
        records1 = Records()  # pragma: no cover

    if baseline:
        # Should not be a reform if baseline is True
        assert not reform

    if not baseline:
        update_policy(policy1, reform)

    # the default set up increments year to 2013
    calc1 = Calculator(records=records1, policy=policy1)
    print('Calculator initial year = ', calc1.current_year)

    # this increment_year function extrapolates all PUF variables to
    # the next year so this step takes the calculator to the start_year
    if calculator_start_year > TC_LAST_YEAR:
        raise RuntimeError("Start year is beyond data extrapolation.")
    while calc1.current_year < calculator_start_year:
        calc1.increment_year()

    return calc1
Example #55
0
def test_reform_json_and_output(tests_path):
    """
    Check that each JSON reform file can be converted into a reform dictionary
    that can then be passed to the Policy class implement_reform() method that
    generates no reform_errors.
    Then use each reform to generate static tax results for small set of
    filing units in a single tax_year and compare those results with
    expected results from a text file.
    """
    # pylint: disable=too-many-statements,too-many-locals
    used_dist_stats = ['c00100',  # AGI
                       'c04600',  # personal exemptions
                       'standard',  # standard deduction
                       'c04800',  # regular taxable income
                       'c05800',  # income tax before credits
                       'iitax',  # income tax after credits
                       'payrolltax',  # payroll taxes
                       'aftertax_income']  # aftertax expanded income
    unused_dist_stats = set(DIST_TABLE_COLUMNS) - set(used_dist_stats)
    renamed_columns = {'c00100': 'AGI',
                       'c04600': 'pexempt',
                       'standard': 'stdded',
                       'c04800': 'taxinc',
                       'c05800': 'tax-wo-credits',
                       'iitax': 'inctax',
                       'payrolltax': 'paytax',
                       'aftertax_income': 'ataxinc'}

    # embedded function used only in test_reform_json_and_output
    def write_distribution_table(calc, resfilename):
        """
        Write abbreviated distribution table calc to file with resfilename.
        """
        dist, _ = calc.distribution_tables(None, groupby='large_income_bins')
        for stat in unused_dist_stats:
            del dist[stat]
        dist = dist[used_dist_stats]
        dist.rename(mapper=renamed_columns, axis='columns', inplace=True)
        pd.options.display.float_format = '{:7.0f}'.format
        with open(resfilename, 'w') as resfile:
            dist.to_string(resfile)

    # embedded function used only in test_reform_json_and_output
    def res_and_out_are_same(base):
        """
        Return true if base.res and base.out file contents are the same;
        return false if base.res and base.out file contents differ.
        """
        with open(base + '.out') as outfile:
            exp_res = outfile.read()
        exp = exp_res.splitlines(True)
        with open(base + '.res') as resfile:
            act_res = resfile.read()
        act = act_res.splitlines(True)
        # assure act & exp line lists have differences less than "small" value
        epsilon = 1e-6
        if sys.version_info.major == 2:
            small = epsilon  # tighter test for Python 2.7
        else:
            small = epsilon  # looser test for Python 3.6 if necessary
        diff_lines = list()
        assert len(act) == len(exp)
        for actline, expline in zip(act, exp):
            if actline == expline:
                continue
            diffs = nonsmall_diff_line_list(actline, expline, small)
            if diffs:
                diff_lines.extend(diffs)
        if diff_lines:
            return False
        return True
    # specify Records object containing cases data
    tax_year = 2020
    cases_path = os.path.join(tests_path, '..', 'reforms', 'cases.csv')
    cases = Records(data=cases_path,
                    gfactors=None,  # keeps raw data unchanged
                    weights=None,
                    adjust_ratios=None,
                    start_year=tax_year)  # set raw input data year
    # specify list of reform failures
    failures = list()
    # specify current-law-policy Calculator object
    calc1 = Calculator(policy=Policy(), records=cases, verbose=False)
    calc1.advance_to_year(tax_year)
    calc1.calc_all()
    res_path = cases_path.replace('cases.csv', 'clp.res')
    write_distribution_table(calc1, res_path)
    if res_and_out_are_same(res_path.replace('.res', '')):
        os.remove(res_path)
    else:
        failures.append(res_path)
    # check reform file contents and reform results for each reform
    reforms_path = os.path.join(tests_path, '..', 'reforms', '*.json')
    json_reform_files = glob.glob(reforms_path)
    for jrf in json_reform_files:
        # read contents of jrf (JSON reform file)
        with open(jrf, 'r') as jfile:
            jrf_text = jfile.read()
        # check that jrf_text has "policy" that can be implemented as a reform
        if '"policy"' in jrf_text:
            gdiffbase = {}
            gdiffresp = {}
            # pylint: disable=protected-access
            policy_dict = (
                Calculator._read_json_policy_reform_text(jrf_text,
                                                         gdiffbase, gdiffresp)
            )
            pol = Policy()
            pol.implement_reform(policy_dict)
            assert not pol.reform_errors
            calc2 = Calculator(policy=pol, records=cases, verbose=False)
            calc2.advance_to_year(tax_year)
            calc2.calc_all()
            res_path = jrf.replace('.json', '.res')
            write_distribution_table(calc2, res_path)
            if res_and_out_are_same(res_path.replace('.res', '')):
                os.remove(res_path)
            else:
                failures.append(res_path)
        else:  # jrf_text has no "policy" key
            msg = 'ERROR: missing policy key in file: {}'
            raise ValueError(msg.format(os.path.basename(jrf)))
    if failures:
        msg = 'Following reforms have res-vs-out differences:\n'
        for ref in failures:
            msg += '{}\n'.format(os.path.basename(ref))
        raise ValueError(msg)
def test_make_Calculator_deepcopy(records_2009):
    parm = Policy()
    calc1 = Calculator(policy=parm, records=records_2009)
    calc2 = copy.deepcopy(calc1)
    assert isinstance(calc2, Calculator)
Example #57
0
def test_behavioral_response_calculator(cps_subsample):
    # create Records object
    rec = Records.cps_constructor(data=cps_subsample)
    year = rec.current_year
    # create Policy object
    pol = Policy()
    # create current-law Calculator object
    calc1 = Calculator(policy=pol, records=rec)
    # implement policy reform
    reform = {year: {'_II_rt7': [0.496],
                     '_PT_rt7': [0.496]}}
    pol.implement_reform(reform)
    # create reform Calculator object with no behavioral response
    behv = Behavior()
    calc2 = Calculator(policy=pol, records=rec, behavior=behv)
    # test incorrect use of Behavior._mtr_xy method
    with pytest.raises(ValueError):
        Behavior._mtr_xy(calc1, calc2, mtr_of='e00200p', tax_type='nonsense')
    # vary substitution and income effects in Behavior object
    behavior0 = {year: {'_BE_sub': [0.0],
                        '_BE_cg': [0.0],
                        '_BE_charity': [[0.0, 0.0, 0.0]]}}
    behv0 = Behavior()
    behv0.update_behavior(behavior0)
    calc2 = Calculator(policy=pol, records=rec, behavior=behv0)
    assert calc2.behavior.has_response() is False
    calc2_behv0 = Behavior.response(calc1, calc2)
    behavior1 = {year: {'_BE_sub': [0.3], '_BE_inc': [-0.1], '_BE_cg': [0.0],
                        '_BE_subinc_wrt_earnings': [True]}}
    behv1 = Behavior()
    behv1.update_behavior(behavior1)
    calc2 = Calculator(policy=pol, records=rec, behavior=behv1)
    assert calc2.behavior.has_response() is True
    epsilon = 1e-9
    assert abs(calc2.behavior.BE_sub - 0.3) < epsilon
    assert abs(calc2.behavior.BE_inc - -0.1) < epsilon
    assert abs(calc2.behavior.BE_cg - 0.0) < epsilon
    calc2_behv1 = Behavior.response(calc1, calc2)
    behavior2 = {year: {'_BE_sub': [0.5], '_BE_cg': [-0.8]}}
    behv2 = Behavior()
    behv2.update_behavior(behavior2)
    calc2 = Calculator(policy=pol, records=rec, behavior=behv2)
    assert calc2.behavior.has_response() is True
    calc2_behv2 = Behavior.response(calc1, calc2, trace=True)
    behavior3 = {year: {'_BE_inc': [-0.2], '_BE_cg': [-0.8]}}
    behv3 = Behavior()
    behv3.update_behavior(behavior3)
    calc2 = Calculator(policy=pol, records=rec, behavior=behv3)
    assert calc2.behavior.has_response() is True
    calc2_behv3 = Behavior.response(calc1, calc2)
    behavior4 = {year: {'_BE_cg': [-0.8]}}
    behv4 = Behavior()
    behv4.update_behavior(behavior4)
    calc2 = Calculator(policy=pol, records=rec, behavior=behv4)
    assert calc2.behavior.has_response() is True
    calc2_behv4 = Behavior.response(calc1, calc2)
    behavior5 = {year: {'_BE_charity': [[-0.5, -0.5, -0.5]]}}
    behv5 = Behavior()
    behv5.update_behavior(behavior5)
    calc2 = Calculator(policy=pol, records=rec, behavior=behv5)
    assert calc2.behavior.has_response() is True
    calc2_behv5 = Behavior.response(calc1, calc2)
    # check that total income tax liability differs across the
    # six sets of behavioral-response elasticities
    assert (calc2_behv0.records.iitax.sum() !=
            calc2_behv1.records.iitax.sum() !=
            calc2_behv2.records.iitax.sum() !=
            calc2_behv3.records.iitax.sum() !=
            calc2_behv4.records.iitax.sum() !=
            calc2_behv5.records.iitax.sum())
def test_Calculator_create_diagnostic_table(records_2009):
    calc = Calculator(policy=Policy(), records=records_2009)
    calc.calc_all()
    adt = create_diagnostic_table(calc)
    assert isinstance(adt, pd.DataFrame)
Example #59
0
def test_create_distribution_tables(pit_fullsample, gst_sample,
                                    cit_crosssample):
    # pylint: disable=too-many-statements,too-many-branches
    # create a current-law Policy object and Calculator object calc1
    rec = Records(data=pit_fullsample)
    grec = GSTRecords(data=gst_sample)
    crec = CorpRecords(data=cit_crosssample)
    pol = Policy()
    calc1 = Calculator(policy=pol,
                       records=rec,
                       gstrecords=grec,
                       corprecords=crec)
    calc1.calc_all()
    # create a policy-reform Policy object and Calculator object calc2
    reform = {2017: {'_rate2': [0.06]}}
    pol.implement_reform(reform)
    calc2 = Calculator(policy=pol,
                       records=rec,
                       gstrecords=grec,
                       corprecords=crec)
    calc2.calc_all()

    test_failure = False

    # test creating various distribution tables

    dist, _ = calc2.distribution_tables(None, 'weighted_deciles')
    assert isinstance(dist, pd.DataFrame)
    tabcol = 'pitax'
    expected = [
        0.000, 0.000, 0.000, 0.000, 0.000, 1.962, 5.711, 14.602, 45.503,
        163.177, 397.795, 1018.520, 1647.270, 331.218, 384.399, 302.903
    ]
    if not np.allclose(dist[tabcol].values, expected):
        test_failure = True
        print('dist xdec', tabcol)
        for val in dist[tabcol].values:
            print('{:.3f},'.format(val))

    tabcol = 'GTI'
    expected = [
        0.000, 0.000, 688.359, 893.687, 1107.005, 1332.670, 1605.580, 1824.545,
        2327.660, 2818.092, 3848.954, 6071.569, 22518.121, 2490.655, 2119.235,
        1461.678
    ]
    if not np.allclose(dist[tabcol].tolist(), expected):
        test_failure = True
        print('dist xdec', tabcol)
        for val in dist[tabcol].values:
            print('{:.3f},'.format(val))

    dist, _ = calc2.distribution_tables(None, 'standard_income_bins')
    assert isinstance(dist, pd.DataFrame)
    tabcol = 'pitax'
    expected = [
        0.000, 0.000, 8.334, 279.113, 542.762, 401.310, 415.751, 0.000, 0.000,
        0.000, 0.000, 1647.270
    ]
    if not np.allclose(dist[tabcol], expected):
        test_failure = True
        print('dist xbin', tabcol)
        for val in dist[tabcol].values:
            print('{:.3f},'.format(val))

    tabcol = 'GTI'
    expected = [
        0.000, 0.000, 5884.790, 7399.792, 4810.526, 2392.643, 2030.370, 0.000,
        0.000, 0.000, 0.000, 22518.121
    ]
    if not np.allclose(dist[tabcol].tolist(), expected):
        test_failure = True
        print('dist xdec', tabcol)
        for val in dist[tabcol].values:
            print('{:.3f},'.format(val))
    """
Example #60
0
def test_diff_table_sum_row(cps_subsample):
    rec = Records.cps_constructor(data=cps_subsample)
    # create a current-law Policy object and Calculator calc1
    pol = Policy()
    calc1 = Calculator(policy=pol, records=rec)
    calc1.calc_all()
    # create a policy-reform Policy object and Calculator calc2
    reform = {2013: {'_II_rt4': [0.56]}}
    pol.implement_reform(reform)
    calc2 = Calculator(policy=pol, records=rec)
    calc2.calc_all()
    # create two difference tables and compare their content
    tdiff1 = create_difference_table(calc1.dataframe(DIFF_VARIABLES),
                                     calc2.dataframe(DIFF_VARIABLES),
                                     'standard_income_bins', 'iitax')
    tdiff2 = create_difference_table(calc1.dataframe(DIFF_VARIABLES),
                                     calc2.dataframe(DIFF_VARIABLES),
                                     'soi_agi_bins', 'iitax')
    non_digit_cols = ['perc_inc', 'perc_cut']
    digit_cols = [c for c in list(tdiff1) if c not in non_digit_cols]
    assert np.allclose(tdiff1[digit_cols][-1:], tdiff2[digit_cols][-1:])
    np.testing.assert_array_equal(tdiff1[non_digit_cols][-1:],
                                  tdiff2[non_digit_cols][-1:])