예제 #1
0
파일: test_tax.py 프로젝트: jpycroft/OG-USA
def test_get_biz_tax():
    # Test function for business tax receipts
    p = Specifications()
    new_param_values = {
        'cit_rate': [0.20],
        'delta_tau_annual': [0.06]
    }
    p.update_specifications(new_param_values)
    p.T = 3
    w = np.array([1.2, 1.1, 1.2])
    Y = np.array([3.0, 7.0, 3.0])
    L = np.array([2.0, 3.0, 2.0])
    K = np.array([5.0, 6.0, 5.0])
    biz_tax = tax.get_biz_tax(w, Y, L, K, p, 'TPI')
    assert np.allclose(biz_tax, np.array([0.0102, 0.11356, 0.0102]))
예제 #2
0
def dynamic_revenue_decomposition(base_params,
                                  base_tpi,
                                  base_ss,
                                  reform_params,
                                  reform_tpi,
                                  reform_ss,
                                  num_years=10,
                                  include_SS=True,
                                  include_overall=True,
                                  include_business_tax=True,
                                  full_break_out=False,
                                  start_year=DEFAULT_START_YEAR,
                                  table_format=None,
                                  path=None):
    '''
    This function decomposes the source of changes in tax revenues to
    determine the percentage change in tax revenues that can be
    attributed to macroeconomic feedback effects.

    Args:
        base_params (OG-Core Specifications class): baseline parameters
            object
        base_tpi (dictionary): TP output from baseline run
        base_ss (dictionary): SS output from baseline run
        reform_params (OG-Core Specifications class): reform parameters
            object
        reform_tpi (dictionary): TP output from reform run
        reform_ss (dictionary): SS output from reform run
        num_years (integer): number of years to include in table
        include_SS (bool): whether to include the steady-state results
            in the table
        include_overall (bool): whether to include results over the
            entire budget window as a column in the table
        include_business_tax (bool): whether to include business tax
            revenue changes in result
        full_break_out (bool): whether to break out behavioral and macro
            effects
        start_year (integer): year to start table
        table_format (string): format to return table in: 'csv', 'tex',
            'excel', 'json', if None, a DataFrame is returned
        path (string): path to save table to

    Returns:
        table (various): table in DataFrame or string format or `None`
            if saved to disk

    .. note:: The decomposition is the following:
        1. Simulate the baseline and reform in OG-Core. Save the
           resulting series of tax revenues. Call these series for the
           baseline and reform A and D, respectively.
        2. Create a third revenue series that is computed using the
           baseline behavior (i.e., `bmat_s` and `n_mat`) and macro
           variables (`tr`, `bq`, `r`, `w`), but with the tax function
           parameter estimates from the reform policy.  Call this
           series B.
        3. Create a fourth revenue series that is computed using the
           reform behavior (i.e., `bmat_s` and `n_mat`) and tax
           functions estimated on the reform tax policy, but
           the macro variables (`tr`, `bq`, `r`, `w`) from the baseline.
           Call this series C.
        3. Calculate the percentage difference between B and A -- call
           this the "static" change from the macro model.  Calculate the
           percentage difference between C and B -- call this the
           behavioral effects.  Calculate the percentage difference
           between D and C -- call this the macroeconomic effect.  The
           full dynamic effect is difference between C and A.

        One can apply the percentage difference from the macro feedback
        effect to ("static") revenue estimates from the policy change
        to produce an estimate of the revenue including macro feedback.

    '''
    assert isinstance(start_year, (int, np.integer))
    assert isinstance(num_years, (int, np.integer))
    # Make sure both runs cover same time period
    assert (base_params.start_year == reform_params.start_year)
    year_vec = np.arange(start_year, start_year + num_years)
    start_index = start_year - base_params.start_year
    year_list = year_vec.tolist()
    if include_overall:
        year_list.append(str(year_vec[0]) + '-' + str(year_vec[-1]))
    if include_SS:
        year_list.append('SS')
    table_dict = {'Year': year_list}
    T, S, J = base_params.T, base_params.S, base_params.J
    base_etr_params_4D = np.tile(
        base_params.etr_params[:T, :, :].reshape(
            T, S, 1, base_params.etr_params.shape[2]), (1, 1, J, 1))
    reform_etr_params_4D = np.tile(
        reform_params.etr_params[:T, :, :].reshape(
            T, S, 1, reform_params.etr_params.shape[2]), (1, 1, J, 1))
    tax_rev_dict = {'indiv': {}, 'biz': {}, 'total': {}}
    indiv_liab = {}
    # Baseline IIT + payroll tax liability
    indiv_liab['A'] = tax.income_tax_liab(
        base_tpi['r_hh'][:T], base_tpi['w'][:T], base_tpi['bmat_s'],
        base_tpi['n_mat'][:T, :, :], base_ss['factor_ss'], 0, None, 'TPI',
        base_params.e, base_etr_params_4D, base_params)
    # IIT + payroll tax liability using baseline behavior and macros
    # with the reform tax functions (this is the OG-Core static estimate)
    indiv_liab['B'] = tax.income_tax_liab(
        base_tpi['r_hh'][:T], base_tpi['w'][:T], base_tpi['bmat_s'],
        base_tpi['n_mat'][:T, :, :], base_ss['factor_ss'], 0, None, 'TPI',
        base_params.e, reform_etr_params_4D, base_params)
    # IIT + payroll tax liability using reform behavior and baseline
    # macros
    indiv_liab['C'] = tax.income_tax_liab(
        base_tpi['r_hh'][:T], base_tpi['w'][:T], reform_tpi['bmat_s'],
        reform_tpi['n_mat'][:T, :, :], base_ss['factor_ss'], 0, None, 'TPI',
        reform_params.e, reform_etr_params_4D, reform_params)
    # IIT + payroll tax liability from the reform simulation
    indiv_liab['D'] = tax.income_tax_liab(
        reform_tpi['r_hh'][:T], reform_tpi['w'][:T], reform_tpi['bmat_s'],
        reform_tpi['n_mat'][:T, :, :], base_ss['factor_ss'], 0, None, 'TPI',
        reform_params.e, reform_etr_params_4D, reform_params)
    # Business tax revenue from the baseline simulation
    tax_rev_dict['biz']['A'] = tax.get_biz_tax(base_tpi['w'][:T],
                                               base_tpi['Y'][:T],
                                               base_tpi['L'][:T],
                                               base_tpi['K'][:T], base_params,
                                               'TPI')
    # Business tax revenue found using baseline behavior and macros with
    # the reform tax rates
    tax_rev_dict['biz']['B'] = tax.get_biz_tax(base_tpi['w'][:T],
                                               base_tpi['Y'][:T],
                                               base_tpi['L'][:T],
                                               base_tpi['K'][:T],
                                               reform_params, 'TPI')
    # Business tax revenue found using the reform behavior and baseline
    # macros with the reform tax rates
    tax_rev_dict['biz']['C'] = tax.get_biz_tax(base_tpi['w'][:T],
                                               reform_tpi['Y'][:T],
                                               reform_tpi['L'][:T],
                                               reform_tpi['K'][:T],
                                               reform_params, 'TPI')
    # Business tax revenue from the reform
    tax_rev_dict['biz']['D'] = tax.get_biz_tax(reform_tpi['w'][:T],
                                               reform_tpi['Y'][:T],
                                               reform_tpi['L'][:T],
                                               reform_tpi['K'][:T],
                                               reform_params, 'TPI')
    pop_weights = (np.squeeze(base_params.lambdas) *
                   np.tile(np.reshape(base_params.omega[:T, :], (T, S, 1)),
                           (1, 1, J)))
    for k in indiv_liab.keys():
        tax_rev_dict['indiv'][k] = ((indiv_liab[k] *
                                     pop_weights).sum(1).sum(1))
        tax_rev_dict['total'][k] = (tax_rev_dict['indiv'][k] +
                                    tax_rev_dict['biz'][k])
    results_for_table = {'indiv': {}, 'biz': {}, 'total': {}}
    for type in ['indiv', 'biz', 'total']:
        # Rate change effect
        pct_change1 = (((tax_rev_dict[type]['B'] - tax_rev_dict[type]['A']) /
                        tax_rev_dict[type]['A']) * 100)
        # Behavior effect
        pct_change2 = (((tax_rev_dict[type]['C'] - tax_rev_dict[type]['B']) /
                        tax_rev_dict[type]['B']) * 100)
        # Macro effect
        pct_change3 = (((tax_rev_dict[type]['D'] - tax_rev_dict[type]['C']) /
                        tax_rev_dict[type]['C']) * 100)
        # Dynamic effect (behavior + macro)
        pct_change4 = (((tax_rev_dict[type]['D'] - tax_rev_dict[type]['B']) /
                        tax_rev_dict[type]['B']) * 100)
        # Total change in tax revenue (rates + behavior + macro)
        pct_change5 = (((tax_rev_dict[type]['D'] - tax_rev_dict[type]['A']) /
                        tax_rev_dict[type]['A']) * 100)
        pct_change_overall1 = ((
            (tax_rev_dict[type]['B'][start_index:start_index +
                                     num_years].sum() - tax_rev_dict[type]['A']
             [start_index:start_index + num_years].sum()) /
            tax_rev_dict[type]['A'][start_index:start_index + num_years].sum())
                               * 100)
        pct_change_overall2 = ((
            (tax_rev_dict[type]['C'][start_index:start_index +
                                     num_years].sum() - tax_rev_dict[type]['B']
             [start_index:start_index + num_years].sum()) /
            tax_rev_dict[type]['B'][start_index:start_index + num_years].sum())
                               * 100)
        pct_change_overall3 = ((
            (tax_rev_dict[type]['D'][start_index:start_index +
                                     num_years].sum() - tax_rev_dict[type]['C']
             [start_index:start_index + num_years].sum()) /
            tax_rev_dict[type]['C'][start_index:start_index + num_years].sum())
                               * 100)
        pct_change_overall4 = ((
            (tax_rev_dict[type]['D'][start_index:start_index +
                                     num_years].sum() - tax_rev_dict[type]['B']
             [start_index:start_index + num_years].sum()) /
            tax_rev_dict[type]['B'][start_index:start_index + num_years].sum())
                               * 100)
        pct_change_overall5 = ((
            (tax_rev_dict[type]['D'][start_index:start_index +
                                     num_years].sum() - tax_rev_dict[type]['A']
             [start_index:start_index + num_years].sum()) /
            tax_rev_dict[type]['A'][start_index:start_index + num_years].sum())
                               * 100)
        if include_overall:
            results_for_table[type][1] = np.append(
                pct_change1[start_index:start_index + num_years],
                pct_change_overall1)
            results_for_table[type][2] = np.append(
                pct_change2[start_index:start_index + num_years],
                pct_change_overall2)
            results_for_table[type][3] = np.append(
                pct_change3[start_index:start_index + num_years],
                pct_change_overall3)
            results_for_table[type][4] = np.append(
                pct_change4[start_index:start_index + num_years],
                pct_change_overall4)
            results_for_table[type][5] = np.append(
                pct_change5[start_index:start_index + num_years],
                pct_change_overall5)
        if include_SS:
            results_for_table[type][1] = np.append(results_for_table[type][1],
                                                   pct_change1[-1])
            results_for_table[type][2] = np.append(results_for_table[type][2],
                                                   pct_change2[-1])
            results_for_table[type][3] = np.append(results_for_table[type][3],
                                                   pct_change3[-1])
            results_for_table[type][4] = np.append(results_for_table[type][4],
                                                   pct_change4[-1])
            results_for_table[type][5] = np.append(results_for_table[type][5],
                                                   pct_change5[-1])
    if full_break_out:
        if include_business_tax:
            table_dict = {
                'Year': year_list,
                # IIT and Payroll Taxes
                'IIT: Pct Change due to tax rates':
                results_for_table['indiv'][1],
                'IIT: Pct Change due to behavior':
                results_for_table['indiv'][2],
                'IIT: Pct Change due to macro': results_for_table['indiv'][3],
                'IIT: Overall Pct Change in taxes':
                results_for_table['indiv'][5],
                # Business Taxes
                'CIT: Pct Change due to tax rates':
                results_for_table['biz'][1],
                'CIT: Pct Change due to behavior': results_for_table['biz'][2],
                'CIT: Pct Change due to macro': results_for_table['biz'][3],
                'CIT: Overall Pct Change in taxes':
                results_for_table['biz'][5],
                # All Taxes
                'All: Pct Change due to tax rates':
                results_for_table['total'][1],
                'All: Pct Change due to behavior':
                results_for_table['total'][2],
                'All: Pct Change due to macro': results_for_table['total'][3],
                'All: Overall Pct Change in taxes':
                results_for_table['total'][5]
            }
        else:
            table_dict = {
                'Year': year_list,
                'Pct Change due to tax rates': results_for_table['indiv'][1],
                'Pct Change due to behavior': results_for_table['indiv'][2],
                'Pct Change due to macro': results_for_table['indiv'][3],
                'Overall Pct Change in taxes': results_for_table['indiv'][5]
            }
    else:
        if include_business_tax:
            table_dict = {
                'Year': year_list,
                # 'IIT and Payroll Taxes:':
                # np.ones(results_for_table['indiv'][1].shape[0]) * np.nan,
                'IIT: Pct Change due to tax rates':
                results_for_table['indiv'][1],
                'IIT: Pct Change due to dynamics':
                results_for_table['indiv'][4],
                'IIT: Overall Pct Change in taxes':
                results_for_table['indiv'][5],
                # 'Business Taxes:':
                # np.ones(results_for_table['biz'][1].shape[0]) * np.nan,
                'CIT: Pct Change due to tax rates':
                results_for_table['biz'][1],
                'CIT: Pct Change due to dynamics': results_for_table['biz'][4],
                'CIT: Overall Pct Change in taxes':
                results_for_table['biz'][5],
                # 'All Taxes:':
                # np.ones(results_for_table['total'][1].shape[0]) * np.nan,
                'All: Pct Change due to tax rates':
                results_for_table['total'][1],
                'All: Pct Change due to dynamics':
                results_for_table['total'][4],
                'All: Overall Pct Change in taxes':
                results_for_table['total'][5]
            }
        else:
            table_dict = {
                'Year': year_list,
                'Pct Change due to tax rates': results_for_table['indiv'][1],
                'Pct Change due to dynamics': results_for_table['indiv'][4],
                'Overall Pct Change in taxes': results_for_table['indiv'][5]
            }
    # Make df with dict so can use pandas functions
    table_df = pd.DataFrame.from_dict(
        table_dict, orient='columns').set_index('Year').transpose()
    table_df.reset_index(inplace=True)
    table_df.rename(columns={'index': 'Variable'}, inplace=True)
    table = save_return_table(table_df, table_format, path)

    return table
예제 #3
0
def revenue(r, w, b, n, bq, c, Y, L, K, factor, ubi, theta, etr_params, p,
            method):
    r'''
    Calculate aggregate tax revenue.

    .. math::
        R_{t} = \sum_{s=E}^{E+S}\sum_{j=0}^{J}\omega_{s,t}\lambda_{j}
        (T_{j,s,t} + \tau^{p}_{t}w_{t}e_{j,s}n_{j,s,t} - \theta_{j}
        w_{t} + \tau^{bq}bq_{j,s,t} + \tau^{c}_{s,t}c_{j,s,t} +
        \tau^{w}_{t}b_{j,s,t}) + \tau^{b}_{t}(Y_{t}-w_{t}L_{t}) -
        \tau^{b}_{t}\delta^{\tau}_{t}K^{\tau}_{t}

    Args:
        r (array_like): the real interest rate
        w (array_like): the real wage rate
        b (Numpy array): household savings
        n (Numpy array): household labor supply
        bq (Numpy array): household bequests received
        c (Numpy array): household consumption
        Y (array_like): aggregate output
        L (array_like): aggregate labor
        K (array_like): aggregate capital
        factor (scalar): scaling factor converting model units to
            dollars
        ubi (array_like): universal basic income household distributions
        theta (Numpy array): social security replacement rate for each
            lifetime income group
        etr_params (Numpy array): paramters of the effective tax rate
            functions
        p (OG-Core Specifications object): model parameters
        method (str): adjusts calculation dimensions based on 'SS' or
            'TPI'

    Returns:
        total_tax_revenue (array_like): aggregate tax revenue
        iit_payroll_tax_revenue (array_like): aggregate income and
            payroll tax revenue
        agg_pension_outlays (array_like): aggregate outlays for gov't
            pensions
        UBI_outlays (array_like): aggregate universal basic income (UBI)
            outlays
        bequest_tax_revenue (array_like): aggregate bequest tax revenue
        wealth_tax_revenue (array_like): aggregate wealth tax revenue
        cons_tax_revenue (array_like): aggregate consumption tax revenue
        business_tax_revenue (array_like): aggregate business tax
            revenue
        payroll_tax_revenue (array_like): aggregate payroll tax revenue
        iit_tax_revenue (array_like): aggregate income tax revenue

    '''
    inc_pay_tax_liab = tax.income_tax_liab(r, w, b, n, factor, 0, None, method,
                                           p.e, etr_params, p)
    pension_benefits = tax.pension_amount(w, n, theta, 0, None, False, method,
                                          p.e, p)
    bq_tax_liab = tax.bequest_tax_liab(r, b, bq, 0, None, method, p)
    w_tax_liab = tax.wealth_tax_liab(r, b, 0, None, method, p)
    if method == 'SS':
        pop_weights = np.transpose(p.omega_SS * p.lambdas)
        iit_payroll_tax_revenue = (inc_pay_tax_liab * pop_weights).sum()
        agg_pension_outlays = (pension_benefits * pop_weights).sum()
        UBI_outlays = (ubi * pop_weights).sum()
        wealth_tax_revenue = (w_tax_liab * pop_weights).sum()
        bequest_tax_revenue = (bq_tax_liab * pop_weights).sum()
        cons_tax_revenue = (p.tau_c[-1, :, :] * c * pop_weights).sum()
        payroll_tax_revenue = (p.frac_tax_payroll[-1] *
                               iit_payroll_tax_revenue)
    elif method == 'TPI':
        pop_weights = (np.squeeze(p.lambdas) *
                       np.tile(np.reshape(p.omega[:p.T, :], (p.T, p.S, 1)),
                               (1, 1, p.J)))
        iit_payroll_tax_revenue = (inc_pay_tax_liab *
                                   pop_weights).sum(1).sum(1)
        agg_pension_outlays = (pension_benefits * pop_weights).sum(1).sum(1)
        UBI_outlays = (ubi[:p.T, :, :] * pop_weights).sum(1).sum(1)
        wealth_tax_revenue = (w_tax_liab * pop_weights).sum(1).sum(1)
        bequest_tax_revenue = (bq_tax_liab * pop_weights).sum(1).sum(1)
        cons_tax_revenue = (p.tau_c[:p.T, :, :] * c *
                            pop_weights).sum(1).sum(1)
        payroll_tax_revenue = (p.frac_tax_payroll[:p.T] *
                               iit_payroll_tax_revenue)
    business_tax_revenue = tax.get_biz_tax(w, Y, L, K, p, method)
    iit_revenue = iit_payroll_tax_revenue - payroll_tax_revenue

    total_tax_revenue = (iit_payroll_tax_revenue + wealth_tax_revenue +
                         bequest_tax_revenue + cons_tax_revenue +
                         business_tax_revenue)

    return (total_tax_revenue, iit_payroll_tax_revenue, agg_pension_outlays,
            UBI_outlays, bequest_tax_revenue, wealth_tax_revenue,
            cons_tax_revenue, business_tax_revenue, payroll_tax_revenue,
            iit_revenue)