Example #1
0
def soli_st_tu(_st_kind_freib_tu, _anz_erwachsene_tu, abgelt_st_tu, soli_st_params):
    """Solidarity Surcharge.

    Solidaritätszuschlaggesetz (SolZG) in 1991 and 1992.
    Solidaritätszuschlaggesetz 1995 (SolZG 1995) since 1995.

    The Solidarity Surcharge is an additional tax on top of the income tax which
    is the tax base. As opposed to the 'standard' income tax, child allowance is
    always deducted for tax base calculation.

    There is also Solidarity Surcharge on the Capital Income Tax, but always
    with Solidarity Surcharge tax rate and no tax exempt level. §3 (3) S.2
    SolzG 1995.
    """
    st_per_individual = _st_kind_freib_tu / _anz_erwachsene_tu
    out = (
        _anz_erwachsene_tu
        * piecewise_polynomial(
            st_per_individual,
            thresholds=soli_st_params["soli_st"]["thresholds"],
            rates=soli_st_params["soli_st"]["rates"],
            intercepts_at_lower_thresholds=soli_st_params["soli_st"][
                "intercepts_at_lower_thresholds"
            ],
        )
        + soli_st_params["soli_st"]["rates"][0, -1] * abgelt_st_tu
    )

    return out
Example #2
0
def st_tarif(x: FloatSeries, params: dict) -> FloatSeries:
    """The German Income Tax Tariff.

    Modelled only after 2002 so far.
    It's not calculated as in the tax code, but rather a gemoetric decomposition of the
    area beneath the marginal tax rate function.
    This facilitates the implementation of alternative tax schedules

    Parameters
    ----------
    x : Floatseries
        Some floatseries wherest_tarif is applied to.
    params : dict
        Dictionary created in respy.piecewise_functions.

    Returns
    -------

    """
    eink_st = piecewise_polynomial(
        x=x,
        thresholds=params["eink_st_tarif"]["thresholds"],
        rates=params["eink_st_tarif"]["rates"],
        intercepts_at_lower_thresholds=params["eink_st_tarif"]
        ["intercepts_at_lower_thresholds"],
    )
    return eink_st
Example #3
0
def proxy_eink_vorj_elterngeld(
    beitr_bemess_grenze_rentenv,
    bruttolohn_vorj_m,
    elterngeld_params,
    eink_st_params,
    eink_st_abzuege_params,
    soli_st_params,
):
    """Calculating the claim for benefits depending on previous wage.

    TODO: This function requires `.fillna(0)` at the end. Investigate!

    """
    # Relevant wage is capped at the contribution thresholds
    max_wage = bruttolohn_vorj_m.clip(upper=beitr_bemess_grenze_rentenv)

    # We need to deduct lump-sum amounts for contributions, taxes and soli
    prox_ssc = elterngeld_params["elterngeld_soz_vers_pausch"] * max_wage

    # Fictive taxes (Lohnsteuer) are approximated by applying the wage to the tax tariff
    prox_tax = _st_tarif(
        12 * max_wage - eink_st_abzuege_params["werbungskostenpauschale"],
        eink_st_params,
    )

    prox_soli = piecewise_polynomial(
        prox_tax,
        thresholds=soli_st_params["soli_st"]["thresholds"],
        rates=soli_st_params["soli_st"]["rates"],
        intercepts_at_lower_thresholds=soli_st_params["soli_st"]
        ["intercepts_at_lower_thresholds"],
    )

    return ((max_wage - prox_ssc - prox_tax / 12 -
             prox_soli / 12).clip(lower=0).fillna(0))
Example #4
0
def eink_anr_frei_bis_10_2005(
    bruttolohn_m: FloatSeries,
    arbeitsl_geld_2_2005_netto_quote: FloatSeries,
    arbeitsl_geld_2_params: dict,
) -> FloatSeries:
    """Calcualte share of income, which remains to the individual until 10/2005.

    Parameters
    ----------
    bruttolohn_m
        See basic input variable :ref:`bruttolohn_m <bruttolohn_m>`.
    arbeitsl_geld_2_2005_netto_quote
        See :func:`arbeitsl_geld_2_2005_netto_quote`.
    arbeitsl_geld_2_params
        See params documentation :ref:`arbeitsl_geld_2_params <arbeitsl_geld_2_params>`.

    Returns
    -------

    """
    out = piecewise_polynomial(
        x=bruttolohn_m,
        thresholds=arbeitsl_geld_2_params["eink_anr_frei"]["thresholds"],
        rates=arbeitsl_geld_2_params["eink_anr_frei"]["rates"],
        intercepts_at_lower_thresholds=arbeitsl_geld_2_params["eink_anr_frei"][
            "intercepts_at_lower_thresholds"
        ],
        rates_multiplier=arbeitsl_geld_2_2005_netto_quote,
    )
    return out
Example #5
0
def eink_anr_frei_ab_10_2005(
    hh_id: IntSeries,
    bruttolohn_m: FloatSeries,
    kinder_in_hh: BoolSeries,
    arbeitsl_geld_2_params: dict,
) -> FloatSeries:
    """Calcualte share of income, which remains to the individual sinc 10/2005.

    Parameters
    ----------
    hh_id
        See basic input variable :ref:`hh_id <hh_id>`.
    bruttolohn_m
        See basic input variable :ref:`bruttolohn_m <bruttolohn_m>`.
    kinder_in_hh
        See :func:`kinder_in_h`.
    arbeitsl_geld_2_params
        See params documentation :ref:`arbeitsl_geld_2_params <arbeitsl_geld_2_params>`.

    Returns
    -------

    """
    out = bruttolohn_m * 0
    kinder_in_hh_individual = hh_id.replace(kinder_in_hh).astype(bool)
    out.loc[kinder_in_hh_individual] = piecewise_polynomial(
        x=bruttolohn_m.loc[kinder_in_hh_individual],
        thresholds=arbeitsl_geld_2_params["eink_anr_frei_kinder"]["thresholds"],
        rates=arbeitsl_geld_2_params["eink_anr_frei_kinder"]["rates"],
        intercepts_at_lower_thresholds=arbeitsl_geld_2_params["eink_anr_frei_kinder"][
            "intercepts_at_lower_thresholds"
        ],
    )
    out.loc[~kinder_in_hh_individual] = piecewise_polynomial(
        x=bruttolohn_m.loc[~kinder_in_hh_individual],
        thresholds=arbeitsl_geld_2_params["eink_anr_frei"]["thresholds"],
        rates=arbeitsl_geld_2_params["eink_anr_frei"]["rates"],
        intercepts_at_lower_thresholds=arbeitsl_geld_2_params["eink_anr_frei"][
            "intercepts_at_lower_thresholds"
        ],
    )
    return out
Example #6
0
def eink_anr_frei_bis_10_2005(bruttolohn_m, arbeitsl_geld_2_2005_netto_quote,
                              arbeitsl_geld_2_params):
    out = piecewise_polynomial(
        x=bruttolohn_m,
        thresholds=arbeitsl_geld_2_params["eink_anr_frei"]["thresholds"],
        rates=arbeitsl_geld_2_params["eink_anr_frei"]["rates"],
        intercepts_at_lower_thresholds=arbeitsl_geld_2_params["eink_anr_frei"]
        ["intercepts_at_lower_thresholds"],
        rates_multiplier=arbeitsl_geld_2_2005_netto_quote,
    )
    return out
Example #7
0
def eink_anr_frei_ab_10_2005(hh_id, bruttolohn_m, kinder_in_hh,
                             arbeitsl_geld_2_params):
    out = bruttolohn_m * 0
    kinder_in_hh_individual = hh_id.replace(kinder_in_hh).astype(bool)
    out.loc[kinder_in_hh_individual] = piecewise_polynomial(
        x=bruttolohn_m.loc[kinder_in_hh_individual],
        thresholds=arbeitsl_geld_2_params["eink_anr_frei_kinder"]
        ["thresholds"],
        rates=arbeitsl_geld_2_params["eink_anr_frei_kinder"]["rates"],
        intercepts_at_lower_thresholds=arbeitsl_geld_2_params[
            "eink_anr_frei_kinder"]["intercepts_at_lower_thresholds"],
    )
    out.loc[~kinder_in_hh_individual] = piecewise_polynomial(
        x=bruttolohn_m.loc[~kinder_in_hh_individual],
        thresholds=arbeitsl_geld_2_params["eink_anr_frei"]["thresholds"],
        rates=arbeitsl_geld_2_params["eink_anr_frei"]["rates"],
        intercepts_at_lower_thresholds=arbeitsl_geld_2_params["eink_anr_frei"]
        ["intercepts_at_lower_thresholds"],
    )
    return out
Example #8
0
def proxy_eink_vorj_elterngeld(
    rentenv_beitr_bemess_grenze: FloatSeries,
    bruttolohn_vorj_m: FloatSeries,
    elterngeld_params: dict,
    eink_st_params: dict,
    eink_st_abzuege_params: dict,
    soli_st_params: dict,
) -> FloatSeries:
    """Calculating the claim for benefits depending on previous wage.

    TODO: This function requires `.fillna(0)` at the end. Investigate!

    Parameters
    ----------
    rentenv_beitr_bemess_grenze
        See :func:`rentenv_beitr_bemess_grenze`.
    bruttolohn_vorj_m
        See basic input variable :ref:`bruttolohn_vorj_m <bruttolohn_vorj_m>`.
    elterngeld_params
        See params documentation :ref:`elterngeld_params <elterngeld_params>`.
    eink_st_params
        See params documentation :ref:`eink_st_params <eink_st_params>`.
    eink_st_abzuege_params
        See params documentation :ref:`eink_st_abzuege_params <eink_st_abzuege_params>`.
    soli_st_params
        See params documentation :ref:`soli_st_params <soli_st_params>`.

    Returns
    -------

    """
    # Relevant wage is capped at the contribution thresholds
    max_wage = bruttolohn_vorj_m.clip(upper=rentenv_beitr_bemess_grenze)

    # We need to deduct lump-sum amounts for contributions, taxes and soli
    prox_ssc = elterngeld_params["elterngeld_soz_vers_pausch"] * max_wage

    # Fictive taxes (Lohnsteuer) are approximated by applying the wage to the tax tariff
    prox_tax = st_tarif(
        (12 * max_wage -
         eink_st_abzuege_params["werbungskostenpauschale"]).clip(lower=0),
        eink_st_params,
    )

    prox_soli = piecewise_polynomial(
        prox_tax,
        thresholds=soli_st_params["soli_st"]["thresholds"],
        rates=soli_st_params["soli_st"]["rates"],
        intercepts_at_lower_thresholds=soli_st_params["soli_st"]
        ["intercepts_at_lower_thresholds"],
    )

    return (max_wage - prox_ssc - prox_tax / 12 - prox_soli / 12).clip(lower=0)
def proxy_eink_vorj_arbeitsl_geld(
    rentenv_beitr_bemess_grenze: FloatSeries,
    bruttolohn_vorj_m: FloatSeries,
    arbeitsl_geld_params: dict,
    eink_st_params: dict,
    eink_st_abzuege_params: dict,
    soli_st_params: dict,
) -> FloatSeries:
    """Approximate last years income for unemployment benefit.

    Parameters
    ----------
    rentenv_beitr_bemess_grenze
        See :func:`rentenv_beitr_bemess_grenze`.
    bruttolohn_vorj_m
        See basic input variable :ref:`bruttolohn_vorj_m <bruttolohn_vorj_m>`.
    arbeitsl_geld_params
        See params documentation :ref:`arbeitsl_geld_params <arbeitsl_geld_params>`.
    eink_st_params
        See params documentation :ref:`eink_st_params <eink_st_params>`.
    eink_st_abzuege_params
        See params documentation :ref:`eink_st_abzuege_params <eink_st_abzuege_params>`.
    soli_st_params
        See params documentation :ref:`soli_st_params <soli_st_params>`.

    Returns
    -------

    """
    # Relevant wage is capped at the contribution thresholds
    max_wage = bruttolohn_vorj_m.clip(lower=None, upper=rentenv_beitr_bemess_grenze)

    # We need to deduct lump-sum amounts for contributions, taxes and soli
    prox_ssc = arbeitsl_geld_params["soz_vers_pausch_arbeitsl_geld"] * max_wage

    # Fictive taxes (Lohnsteuer) are approximated by applying the wage to the tax tariff
    prox_tax = st_tarif(
        12 * max_wage - eink_st_abzuege_params["werbungskostenpauschale"],
        eink_st_params,
    )
    prox_soli = piecewise_polynomial(
        prox_tax,
        thresholds=soli_st_params["soli_st"]["thresholds"],
        rates=soli_st_params["soli_st"]["rates"],
        intercepts_at_lower_thresholds=soli_st_params["soli_st"][
            "intercepts_at_lower_thresholds"
        ],
    )

    return (max_wage - prox_ssc - prox_tax / 12 - prox_soli / 12).clip(lower=0)
def soli_st_tu(
    st_kind_freib_tu: FloatSeries,
    anz_erwachsene_tu: IntSeries,
    abgelt_st_tu: FloatSeries,
    soli_st_params: dict,
) -> FloatSeries:
    """Calculate the Solidarity Surcharge.

    Solidaritätszuschlaggesetz (SolZG) in 1991 and 1992.
    Solidaritätszuschlaggesetz 1995 (SolZG 1995) since 1995.

    The Solidarity Surcharge is an additional tax on top of the income tax which
    is the tax base. As opposed to the 'standard' income tax, child allowance is
    always deducted for tax base calculation.

    There is also Solidarity Surcharge on the Capital Income Tax, but always
    with Solidarity Surcharge tax rate and no tax exempt level. §3 (3) S.2
    SolzG 1995.

    Parameters
    ----------
    st_kind_freib_tu
        See :func:`st_kind_freib_tu`.
    anz_erwachsene_tu
        See :func:`anz_erwachsene_tu`.
    abgelt_st_tu
        See :func:`abgelt_st_tu`.
    soli_st_params
        See params documentation :ref:`soli_st_params <soli_st_params>`.

    Returns
    -------

    """
    st_per_individual = st_kind_freib_tu / anz_erwachsene_tu
    out = (anz_erwachsene_tu * piecewise_polynomial(
        st_per_individual,
        thresholds=soli_st_params["soli_st"]["thresholds"],
        rates=soli_st_params["soli_st"]["rates"],
        intercepts_at_lower_thresholds=soli_st_params["soli_st"]
        ["intercepts_at_lower_thresholds"],
    ) + soli_st_params["soli_st"]["rates"][0, -1] * abgelt_st_tu)

    return out
Example #11
0
def _ertragsanteil(jahr_renteneintr, eink_st_params):
    """Calculate the share of pensions subject to income taxation.

    Parameters
    ----------
    jahr_renteneintr

    Returns
    -------

    """
    out = piecewise_polynomial(
        x=jahr_renteneintr,
        thresholds=eink_st_params["ertragsanteil"]["thresholds"],
        rates=eink_st_params["ertragsanteil"]["rates"],
        intercepts_at_lower_thresholds=eink_st_params["ertragsanteil"]
        ["intercepts_at_lower_thresholds"],
    )
    return out
Example #12
0
def _st_tarif(x, params):
    """ The German Income Tax Tariff.
     Modelled only after 2002 so far.

    It's not calculated as in the tax code, but rather a gemoetric decomposition of the
    area beneath the marginal tax rate function.
    This facilitates the implementation of alternative tax schedules

    args:
        x (Series): taxable income
        params (dict): tax-benefit parameters specific to year and reform
    """
    eink_st = piecewise_polynomial(
        x=x,
        thresholds=params["eink_st_tarif"]["thresholds"],
        rates=params["eink_st_tarif"]["rates"],
        intercepts_at_lower_thresholds=params["eink_st_tarif"][
            "intercepts_at_lower_thresholds"
        ],
    )
    return eink_st
def ertragsanteil(jahr_renteneintr: IntSeries, eink_st_params: dict) -> FloatSeries:
    """Calculate the share of pensions subject to income taxation.

    Parameters
    ----------
    jahr_renteneintr
            See basic input variable :ref:`jahr_renteneintr <jahr_renteneintr>`.
    eink_st_params
        See params documentation :ref:`eink_st_params <eink_st_params>`.
    Returns
    -------

    """
    out = piecewise_polynomial(
        x=jahr_renteneintr,
        thresholds=eink_st_params["ertragsanteil"]["thresholds"],
        rates=eink_st_params["ertragsanteil"]["rates"],
        intercepts_at_lower_thresholds=eink_st_params["ertragsanteil"][
            "intercepts_at_lower_thresholds"
        ],
    )
    return out
def tax_rate_data(start, end):
    """
    For a given year span returns the policy parameters to plot income tax
    rate per income

    sel_year (Int): The year for which the data will be simulated. The range for
                    which parameters can be simulated is 2002-2020.

    returns dict
    """
    years = range(start, end + 1)
    einkommen = pd.Series(data=np.linspace(0, 300000, 601))
    tax_rate_dict_full = {}
    for i in years:
        policy_params, policy_functions = set_up_policy_environment(i)
        eink_params = policy_params["eink_st"]
        soli_params = policy_params["soli_st"]["soli_st"]

        eink_tax = st_tarif(einkommen, eink_params)
        soli = piecewise_polynomial(
            eink_tax,
            thresholds=soli_params["thresholds"],
            rates=soli_params["rates"],
            intercepts_at_lower_thresholds=soli_params[
                "intercepts_at_lower_thresholds"],
        )
        marginal_rate = np.gradient(eink_tax, einkommen)
        overall_marginal_rate = np.gradient(eink_tax + soli, einkommen)
        tax_rate_dict_full[i] = {
            "tax_rate": (eink_tax / einkommen),
            "overall_tax_rate": ((soli + eink_tax) / einkommen),
            "marginal_rate": pd.Series(marginal_rate),
            "overall_marginal_rate": pd.Series(overall_marginal_rate),
            "income": einkommen,
        }

    return tax_rate_dict_full