Beispiel #1
0
def ETR_income(r, w, b, n, factor, e, etr_params, p):
    '''
    Calculates effective personal income tax rate.

    Args:
        r (array_like): real interest rate
        w (array_like): real wage rate
        b (Numpy array): savings
        n (Numpy array): labor supply
        factor (scalar): scaling factor converting model units to
            dollars
        e (Numpy array): effective labor units
        etr_params (Numpy array): effective tax rate function parameters
        p (OG-Core Specifications object): model parameters

    Returns:
        tau (Numpy array): effective tax rate on total income

    '''
    X = (w * e * n) * factor
    Y = (r * b) * factor

    tau = get_tax_rates(etr_params,
                        X,
                        Y,
                        None,
                        p.tax_func_type,
                        'etr',
                        for_estimation=False)

    return tau
Beispiel #2
0
def MTR_income(r, w, b, n, factor, mtr_capital, e, etr_params, mtr_params, p):
    r'''
    Generates the marginal tax rate on labor income for households.

    Args:
        r (array_like): real interest rate
        w (array_like): real wage rate
        b (Numpy array): savings
        n (Numpy array): labor supply
        factor (scalar): scaling factor converting model units to
            dollars
        mtr_capital (bool): whether to compute the marginal tax rate on
            capital income or labor income
        e (Numpy array): effective labor units
        etr_params (Numpy array): effective tax rate function parameters
        p (OG-Core Specifications object): model parameters

    Returns:
        tau (Numpy array): marginal tax rate on income source

    '''
    X = (w * e * n) * factor
    Y = (r * b) * factor

    if p.analytical_mtrs:
        tau = get_tax_rates(etr_params,
                            X,
                            Y,
                            None,
                            p.tax_func_type,
                            'mtr',
                            p.analytical_mtrs,
                            mtr_capital,
                            for_estimation=False)
    else:
        tau = get_tax_rates(mtr_params,
                            X,
                            Y,
                            None,
                            p.tax_func_type,
                            'mtr',
                            p.analytical_mtrs,
                            mtr_capital,
                            for_estimation=False)

    return tau
Beispiel #3
0
def test_get_tax_rates(tax_func_type, rate_type, params, analytical_mtrs,
                       mtr_capital, for_estimation, expected):
    '''
    Teset of txfunc.get_tax_rates() function.  There are 6 cases to
    test:
    1) DEP function, for estimation
    2) DEP function, not for estimation
    3) GS function, etr
    4) GS function, mtr
    5) DEP_totalinc function, for estimation
    6) DEP_totalinc function, not for estimation
    '''
    wgts = np.array([0.1, 0.25, 0.55, 0.1])
    X = np.array([32.0, 44.0, 1.6, 0.4])
    Y = np.array([32.0, 55.0, 0.9, 0.03])
    print('Params = ', params)
    test_txrates = txfunc.get_tax_rates(params, X, Y, wgts, tax_func_type,
                                        rate_type, analytical_mtrs,
                                        mtr_capital, for_estimation)

    assert np.allclose(test_txrates, expected)
def get_tax_fn(
    year,
    start_year,
    tax_param_list,
    age=None,
    tax_func_type=["DEP"],
    rate_type="etr",
    over_labinc=True,
    other_inc_val=1000,
    max_inc_amt=1000000,
    data_list=None,
    labels=["1st Functions"],
    title=None,
    path=None,
):
    # Check that inputs are valid
    year, start_year = int(year), int(start_year)
    assert year >= start_year
    # if list of tax function types less than list of params, assume
    # all the same functional form
    if len(tax_func_type) < len(tax_param_list):
        tax_func_type = [tax_func_type[0]] * len(tax_param_list)
    for i, v in enumerate(tax_func_type):
        assert v in ["DEP", "DEP_totalinc", "GS", "linear"]
    assert rate_type in ["etr", "mtrx", "mtry"]
    assert len(tax_param_list) == len(labels)

    # Set age and year to look at
    if age is not None:
        assert isinstance(age, int)
        s = age - 21
    else:
        s = 0  # if not age-specific, all ages have the same values
    t = year - start_year

    # create rate_key to correspond to keys in tax func dicts
    rate_key = "tfunc_" + rate_type + "_params_S"

    # Set income range to plot over (min income value hard coded to 5)
    inc_sup = np.exp(np.linspace(np.log(5), np.log(max_inc_amt), 100))
    # Set income value for other income
    inc_fix = other_inc_val

    if over_labinc:
        key1 = "total_labinc"
        X = inc_sup
        Y = inc_fix
    else:
        key1 = "total_capinc"
        X = inc_fix
        Y = inc_sup

    # get tax rates for each point in the income support and plot
    for i, tax_params in enumerate(tax_param_list):
        rates = txfunc.get_tax_rates(
            tax_params[rate_key][s, t, :],
            X,
            Y,
            None,
            tax_func_type[i],
            rate_type,
            for_estimation=False,
        )

    return lambda x, y: txfunc.get_tax_rates(
        tax_params[rate_key][s, t, :],
        x,
        y,
        None,
        tax_func_type[i],
        rate_type,
        for_estimation=False,
    )
Beispiel #5
0
def plot_2D_taxfunc(year,
                    start_year,
                    tax_param_list,
                    age=None,
                    tax_func_type=['DEP'],
                    rate_type='etr',
                    over_labinc=True,
                    other_inc_val=1000,
                    max_inc_amt=1000000,
                    data_list=None,
                    labels=['1st Functions'],
                    title=None,
                    path=None):
    '''
    This function plots OG-Core tax functions in two dimensions.
    The tax rates are plotted over capital or labor income, as
    entered by the user.

    Args:
        year (int): year of policy tax functions represent
        start_year (int): first year tax functions estimated for in
            tax_param_list elements
        tax_param_list (list): list of arrays containing tax function
            parameters
        age (int): age for tax functions to plot, use None if tax
            function parameters were not age specific
        tax_func_type (list): list of strings in ["DEP", "DEP_totalinc",
            "GS", "linear"] and specifies functional form of tax functions
            in tax_param_list
        rate_type (str): string that is in ["etr", "mtrx", "mtry"] and
            determines the type of tax rate that is plotted
        over_labinc (bool): indicates that x-axis of the plot is over
            labor income, if False then plot is over capital income
        other_inc_val (scalar): dollar value at which to hold constant
            the amount of income that is not represented on the x-axis
        max_inc_amt (scalar): largest income amount to represent on the
            x-axis of the plot
        data_list (list): list of DataFrames with data to scatter plot
            with tax functions, needs to be of format output from
            ogcore.get_micro_data.get_data
        labels (list): list of labels for tax function parameters
        title (str): title for the plot
        path (str): path to which to save plot, if None then figure
            returned

    Returns:
        fig (Matplotlib plot object): plot of tax functions

    '''
    # Check that inputs are valid
    assert isinstance(start_year, int)
    assert isinstance(year, int)
    assert (year >= start_year)
    # if list of tax function types less than list of params, assume
    # all the same functional form
    if len(tax_func_type) < len(tax_param_list):
        tax_func_type = [tax_func_type[0]] * len(tax_param_list)
    for i, v in enumerate(tax_func_type):
        assert (v in ['DEP', 'DEP_totalinc', 'GS', 'linear'])
    assert (rate_type in ['etr', 'mtrx', 'mtry'])
    assert (len(tax_param_list) == len(labels))

    # Set age and year to look at
    if age is not None:
        assert isinstance(age, int)
        s = age - 21
    else:
        s = 0  # if not age-specific, all ages have the same values
    t = year - start_year

    # create rate_key to correspond to keys in tax func dicts
    rate_key = 'tfunc_' + rate_type + '_params_S'

    # Set income range to plot over (min income value hard coded to 5)
    inc_sup = np.exp(np.linspace(np.log(5), np.log(max_inc_amt), 100))
    # Set income value for other income
    inc_fix = other_inc_val

    if over_labinc:
        key1 = 'total_labinc'
        X = inc_sup
        Y = inc_fix
    else:
        key1 = 'total_capinc'
        X = inc_fix
        Y = inc_sup

    # get tax rates for each point in the income support and plot
    fig, ax = plt.subplots()
    for i, tax_params in enumerate(tax_param_list):
        rates = txfunc.get_tax_rates(tax_params[rate_key][s, t, :],
                                     X,
                                     Y,
                                     None,
                                     tax_func_type[i],
                                     rate_type,
                                     for_estimation=False)
        plt.plot(inc_sup, rates, label=labels[i])

    # plot raw data (if passed)
    if data_list is not None:
        rate_type_dict = {
            'etr': 'etr',
            'mtrx': 'mtr_labinc',
            'mtry': 'mtr_capinc'
        }
        # censor data to range of the plot
        for d, data in enumerate(data_list):
            data_to_plot = data[str(year)].copy()
            if age is not None:
                data_to_plot.drop(
                    data_to_plot[data_to_plot['age'] != age].index,
                    inplace=True)
            # other censoring
            data_to_plot.drop(
                data_to_plot[data_to_plot[key1] > max_inc_amt].index,
                inplace=True)
            # other censoring used in txfunc.py
            data_to_plot = txfunc.tax_data_sample(data_to_plot)
            # set number of bins to 100 or bins of $1000 dollars
            n_bins = min(100, np.floor_divide(max_inc_amt, 1000))
            # need to compute weighted averages by group...
            wm = lambda x: np.average(
                x, weights=data_to_plot.loc[x.index, "weight"])
            data_to_plot['inc_bin'] = pd.cut(data_to_plot[key1], n_bins)
            groups = pd.DataFrame(
                data_to_plot.groupby(["inc_bin"
                                      ]).agg(rate=(rate_type_dict[rate_type],
                                                   wm),
                                             income=(key1, wm)))
            plt.scatter(groups['income'], groups['rate'], alpha=0.1)
    # add legend, labels, etc to plot
    plt.legend(loc='center right')
    if title:
        plt.title(title)
    if over_labinc:
        plt.xlabel(r'Labor income')
    else:
        plt.xlabel(r'Capital income')
    plt.ylabel(VAR_LABELS[rate_type])
    if path is None:
        return fig
    else:
        plt.savefig(path)
Beispiel #6
0
def txfunc_graph(s, t, df, X, Y, txrates, rate_type, tax_func_type,
                 get_tax_rates, params_to_plot, output_dir):
    '''
    This function creates a 3D plot of the fitted tax function against
    the data.

    Args:
        s (int): age of individual, >= 21
        t (int): year of analysis, >= 2016
        df (Pandas DataFrame): 11 variables with N observations of tax
            rates
        X (Pandas DataSeries): labor income
        Y (Pandas DataSeries): capital income
        Y (Pandas DataSeries): tax rates from the data
        rate_type (str): type of tax rate: mtrx, mtry, etr
        tax_func_type (str): functional form of tax functions
        get_tax_rates (function): function to generate tax rates given
            parameters
        params_to_plot (Numpy Array): tax function parameters
        output_dir (str): output directory for saving plot files

    Returns:
        None

    '''
    cmap1 = matplotlib.cm.get_cmap('summer')

    # Make comparison plot with full income domains
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.scatter(X, Y, txrates, c='r', marker='o')
    ax.set_xlabel('Total Labor Income')
    ax.set_ylabel('Total Capital Income')
    if rate_type == 'etr':
        tx_label = 'ETR'
    elif rate_type == 'mtrx':
        tx_label = 'MTRx'
    elif rate_type == 'mtry':
        tx_label = 'MTRy'
    ax.set_zlabel(tx_label)
    plt.title(tx_label + ' vs. Predicted ' + tx_label + ': Age=' + str(s) +
              ', Year=' + str(t))

    gridpts = 50
    X_vec = np.exp(np.linspace(np.log(5), np.log(X.max()), gridpts))
    Y_vec = np.exp(np.linspace(np.log(5), np.log(Y.max()), gridpts))
    X_grid, Y_grid = np.meshgrid(X_vec, Y_vec)
    txrate_grid = txfunc.get_tax_rates(params_to_plot,
                                       X_grid,
                                       Y_grid,
                                       None,
                                       tax_func_type,
                                       rate_type,
                                       for_estimation=False)
    ax.plot_surface(X_grid, Y_grid, txrate_grid, cmap=cmap1, linewidth=0)
    filename = (tx_label + '_age_' + str(s) + '_Year_' + str(t) +
                '_vsPred.png')
    fullpath = os.path.join(output_dir, filename)
    fig.savefig(fullpath, bbox_inches='tight')
    plt.close()

    # Make comparison plot with truncated income domains
    df_trnc_gph = df[(df['total_labinc'] > 5) & (df['total_labinc'] < 800000) &
                     (df['total_capinc'] > 5) & (df['total_capinc'] < 800000)]
    X_gph = df_trnc_gph['total_labinc']
    Y_gph = df_trnc_gph['total_capinc']
    if rate_type == 'etr':
        txrates_gph = df_trnc_gph['etr']
    elif rate_type == 'mtrx':
        txrates_gph = df_trnc_gph['mtr_labinc']
    elif rate_type == 'mtry':
        txrates_gph = df_trnc_gph['mtr_capinc']

    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.scatter(X_gph, Y_gph, txrates_gph, c='r', marker='o')
    ax.set_xlabel('Total Labor Income')
    ax.set_ylabel('Total Capital Income')
    ax.set_zlabel(tx_label)
    plt.title('Truncated ' + tx_label + ', Lab. Inc., and Cap. ' +
              'Inc., Age=' + str(s) + ', Year=' + str(t))

    gridpts = 50
    X_vec = np.exp(np.linspace(np.log(5), np.log(X_gph.max()), gridpts))
    Y_vec = np.exp(np.linspace(np.log(5), np.log(Y_gph.max()), gridpts))
    X_grid, Y_grid = np.meshgrid(X_vec, Y_vec)
    txrate_grid = txfunc.get_tax_rates(params_to_plot,
                                       X_grid,
                                       Y_grid,
                                       None,
                                       tax_func_type,
                                       rate_type,
                                       for_estimation=False)
    ax.plot_surface(X_grid, Y_grid, txrate_grid, cmap=cmap1, linewidth=0)
    filename = (tx_label + 'trunc_age_' + str(s) + '_Year_' + str(t) +
                '_vsPred.png')
    fullpath = os.path.join(output_dir, filename)
    fig.savefig(fullpath, bbox_inches='tight')
    plt.close()