def test_consumption_response(cps_subsample):
    consump = Consumption()
    mpc = 0.5
    consumption_response = {'MPC_e20400': {2013: mpc}}
    consump.update_consumption(consumption_response)
    # test incorrect call to response method
    with pytest.raises(ValueError):
        consump.response(list(), 1)
    # test correct call to response method
    rec = Records.cps_constructor(data=cps_subsample)
    pre = copy.deepcopy(rec.e20400)
    consump.response(rec, 1.0)
    post = rec.e20400
    actual_diff = post - pre
    expected_diff = np.ones(rec.array_length) * mpc
    assert np.allclose(actual_diff, expected_diff)
    # compute earnings mtr with no consumption response
    rec = Records.cps_constructor(data=cps_subsample)
    ided0 = copy.deepcopy(rec.e20400)
    calc0 = Calculator(policy=Policy(), records=rec, consumption=None)
    (mtr0_ptax, mtr0_itax, _) = calc0.mtr(variable_str='e00200p',
                                          wrt_full_compensation=False)
    assert np.allclose(calc0.array('e20400'), ided0)
    # compute earnings mtr with consumption response
    calc1 = Calculator(policy=Policy(), records=rec, consumption=consump)
    mtr1_ptax, mtr1_itax, _ = calc1.mtr(variable_str='e00200p',
                                        wrt_full_compensation=False)
    assert np.allclose(calc1.array('e20400'), ided0)
    # confirm that payroll mtr values are no different
    assert np.allclose(mtr1_ptax, mtr0_ptax)
    # confirm that all mtr with cons-resp are no greater than without cons-resp
    assert np.all(np.less_equal(np.around(mtr1_itax, decimals=5),
                                np.around(mtr0_itax, decimals=5)))
    # confirm that some mtr with cons-resp are less than without cons-resp
    assert np.any(np.less(mtr1_itax, mtr0_itax))
def test_calc_and_used_vars(tests_path):
    """
    Runs two kinds of tests on variables used in the calcfunctions.py file:

    (1) Checks that each var in Records.CALCULATED_VARS is actually calculated

    If test (1) fails, a variable in Records.CALCULATED_VARS was not
    calculated in any function in the calcfunctions.py file.  With the
    exception of a few variables listed in this test, all
    Records.CALCULATED_VARS must be calculated in the calcfunctions.py file.

    (2) Check that each variable that is calculated in a function and
    returned by that function is an argument of that function.
    """
    # pylint: disable=too-many-locals
    funcpath = os.path.join(tests_path, '..', 'calcfunctions.py')
    gfd = GetFuncDefs()
    fnames, fargs, cvars, rvars = gfd.visit(ast.parse(open(funcpath).read()))
    # Test (1):
    # .. create set of vars that are actually calculated in calcfunctions.py
    all_cvars = set()
    for fname in fnames:
        if fname == 'BenefitSurtax':
            continue  # because BenefitSurtax is not really a function
        all_cvars.update(set(cvars[fname]))
    # .. add to all_cvars set variables calculated in Records class
    all_cvars.update(set(['num', 'sep', 'exact']))
    # .. add to all_cvars set variables calculated elsewhere
    all_cvars.update(set(['mtr_paytax', 'mtr_inctax']))
    all_cvars.update(set(['benefit_cost_total', 'benefit_value_total']))
    # .. check that each var in Records.CALCULATED_VARS is in the all_cvars set
    Records.read_var_info()
    found_error1 = False
    if not Records.CALCULATED_VARS <= all_cvars:
        msg1 = ('all Records.CALCULATED_VARS not calculated '
                'in calcfunctions.py\n')
        for var in Records.CALCULATED_VARS - all_cvars:
            found_error1 = True
            msg1 += 'VAR NOT CALCULATED: {}\n'.format(var)
    # Test (2):
    faux_functions = ['EITCamount', 'ComputeBenefit', 'BenefitPrograms',
                      'BenefitSurtax', 'BenefitLimitation']
    found_error2 = False
    msg2 = 'calculated & returned variables are not function arguments\n'
    for fname in fnames:
        if fname in faux_functions:
            continue  # because fname is not a genuine function
        crvars_set = set(cvars[fname]) & set(rvars[fname])
        if not crvars_set <= set(fargs[fname]):
            found_error2 = True
            for var in crvars_set - set(fargs[fname]):
                msg2 += 'FUNCTION,VARIABLE: {} {}\n'.format(fname, var)
    # Report errors for the two tests:
    if found_error1 and found_error2:
        raise ValueError('{}\n{}'.format(msg1, msg2))
    if found_error1:
        raise ValueError(msg1)
    if found_error2:
        raise ValueError(msg2)
def test_validity_of_name_lists():
    assert len(DIST_TABLE_COLUMNS) == len(DIST_TABLE_LABELS)
    Records.read_var_info()
    assert set(DIST_VARIABLES).issubset(Records.CALCULATED_VARS | {'s006'})
    extra_vars_set = set(['num_returns_StandardDed',
                          'num_returns_ItemDed',
                          'num_returns_AMT'])
    assert (set(DIST_TABLE_COLUMNS) - set(DIST_VARIABLES)) == extra_vars_set
def test_correct_Records_instantiation():
    rec1 = Records(data=TAXDATA, blowup_factors=None, weights=WEIGHTS)
    assert rec1
    assert np.all(rec1.MARS != 0)
    assert rec1.current_year == Records.PUF_YEAR
    sum_e00200_in_puf_year = rec1.e00200.sum()
    rec1.set_current_year(Records.PUF_YEAR + 1)
    sum_e00200_in_puf_year_plus_one = rec1.e00200.sum()
    assert sum_e00200_in_puf_year_plus_one == sum_e00200_in_puf_year
    bf_df = pd.read_csv(Records.BLOWUP_FACTORS_PATH)
    rec2 = Records(data=TAXDATA, blowup_factors=bf_df, weights=None)
    assert rec2
    assert np.all(rec2.MARS != 0)
    assert rec2.current_year == Records.PUF_YEAR
def test_correct_Records_instantiation_sample(puf_1991, weights_1991):
    sample = puf_1991.sample(frac=0.10)
    rec1 = Records(data=sample, blowup_factors=None, weights=weights_1991)
    assert rec1
    assert np.all(rec1.MARS != 0)
    assert rec1.current_year == Records.PUF_YEAR
    sum_e00200_in_puf_year = rec1.e00200.sum()
    rec1.set_current_year(Records.PUF_YEAR + 1)
    sum_e00200_in_puf_year_plus_one = rec1.e00200.sum()
    assert sum_e00200_in_puf_year_plus_one == sum_e00200_in_puf_year
    bf_df = pd.read_csv(Records.BLOWUP_FACTORS_PATH)
    rec2 = Records(data=sample, blowup_factors=bf_df, weights=None)
    assert rec2
    assert np.all(rec2.MARS != 0)
    assert rec2.current_year == Records.PUF_YEAR
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_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_make_calculator_with_multiyear_reform(cps_subsample):
    """
    Test Calculator class ctor with multi-year 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 = {2015: {}, 2016: {}}
    reform[2015]['_II_em'] = [5000, 6000]  # reform values for 2015 and 2016
    reform[2015]['_II_em_cpi'] = False
    reform[2016]['_STD_Aged'] = [[1600, 1300, 1600, 1300, 1600]]
    pol.implement_reform(reform)
    # create a Calculator object using this policy-reform
    calc = Calculator(policy=pol, records=rec)
    # check that Policy object embedded in Calculator object is correct
    assert pol.num_years == Policy.DEFAULT_NUM_YEARS
    assert calc.current_year == year
    assert calc.policy_param('II_em') == 3950
    exp_II_em = [3900, 3950, 5000] + [6000] * (Policy.DEFAULT_NUM_YEARS - 3)
    assert np.allclose(calc.policy_param('_II_em'),
                       np.array(exp_II_em))
    calc.increment_year()
    calc.increment_year()
    assert calc.current_year == 2016
    assert np.allclose(calc.policy_param('STD_Aged'),
                       np.array([1600, 1300, 1600, 1300, 1600]))
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_make_calculator_raises_on_no_policy(cps_subsample):
    """
    Test Calculator ctor error with no policy argument.
    """
    rec = Records.cps_constructor(data=cps_subsample)
    with pytest.raises(ValueError):
        Calculator(records=rec)
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)
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_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.
    """
    recs = 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=recs)
    hc_calc.calc_all()
    hc_taxes = hc_calc.dataframe(['iitax', 'payrolltax'])
    del hc_calc
    # 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=recs)
    bs_calc.calc_all()
    bs_taxes = bs_calc.dataframe(['iitax', 'payrolltax'])
    del bs_calc
    # compare calculated taxes generated by the two reforms
    assert np.allclose(hc_taxes['payrolltax'], bs_taxes['payrolltax'])
    assert np.allclose(hc_taxes['iitax'], bs_taxes['iitax'])
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_dec_graph_plots(cps_subsample):
    pol = Policy()
    rec = Records.cps_constructor(data=cps_subsample)
    calc1 = Calculator(policy=pol, records=rec)
    year = 2020
    calc1.advance_to_year(year)
    reform = {
        'SS_Earnings_c': {year: 9e99},  # OASDI FICA tax on all earnings
        'FICA_ss_trt': {year: 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_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_blowup():
    pol1 = Policy()
    assert pol1.current_year == Policy.JSON_START_YEAR
    rec1 = Records(data=TAXDATA, weights=WEIGHTS)
    assert rec1.current_year == Records.PUF_YEAR
    calc1 = Calculator(policy=pol1, records=rec1, sync_years=True)
    assert calc1.records.current_year == Policy.JSON_START_YEAR
    pol2 = Policy()
    assert pol2.current_year == Policy.JSON_START_YEAR
    rec2 = Records(data=TAXDATA, weights=WEIGHTS)
    assert rec2.current_year == Records.PUF_YEAR
    rec2.set_current_year(Policy.JSON_START_YEAR)
    assert rec2.current_year == Policy.JSON_START_YEAR
    calc2 = Calculator(policy=pol2, records=rec2, sync_years=False)
    assert calc2.policy.current_year == Policy.JSON_START_YEAR
    assert calc2.records.current_year == Policy.JSON_START_YEAR
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_make_calculator_deepcopy(cps_subsample):
    """
    Test deepcopy of Calculator object.
    """
    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_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:])
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_ce_aftertax_income(cps_subsample):
    """
    Test ce_aftertax_income method.
    """
    rec = Records.cps_constructor(data=cps_subsample)
    pol = Policy()
    calc1 = Calculator(policy=pol, records=rec)
    pol.implement_reform({2013: {'_SS_Earnings_c': [9e99]}})
    calc2 = Calculator(policy=pol, records=rec)
    res = calc1.ce_aftertax_income(calc2)
    assert isinstance(res, dict)
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_mtr_graph(cps_subsample):
    """
    Test mtr_graph method.
    """
    recs = Records.cps_constructor(data=cps_subsample)
    calc = Calculator(policy=Policy(), records=recs)
    fig = calc.mtr_graph(calc,
                         mars=2,
                         income_measure='wages',
                         mtr_measure='ptax')
    assert fig
    fig = calc.mtr_graph(calc,
                         income_measure='agi',
                         mtr_measure='itax')
    assert fig
def test_privacy_of_embedded_objects(cps_subsample):
    """
    Test privacy of objects embedded in Calculator object.
    """
    recs = Records.cps_constructor(data=cps_subsample)
    calc = Calculator(policy=Policy(), records=recs)
    var1 = var2 = var3 = 0
    # pylint: disable=protected-access
    with pytest.raises(AttributeError):
        var1 = calc.__policy.current_year
    with pytest.raises(AttributeError):
        var2 = calc.__records.s006
    with pytest.raises(AttributeError):
        var3 = calc.__consumption.current_year
    assert var1 == var2 == var3
def fixture_tc_objs(request, reform_xx, puf_subsample, cps_subsample):
    """
    Fixture for creating Tax-Calculator objects that use the PUF and
    use the CPS (called only twice: once for PUF and once for CPS)
    """
    puftest = request.param
    p_xx = Policy()
    p_xx.implement_reform(reform_xx, raise_errors=False)
    if puftest:
        rec_xx = Records(data=puf_subsample)
    else:
        rec_xx = Records.cps_constructor(data=cps_subsample)
    c_xx = Calculator(policy=p_xx, records=rec_xx)
    c_xx.advance_to_year(TEST_YEAR)
    c_xx.calc_all()
    return rec_xx, c_xx, puftest
def test_difference_table(cps_subsample):
    """
    Test difference_table method.
    """
    cyr = 2014
    pol = Policy()
    recs = Records.cps_constructor(data=cps_subsample)
    calc1 = Calculator(policy=pol, records=recs)
    assert calc1.current_year == cyr
    reform = {cyr: {'_SS_Earnings_c': [9e99]}}
    pol.implement_reform(reform)
    calc2 = Calculator(policy=pol, records=recs)
    assert calc2.current_year == cyr
    calc1.calc_all()
    calc2.calc_all()
    diff = calc1.difference_table(calc2, 'weighted_deciles', 'iitax')
    assert isinstance(diff, pd.DataFrame)
def test_calculator_mtr(cps_subsample):
    """
    Test Calculator mtr method.
    """
    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_xtr_graph_plot(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', '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)
Exemple #30
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)
def test_Calculator_results_consistency(pit_fullsample, cit_crosssample):
    # generate calculated-variable dataframe for full sample in second year
    recs = Records(data=pit_fullsample)
    crecs = CorpRecords(data=cit_crosssample)
    calc = Calculator(policy=Policy(), records=recs, corprecords=crecs)
    assert isinstance(calc, Calculator)
    assert calc.current_year == Policy.JSON_START_YEAR
    calc.advance_to_year(Policy.JSON_START_YEAR + 1)
    assert calc.current_year == Policy.JSON_START_YEAR + 1
    calc.calc_all()
    varlist = list(Records.CALCULATED_VARS)
    vdf = calc.dataframe(varlist)
    assert isinstance(vdf, pd.DataFrame)
    # check consistency of calculated results individual by individual
    assert np.allclose(vdf['TTI'], vdf['GTI'] - vdf['deductions'])
    assert np.allclose(vdf['Aggregate_Income'],
                       np.maximum(0., vdf['TTI'] - vdf['TI_special_rates']))
    assert np.all(vdf['Tax_ST_CG_RATE1'] >= 0.)
    assert np.all(vdf['Tax_ST_CG_RATE2'] >= 0.)
    assert np.all(vdf['Tax_ST_CG_APPRATE'] == 0.)
    assert np.allclose(vdf['Total_Tax_STCG'],
                       (vdf['Tax_ST_CG_RATE1'] + vdf['Tax_ST_CG_RATE2'] +
                        vdf['Tax_ST_CG_APPRATE']))
    assert np.all(vdf['Tax_LT_CG_RATE1'] >= 0.)
    assert np.all(vdf['Tax_LT_CG_RATE2'] >= 0.)
    assert np.allclose(vdf['Total_Tax_LTCG'],
                       vdf['Tax_LT_CG_RATE1'] + vdf['Tax_LT_CG_RATE2'])
    assert np.allclose(vdf['Total_Tax_Cap_Gains'],
                       vdf['Total_Tax_STCG'] + vdf['Total_Tax_LTCG'])
    assert np.all(vdf['tax_Aggregate_Income'] >= 0.)
    assert np.all(vdf['tax_TI_special_rates'] >= 0.)
    assert np.all(vdf['rebate_agri'] >= 0.)
    exp = vdf['tax_Aggregate_Income'] + vdf['tax_TI_special_rates']
    exp -= vdf['rebate_agri']
    assert np.allclose(vdf['tax_TTI'], exp)
    assert np.all(vdf['rebate'] >= 0.)
    assert np.all(vdf['surcharge'] >= 0.)
    assert np.all(vdf['cess'] >= 0.)
    assert np.all(vdf['pitax'] >= 0.)
    exp = vdf['tax_TTI'] - vdf['rebate'] + vdf['surcharge'] + vdf['cess']
    assert np.allclose(vdf['pitax'], exp)
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()
    std5 = 2000
    reform = {
        'STD_Aged': {
            2015: [std5, std5, std5, std5, std5]
        },
        'II_em': {
            2015: 5000,
            2016: 6000
        },
        'II_em-indexed': {
            2016: 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)
Exemple #33
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)
    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)
Exemple #34
0
def test_puf_var_stats(tests_path, puf_fullsample):
    """
    Main logic of test.
    """
    # create a baseline Policy object containing 2017_law.json parameters
    pre_tcja_jrf = os.path.join(tests_path, '..', 'reforms', '2017_law.json')
    pre_tcja = Calculator.read_json_param_objects(pre_tcja_jrf, None)
    baseline_policy = Policy()
    baseline_policy.implement_reform(pre_tcja['policy'])
    # create a Calculator object using baseline_policy and full puf.csv sample
    rec = Records(data=puf_fullsample)
    calc = Calculator(policy=baseline_policy, records=rec, verbose=False)
    # create base tables
    table_mean = create_base_table(tests_path)
    table_corr = copy.deepcopy(table_mean)
    del table_corr['description']
    # add statistics to tables
    year_headers = ['description']
    for year in range(Policy.JSON_START_YEAR, Policy.LAST_BUDGET_YEAR + 1):
        assert year == calc.policy_current_year()
        year_headers.append(str(year))
        calc.calc_all()
        calculate_mean_stats(calc, table_mean, year)
        if year == 2016:
            calculate_corr_stats(calc, table_corr)
        if year < Policy.LAST_BUDGET_YEAR:
            calc.increment_year()
    # write tables to new CSV files
    mean_path = os.path.join(tests_path, MEAN_FILENAME + '-new')
    table_mean.sort_index(inplace=True)
    table_mean.to_csv(mean_path, header=year_headers, float_format='%8.0f')
    corr_path = os.path.join(tests_path, CORR_FILENAME + '-new')
    table_corr.sort_index(inplace=True)
    table_corr.to_csv(corr_path,
                      float_format='%8.2f',
                      columns=table_corr.index)
    # compare new and old CSV files for nonsmall differences
    mean_msg = differences(mean_path, mean_path[:-4], 'MEAN')
    corr_msg = differences(corr_path, corr_path[:-4], 'CORR')
    if mean_msg or corr_msg:
        raise ValueError(mean_msg + corr_msg)
Exemple #35
0
def test_agg():
    """
    Test Tax-Calculator aggregate taxes with no policy reform using puf.csv
    """
    # create a Policy object (clp) containing current-law policy parameters
    clp = Policy()
    # create a Records object (puf) containing puf.csv input records
    puf = Records(data=PUFCSV_PATH)
    # create a Calculator object using clp policy and puf records
    calc = Calculator(policy=clp, records=puf)
    # create aggregate diagnostic table (adt) as a Pandas DataFrame object
    adt = calc.diagnostic_table(num_years=10)
    # convert adt results to a string with a trailing EOL character
    adtstr = adt.to_string() + '\n'
    # generate differences between actual and expected results
    actual = adtstr.splitlines(True)
    with open(AGGRES_PATH, 'r') as expected_file:
        txt = expected_file.read()
    expected_results = txt.rstrip('\n\t ') + '\n'  # cleanup end of file txt
    expected = expected_results.splitlines(True)
    diff = difflib.unified_diff(expected,
                                actual,
                                fromfile='expected',
                                tofile='actual',
                                n=0)
    # convert diff generator into a list of lines:
    diff_lines = list()
    for line in diff:
        diff_lines.append(line)
    # test failure if there are any diff_lines
    if len(diff_lines) > 0:
        new_filename = '{}{}'.format(AGGRES_PATH[:-10], 'actual.txt')
        with open(new_filename, 'w') as new_file:
            new_file.write(adtstr)
        sys.stdout.write('*************************************************\n')
        sys.stdout.write('*** NEW RESULTS IN pufcsv_agg_actual.txt FILE ***\n')
        sys.stdout.write('*** if new OK, copy pufcsv_agg_actual.txt to  ***\n')
        sys.stdout.write('***                 pufcsv_agg_expect.txt     ***\n')
        sys.stdout.write('***            and rerun test.                ***\n')
        sys.stdout.write('*************************************************\n')
        assert False
def test_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)
    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 = {'II_em': {2019: 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)
def test_make_calculator(cps_subsample):
    pol = Policy(start_year=2014, num_years=9)
    assert pol.current_year == 2014
    rec = Records.cps_constructor(data=cps_subsample)
    consump = Consumption()
    consump.update_consumption({2014: {'_MPC_e20400': [0.05]}})
    assert consump.current_year == 2013
    calc = Calculator(policy=pol,
                      records=rec,
                      consumption=consump,
                      behavior=Behavior())
    assert calc.current_year == 2014
    # 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())
Exemple #38
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)
def test_make_calculator(cps_subsample):
    start_year = Policy.JSON_START_YEAR
    sim_year = 2018
    pol = Policy()
    assert pol.current_year == start_year
    rec = Records.cps_constructor(data=cps_subsample)
    consump = Consumption()
    consump.update_consumption({sim_year: {'_MPC_e20400': [0.05]}})
    assert consump.current_year == start_year
    calc = Calculator(policy=pol, records=rec,
                      consumption=consump, behavior=Behavior())
    assert calc.current_year == Records.CPSCSV_YEAR
    # test incorrect Calculator instantiation:
    with pytest.raises(ValueError):
        Calculator(policy=None, records=rec)
    with pytest.raises(ValueError):
        Calculator(policy=pol, records=None)
    with pytest.raises(ValueError):
        Calculator(policy=pol, records=rec, behavior=list())
    with pytest.raises(ValueError):
        Calculator(policy=pol, records=rec, consumption=list())
Exemple #40
0
def test_dec_graph_plot(cps_subsample):
    pol = Policy()
    rec = Records.cps_constructor(data=cps_subsample)
    calc1 = Calculator(policy=pol, records=rec)
    year = 2020
    calc1.advance_to_year(year)
    reform = {
        year: {
            '_SS_Earnings_c': [9e99],  # OASDI FICA tax on all earnings
            '_FICA_ss_trt': [0.107484]  # lower rate to keep revenue unchanged

        }
    }
    pol.implement_reform(reform)
    calc2 = Calculator(policy=pol, records=rec)
    calc2.advance_to_year(year)
    assert calc1.current_year == calc2.current_year
    calc1.calc_all()
    calc2.calc_all()
    fig = calc1.decile_graph(calc2)
    assert fig
Exemple #41
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, no_benefits=True)
    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())
Exemple #42
0
def taxcalc_clp_results():
    """
    Use taxcalc package on this computer to compute aggregate income tax
    and payroll tax revenues for years beginning with MIN_START_YEAR and
    ending with MAX_START_YEAR+NUMBER_OF_YEARS-1 for current-law policy.
    Return two aggregate revenue dictionaries indexed by calendar year.
    """
    calc = Calculator(policy=Policy(),
                      records=Records(data=PUF_PATH),
                      verbose=False)
    nyears = MAX_START_YEAR + NUMBER_OF_YEARS - MIN_START_YEAR - 1
    adts = list()
    for iyr in range(-1, nyears - 1):
        calc.calc_all()
        adts.append(create_diagnostic_table(calc))
        if iyr < nyears:
            calc.increment_year()
    adt = pd.concat(adts, axis=1)
    # note that adt is Pandas DataFrame object
    return (adt.xs('Ind Income Tax ($b)').to_dict(),
            adt.xs('Payroll Taxes ($b)').to_dict())
def test_incorrect_Records_instantiation(cps_subsample):
    with pytest.raises(ValueError):
        recs = Records(data=list())
    with pytest.raises(ValueError):
        recs = Records(data=cps_subsample, gfactors=list())
    with pytest.raises(ValueError):
        recs = Records(data=cps_subsample, gfactors=None, weights=list())
    with pytest.raises(ValueError):
        recs = Records(data=cps_subsample, gfactors=None, weights=None,
                       start_year=list())
    with pytest.raises(ValueError):
        recs = Records(data=cps_subsample, gfactors=None, weights=None,
                       adjust_ratios=list())
    with pytest.raises(ValueError):
        recs = Records(data=cps_subsample, gfactors=None, weights=None,
                       adjust_ratios=None, benefits=list())
Exemple #44
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.
    """
    recs = 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=recs)
    hc_calc.calc_all()
    hc_taxes = hc_calc.dataframe(['iitax', 'payrolltax'])
    del hc_calc
    # 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=recs)
    bs_calc.calc_all()
    bs_taxes = bs_calc.dataframe(['iitax', 'payrolltax'])
    del bs_calc
    # compare calculated taxes generated by the two reforms
    assert np.allclose(hc_taxes['payrolltax'], bs_taxes['payrolltax'])
    assert np.allclose(hc_taxes['iitax'], bs_taxes['iitax'])
def xtest_diff_table_sum_row(pit_subsample):
    rec = Records(data=pit_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 = {2017: {'_rate2': [0.06]}}
    pol.implement_reform(reform)
    calc2 = Calculator(policy=pol, records=rec)
    calc2.calc_all()
    # create two difference tables and compare their content
    tdiff1 = create_difference_table(calc1.dataframe(DIFF_VARIABLES),
                                     calc2.dataframe(DIFF_VARIABLES),
                                     'standard_income_bins', 'iitax')
    tdiff2 = create_difference_table(calc1.dataframe(DIFF_VARIABLES),
                                     calc2.dataframe(DIFF_VARIABLES),
                                     'soi_agi_bins', 'iitax')
    non_digit_cols = ['perc_inc', 'perc_cut']
    digit_cols = [c for c in list(tdiff1) if c not in non_digit_cols]
    assert np.allclose(tdiff1[digit_cols][-1:], tdiff2[digit_cols][-1:])
    np.allclose(tdiff1[non_digit_cols][-1:], tdiff2[non_digit_cols][-1:])
def test_qbid_calculation():
    """
    Test Calculator's QBID calculations using the six example filing units
    specified in Table 1 of this TPC publication: "Navigating the New
    Pass-Through Provisions: A Technical Explanation" by William G. Gale
    and Aaron Krupkin (January 31, 2018), which is available at this URL:
      https://www.taxpolicycenter.org/publications/
      navigating-new-pass-through-provisions-technical-explanation/full
    """
    # In constructing the TPC example filing units, assume that the taxpayer
    # has business income in the form of e26270/e02000 income and no earnings,
    # and that the spouse has no business income and only earnings.
    TPC_YEAR = 2018
    TPC_VARS = (
        'RECID,MARS,e00200s,e00200,e26270,e02000,PT_SSTB_income,'
        'PT_binc_w2_wages,PT_ubia_property,pre_qbid_taxinc,qbid\n'
    )
    TPC_FUNITS = (
        '1,2, 99000, 99000,75000,75000,1,20000,90000,150000,15000.00\n'
        '2,2,349000,349000,75000,75000,1,20000,90000,400000, 1612.50\n'
        '3,2,524000,524000,75000,75000,1,20000,90000,575000,    0.00\n'
        '4,2, 99000, 99000,75000,75000,0,20000,90000,150000,15000.00\n'
        '5,2,349000,349000,75000,75000,0,20000,90000,400000,10750.00\n'
        '6,2,524000,524000,75000,75000,0,20000,90000,575000,10000.00\n'
    )
    # generate actual Calculator pre-qbid taxinc and qbid amounts
    tpc_df = pd.read_csv(StringIO(TPC_VARS + TPC_FUNITS))
    recs = Records(data=tpc_df, start_year=TPC_YEAR,
                   gfactors=None, weights=None)
    calc = Calculator(policy=Policy(), records=recs)
    assert calc.current_year == TPC_YEAR
    calc.calc_all()
    varlist = ['RECID', 'c00100', 'standard', 'c04470', 'qbided']
    tc_df = calc.dataframe(varlist)
    # compare actual amounts with expected amounts from TPC publication
    act_taxinc = tc_df.c00100 - np.maximum(tc_df.standard, tc_df.c04470)
    exp_taxinc = tpc_df.pre_qbid_taxinc
    assert np.allclose(act_taxinc, exp_taxinc)
    assert np.allclose(tc_df.qbided, tpc_df.qbid)
def 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.records.payrolltax, crt_calc.records.payrolltax)
    assert np.allclose(hc_calc.records.iitax, crt_calc.records.iitax)
def test_distribution_tables(cps_subsample):
    pol = Policy()
    recs = Records.cps_constructor(data=cps_subsample)
    calc1 = Calculator(policy=pol, records=recs)
    assert calc1.current_year == 2014
    calc1.calc_all()
    dt1, dt2 = calc1.distribution_tables(None)
    assert isinstance(dt1, pd.DataFrame)
    assert dt2 is None
    dt1, dt2 = calc1.distribution_tables(calc1)
    assert isinstance(dt1, pd.DataFrame)
    assert isinstance(dt2, pd.DataFrame)
    reform = {2014: {'_UBI_u18': [1000],
                     '_UBI_1820': [1000],
                     '_UBI_21': [1000]}}
    pol.implement_reform(reform)
    assert not pol.reform_errors
    calc2 = Calculator(policy=pol, records=recs)
    calc2.calc_all()
    dt1, dt2 = calc1.distribution_tables(calc2)
    assert isinstance(dt1, pd.DataFrame)
    assert isinstance(dt2, pd.DataFrame)
def test_make_calculator_with_policy_reform(cps_subsample):
    rec = Records.cps_constructor(data=cps_subsample)
    year = rec.current_year
    # create a Policy object and apply a policy reform
    pol = Policy()
    reform = {2013: {'_II_em': [4000], '_II_em_cpi': False,
                     '_STD_Aged': [[1600, 1300, 1300, 1600, 1600]],
                     '_STD_Aged_cpi': False}}
    pol.implement_reform(reform)
    # create a Calculator object using this policy reform
    calc = Calculator(policy=pol, records=rec)
    # check that Policy object embedded in Calculator object is correct
    assert calc.current_year == year
    assert calc.param('II_em') == 4000
    assert np.allclose(calc.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.param('_STD_Aged'),
                       np.array(exp_STD_Aged))
    assert np.allclose(calc.param('STD_Aged'),
                       np.array([1600, 1300, 1300, 1600, 1600]))
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)
Exemple #51
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_make_Calculator_with_multiyear_reform():
    # create a Policy object and apply a policy reform
    policy3 = Policy()
    reform3 = {2015: {}}
    reform3[2015]['_STD_Aged'] = [[1600, 1300, 1600, 1300, 1600, 1300]]
    reform3[2015]['_II_em'] = [5000, 6000]  # reform values for 2015 and 2016
    reform3[2015]['_II_em_cpi'] = False
    policy3.implement_reform(reform3)
    # create a Calculator object using this policy-reform
    puf = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009)
    calc3 = Calculator(policy=policy3, records=puf)
    # check that Policy object embedded in Calculator object is correct
    assert calc3.current_year == 2013
    assert calc3.policy.II_em == 3900
    assert calc3.policy.num_years == Policy.DEFAULT_NUM_YEARS
    exp_II_em = [3900, 3950, 5000] + [6000] * (Policy.DEFAULT_NUM_YEARS - 3)
    assert_array_equal(calc3.policy._II_em, np.array(exp_II_em))
    calc3.increment_year()
    calc3.increment_year()
    assert calc3.current_year == 2015
    assert_array_equal(calc3.policy.STD_Aged,
                       np.array([1600, 1300, 1600, 1300, 1600, 1300]))
Exemple #53
0
def main():
    parser = argparse.ArgumentParser(
        prog="python stats_summary.py",
        description=('Generates a files for either statistics summary'
                     'on a 10-year span or correlation matrix of current'
                     'tax year. Adding either sum-stats or correlation'
                     'as an argument after python Stats_Summary.py --output'))
    parser.add_argument('--output', default='sum-stats')
    args = parser.parse_args()
    # create a calculator
    tax_dta1 = pd.read_csv(PUF_PATH)
    records1 = Records(tax_dta1)
    policy1 = Policy(start_year=2013)
    calc1 = Calculator(records=records1, policy=policy1)
    table = creat_table_base()
    if args.output == 'sum-stats':
        gen_sum_stats(table, calc=calc1)
    elif args.output == 'correlation':
        gen_correlation(table, calc=calc1)
    else:
        print("no such output available")
    return 0
Exemple #54
0
def test_atr_graph_data(cps_subsample):
    pol = Policy()
    rec = Records.cps_constructor(data=cps_subsample, no_benefits=True)
    calc = Calculator(policy=pol, records=rec)
    year = calc.current_year
    with pytest.raises(ValueError):
        atr_graph_data(None, year, mars='bad')
    with pytest.raises(ValueError):
        atr_graph_data(None, year, mars=0)
    with pytest.raises(ValueError):
        atr_graph_data(None, year, mars=list())
    with pytest.raises(ValueError):
        atr_graph_data(None, year, atr_measure='badtax')
    calc.calc_all()
    vdf = calc.dataframe(['s006', 'MARS', 'expanded_income'])
    tax = 0.20 * np.ones_like(vdf['expanded_income'])
    vdf['tax1'] = tax
    vdf['tax2'] = tax
    gdata = atr_graph_data(vdf, year, mars=1, atr_measure='combined')
    gdata = atr_graph_data(vdf, year, atr_measure='itax')
    gdata = atr_graph_data(vdf, year, atr_measure='ptax')
    assert isinstance(gdata, dict)
def test_ID_StateLocal_HC_vs_CRT(cps_subsample):
    """
    Test that a cap on state/local income and sales tax deductions at 0 percent
    of AGI is equivalent to a complete haircut on the same state/local tax
    deductions.
    """
    rec = Records.cps_constructor(data=cps_subsample)
    # specify state/local complete haircut reform policy and Calculator object
    hc_policy = Policy()
    hc_reform = {'ID_StateLocalTax_hc': {2013: 1.0}}
    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_policy = Policy()
    crt_reform = {'ID_StateLocalTax_crt': {2013: 0.0}}
    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_dec_graph_plot(cps_subsample):
    pol = Policy()
    rec = Records.cps_constructor(data=cps_subsample)
    calc1 = Calculator(policy=pol, records=rec)
    year = 2020
    reform = {
        year: {
            '_SS_Earnings_c': [9e99],  # OASDI FICA tax on all earnings
            '_FICA_ss_trt': [0.107484]  # lower rate to keep revenue unchanged
        }
    }
    pol.implement_reform(reform)
    calc2 = Calculator(policy=pol, records=rec)
    calc1.advance_to_year(year)
    with pytest.raises(ValueError):
        dec_graph_data(calc1, calc2)
    calc2.advance_to_year(year)
    gdata = dec_graph_data(calc1, calc2)
    assert isinstance(gdata, dict)
    deciles = gdata['bars'].keys()
    assert len(deciles) == 14
    gplot = dec_graph_plot(gdata, xlabel='', ylabel='')
    assert gplot
def test_Calculator_create_distribution_table():
    policy = Policy()
    puf = Records(data=TAXDATA, weights=WEIGHTS, start_year=2009)
    calc = Calculator(policy=policy, records=puf)
    calc.calc_all()
    dist_labels = [
        'Returns', 'AGI', 'Standard Deduction Filers', 'Standard Deduction',
        'Itemizers', 'Itemized Deduction', 'Personal Exemption',
        'Taxable Income', 'Regular Tax', 'AMTI', 'AMT Filers', 'AMT',
        'Tax before Credits', 'Non-refundable Credits',
        'Tax before Refundable Credits', 'Refundable Credits',
        'Individual Income Tax Liabilities', 'Payroll Tax Liablities',
        'Combined Payroll and Individual Income Tax Liabilities'
    ]
    dt1 = create_distribution_table(calc,
                                    groupby="weighted_deciles",
                                    result_type="weighted_sum")
    dt1.columns = dist_labels
    dt2 = create_distribution_table(calc,
                                    groupby="small_income_bins",
                                    result_type="weighted_avg")
    assert isinstance(dt1, pd.DataFrame)
    assert isinstance(dt2, pd.DataFrame)
def test_make_calculator_with_multiyear_reform(cps_subsample):
    rec = Records.cps_constructor(data=cps_subsample)
    year = rec.current_year
    # create a Policy object and apply a policy reform
    pol = Policy()
    reform = {2015: {}, 2016: {}}
    reform[2015]['_II_em'] = [5000, 6000]  # reform values for 2015 and 2016
    reform[2015]['_II_em_cpi'] = False
    reform[2016]['_STD_Aged'] = [[1600, 1300, 1600, 1300, 1600]]
    pol.implement_reform(reform)
    # create a Calculator object using this policy-reform
    calc = Calculator(policy=pol, records=rec)
    # check that Policy object embedded in Calculator object is correct
    assert calc.current_year == year
    assert calc.policy.II_em == 3950
    assert calc.policy.num_years == Policy.DEFAULT_NUM_YEARS
    exp_II_em = [3900, 3950, 5000] + [6000] * (Policy.DEFAULT_NUM_YEARS - 3)
    assert np.allclose(calc.policy._II_em, np.array(exp_II_em))
    calc.increment_year()
    calc.increment_year()
    assert calc.current_year == 2016
    assert np.allclose(calc.policy.STD_Aged,
                       np.array([1600, 1300, 1600, 1300, 1600]))
def test_make_calculator(cps_subsample):
    """
    Test Calculator class ctor.
    """
    start_year = Policy.JSON_START_YEAR
    sim_year = 2018
    pol = Policy()
    assert pol.current_year == start_year
    rec = Records.cps_constructor(data=cps_subsample)
    consump = Consumption()
    consump.update_consumption({'MPC_e20400': {sim_year: 0.05}})
    assert consump.current_year == start_year
    calc = Calculator(policy=pol, records=rec,
                      consumption=consump, verbose=True)
    assert calc.data_year == Records.CPSCSV_YEAR
    assert calc.current_year == Records.CPSCSV_YEAR
    # test incorrect Calculator instantiation:
    with pytest.raises(ValueError):
        Calculator(policy=None, records=rec)
    with pytest.raises(ValueError):
        Calculator(policy=pol, records=None)
    with pytest.raises(ValueError):
        Calculator(policy=pol, records=rec, consumption=list())
def test_puf_var_stats(tests_path, puf_fullsample):
    """
    Main logic of test.
    """
    # create a Calculator object
    rec = Records(data=puf_fullsample)
    calc = Calculator(policy=Policy(), records=rec, verbose=False)
    # create base tables
    table_mean = create_base_table(tests_path)
    table_corr = copy.deepcopy(table_mean)
    del table_corr['description']
    # add statistics to tables
    year_headers = ['description']
    for year in range(Policy.JSON_START_YEAR, Policy.LAST_BUDGET_YEAR + 1):
        assert year == calc.policy.current_year
        year_headers.append(str(year))
        calc.calc_all()
        calculate_mean_stats(calc, table_mean, year)
        if year == 2016:
            calculate_corr_stats(calc, table_corr)
        if year < Policy.LAST_BUDGET_YEAR:
            calc.increment_year()
    # write tables to new CSV files
    mean_path = os.path.join(tests_path, MEAN_FILENAME + '-new')
    table_mean.sort_index(inplace=True)
    table_mean.to_csv(mean_path, header=year_headers, float_format='%8.0f')
    corr_path = os.path.join(tests_path, CORR_FILENAME + '-new')
    table_corr.sort_index(inplace=True)
    table_corr.to_csv(corr_path,
                      float_format='%8.2f',
                      columns=table_corr.index)
    # compare new and old CSV files for differences no larger than small value
    mean_msg = differences(mean_path, mean_path[:-4], 'MEAN', small=1.000001)
    corr_msg = differences(corr_path, corr_path[:-4], 'CORR', small=0.010001)
    if mean_msg or corr_msg:
        raise ValueError(mean_msg + corr_msg)