Tax-Calculator Behavioral Responses

Tax-Calculator Behavioral Responses#

Tax-Calculator Behavioral Responses

taxcalc.behresp#

Partial-equilibrium elasticity-based behavioral-responses logic.

taxcalc.behresp.labor_response(earnings=array([1]), substitution_eti=array([0.]), mtr1=array([0.]), mtr2=array([0.]), income_elasticity=array([0.]), aftertax_income1=array([0.]), aftertax_income2=array([0.]))[source]#

Calculate labor response given earnings, substitution elasticity of taxable income, initial and new marginal tax rates, income elasticity, and initial and new after-tax income. Accepts arrays.

Parameters:
  • earnings (numpy array) – pre-response earnings whose response is being calculated. Defaults to 1.

  • substitution_eti (float or numpy array) – coefficient of the substitution elasticity of taxable income. Defaults to 0.

  • mtr1 (numpy array) –

    marginal tax rate of earnings under baseline policy.

    Note that this function forces MTRs to be in [-inf, 0.99] range, but the caller of this function may want to constrain large MTRs to be somewhat smaller in order to avoid extreme proportional changes in earnings. Defaults to 0.

  • mtr2 (numpy array) –

    marginal tax rate of earnings under reform policy.

    Note that this function forces MTRs to be in [-inf, 0.99] range, but the caller of this function may want to constrain large MTRs to be somewhat smaller in order to avoid extreme proportional changes in earnings. Defaults to 0.

  • income_elasticity (float) – coefficient of the percentage change in aftertax income in the log-log response equation. Defaults to 0.

  • aftertax_income1 (numpy array) –

    aftertax income under baseline policy.

    Note that this function forces income to be in [1, inf] range, but the caller of this function may want to constrain negative or small incomes to be somewhat larger in order to avoid extreme proportional changes in aftertax income. Defaults to 0.

  • aftertax_income2 (numpy array) –

    aftertax income under reform policy.

    Note that this function forces income to be in [1, inf] range, but the caller of this function may want to constrain negative or small incomes to be somewhat larger in order to avoid extreme proportional changes in aftertax income. Defaults to 0.

Returns:

response – dollar change in earnings calculated from log-log response equation

Return type:

numpy array

taxcalc.behresp.quantity_response(quantity=array([1]), price_elasticity=array([0.]), aftertax_price1=array([0.]), aftertax_price2=array([0.]), income_elasticity=array([0.]), aftertax_income1=array([0.]), aftertax_income2=array([0.]))[source]#

Calculate dollar change in quantity using a log-log response equation, which assumes that the proportional change in the quantity is equal to the sum of two terms:

  1. the proportional change in the quantity’s marginal aftertax price times an assumed price elasticity, and

  2. the proportional change in aftertax income times an assumed income elasticity.

Not all inputs are required, so it’s possible to calculate only the price or income effects by providing a subset of arguments. Accepts arrays.

Parameters:
  • quantity (numpy array) – pre-response quantity whose response is being calculated. Defaults to 1.

  • price_elasticity (float) – coefficient of the percentage change in aftertax price of the quantity in the log-log response equation. Defaults to 0.

  • aftertax_price1 (numpy array) –

    marginal aftertax price of the quantity under baseline policy.

    Note that this function forces prices to be in [0.01, inf] range, but the caller of this function may want to constrain negative or very small prices to be somewhat larger in order to avoid extreme proportional changes in price. Defaults to 0.

    Note this is NOT an array of marginal tax rates (MTR), but rather usually 1-MTR (or in the case of quantities, like charitable giving, whose MTR values are non-positive, 1+MTR).

  • aftertax_price2 (numpy array) –

    marginal aftertax price of the quantity under reform policy.

    Note that this function forces prices to be in [0.01, inf] range, but the caller of this function may want to constrain negative or very small prices to be somewhat larger in order to avoid extreme proportional changes in price. Defaults to 0.

    Note this is NOT an array of marginal tax rates (MTR), but rather usually 1-MTR (or in the case of quantities, like charitable giving, whose MTR values are non-positive, 1+MTR).

  • income_elasticity (float) – coefficient of the percentage change in aftertax income in the log-log response equation. Defaults to 0.

  • aftertax_income1 (numpy array) –

    aftertax income under baseline policy.

    Note that this function forces income to be in [1, inf] range, but the caller of this function may want to constrain negative or small incomes to be somewhat larger in order to avoid extreme proportional changes in aftertax income. Defaults to 0.

  • aftertax_income2 (numpy array) –

    aftertax income under reform policy.

    Note that this function forces income to be in [1, inf] range, but the caller of this function may want to constrain negative or small incomes to be somewhat larger in order to avoid extreme proportional changes in aftertax income. Defaults to 0.

Returns:

response – dollar change in quantity calculated from log-log response equation

Return type:

numpy array

taxcalc.behresp.response(calc_1, calc_2, elasticities, dump=False)[source]#

Implements “Partial Equilibrium Simulation” conventional analysis, returning results as a tuple of Pandas DataFrame objects (df1, df2) where df1 is extracted from a baseline-policy calc_1 copy, and df2 is extracted from a reform-policy calc_2 copy that incorporates the behavioral responses given by the nature of the baseline-to-reform change in policy and elasticities in the specified behavior dictionary.

Note: this function internally modifies a copy of calc_2 records to account for behavioral responses that arise from the policy reform that involves moving from calc1 policy to calc2 policy. Neither calc_1 nor calc_2 need to have had calc_all() executed before calling the response function. And neither calc_1 nor calc_2 are affected by this response function.

The elasticities argument is a dictionary containing the assumed response elasticities. Omitting an elasticity key:value pair in the dictionary implies the omitted elasticity is assumed to be zero. Here is the full dictionary content and each elasticity’s internal name:

be_sub = elasticities[‘sub’]

Substitution elasticity of taxable income. Defined as proportional change in taxable income divided by proportional change in marginal net-of-tax rate (1-MTR) on taxpayer earnings caused by the reform. Must be zero or positive.

be_inc = elasticities[‘inc’]

Income elasticity of taxable income. Defined as dollar change in taxable income divided by dollar change in after-tax income caused by the reform. Must be zero or negative.

be_cg = elasticities[‘cg’]

Semi-elasticity of long-term capital gains. Defined as change in logarithm of long-term capital gains divided by change in marginal tax rate (MTR) on long-term capital gains caused by the reform. Must be zero or negative. Read response function documentation (see below) for discussion of appropriate values.

The optional dump argument controls the number of variables included in the two returned DataFrame objects. When dump=False (its default value), the variables in the two returned DataFrame objects include just the variables in the Tax-Calculator DIST_VARIABLES list, which is sufficient for constructing the standard Tax-Calculator tables. When dump=True, the variables in the two returned DataFrame objects include all the Tax-Calculator input and calculated output variables, which is the same output as produced by the Tax-Calculator tc –dump option except for one difference: the tc –dump option provides two calculated variables, mtr_inctax and mtr_paytax, that are replaced in the dump output of this response function by mtr_combined, which is the sum of mtr_inctax and mtr_paytax.

Note: the use here of a dollar-change income elasticity (rather than

a proportional-change elasticity) is consistent with Feldstein and Feenberg, “The Taxation of Two Earner Families”, NBER Working Paper No. 5155 (June 1995). A proportional-change elasticity was used by Gruber and Saez, “The elasticity of taxable income: evidence and implications”, Journal of Public Economics 84:1-32 (2002) [see equation 2 on page 10].

Note: the nature of the capital-gains elasticity used here is similar

to that used in Joint Committee on Taxation, “New Evidence on the Tax Elasticity of Capital Gains: A Joint Working Paper of the Staff of the Joint Committee on Taxation and the Congressional Budget Office”, (JCX-56-12), June 2012. In particular, the elasticity use here is equivalent to the term inside the square brackets on the right-hand side of equation (4) on page 11 — not the epsilon variable on the left-hand side of equation (4), which is equal to the elasticity used here times the weighted average marginal tax rate on long-term capital gains. So, the JCT-CBO estimate of -0.792 for the epsilon elasticity (see JCT-CBO, Table 5) translates into a much larger absolute value for the be_cg semi-elasticity used by Tax-Calculator. To calculate the elasticity from a semi-elasticity, we multiply by MTRs from TC and weight by shares of taxable gains. To avoid those with zero MTRs, we restrict this to the top 40% of tax units by AGI. Using this function, a semi-elasticity of -3.45 corresponds to a tax rate elasticity of -0.792.