Source code for _gettsim.transfers.grundrente

from _gettsim.piecewise_functions import piecewise_polynomial
from _gettsim.shared import add_rounding_spec


[docs]@add_rounding_spec(params_key="ges_rente") def grundr_zuschlag_m( grundr_zuschlag_vor_eink_anr_m: float, grundr_zuschlag_eink_m: float ) -> float: """Calculate Grundrentenzuschlag (additional monthly pensions payments resulting from Grundrente) Parameters ---------- grundr_zuschlag_vor_eink_anr_m See :func:`grundr_zuschlag_vor_eink_anr_m`. grundr_zuschlag_eink_m See :func:`grundr_zuschlag_eink_m`. Returns ------- """ out = grundr_zuschlag_vor_eink_anr_m - grundr_zuschlag_eink_m return max(out, 0.0)
def _grundr_zuschlag_eink_vor_freibetrag_m( rente_vorj_vor_grundr_proxy_m: float, bruttolohn_vorj_m: float, eink_selbst: float, eink_vermietung: float, kapitaleink: float, ) -> float: """Calculate total income relevant for Grundrentenzuschlag before deductions are subtracted. Some notes: - The Grundrentenzuschlag (in previous years) is not part of the relevant income and does not lower the Grundrentenzuschlag (reference: § 97a Abs. 2 S. 7 SGB VI). - The Deutsche Rentenversicherung uses the income of the year two to three years ago to be able to use administrative data on this income for the calculation: "It can be assumed that the tax office regularly has the data two years after the end of the assessment period, which can be retrieved from the pension insurance." - Warning: Currently, earnings of dependent work and pensions are based on the last year, and other income on the current year instead of the year two years ago to avoid the need for several new input variables. # ToDo: Freibeträge for income are currently not considered # ToDo: as freibeträge_tu depends on pension income through # ToDo: `ges_krankenv_beitr_m` -> `vorsorgeaufw` -> `freibeträge` Reference: § 97a Abs. 2 S. 1 SGB VI Parameters ---------- rente_vorj_vor_grundr_proxy_m See :func:`rente_vorj_vor_grundr_proxy_m`. bruttolohn_vorj_m See :func:`bruttolohn_vorj_m`. eink_selbst See :func:`eink_selbst`. eink_vermietung See :func:`eink_vermietung`. kapitaleink See :func:`kapitaleink`. Returns ------- """ # Sum income over different income sources. out = ( rente_vorj_vor_grundr_proxy_m + bruttolohn_vorj_m + eink_selbst / 12 # income from self-employment + eink_vermietung / 12 # rental income + kapitaleink / 12 ) return out
[docs]@add_rounding_spec(params_key="ges_rente") def grundr_zuschlag_eink_m( _grundr_zuschlag_eink_vor_freibetrag_m_tu: float, gemeinsam_veranlagt_tu: bool, rentenwert: float, ges_rente_params: dict, ) -> float: """Calculate income which is deducted from Grundrentenzuschlag. Apply allowances. There are upper and lower thresholds for singles and couples. 60% of income between the upper and lower threshold is credited against the Grundrentenzuschlag. All the income above the upper threshold is credited against the Grundrentenzuschlag. Reference: § 97a Abs. 4 S. 2, 4 SGB VI Parameters ---------- _grundr_zuschlag_eink_vor_freibetrag_m_tu See :func:`_grundr_zuschlag_eink_vor_freibetrag_m_tu`. gemeinsam_veranlagt_tu See :func:`gemeinsam_veranlagt_tu`. rentenwert See :func:`rentenwert`. ges_rente_params See params documentation :ref:`ges_rente_params <ges_rente_params>`. Returns ------- """ # Calculate relevant income following the crediting rules using the values for # singles and those for married subjects # Note: Thresholds are defined relativ to rentenwert which is implemented by # dividing the income by rentenwert and multiply rentenwert to the result. if gemeinsam_veranlagt_tu: einkommensanr_params = ges_rente_params["grundr_einkommensanr_verheiratet"] else: einkommensanr_params = ges_rente_params["grundr_einkommensanr_single"] out = ( piecewise_polynomial( x=_grundr_zuschlag_eink_vor_freibetrag_m_tu / rentenwert, thresholds=einkommensanr_params["thresholds"], rates=einkommensanr_params["rates"], intercepts_at_lower_thresholds=einkommensanr_params[ "intercepts_at_lower_thresholds" ], ) * rentenwert ) return out
[docs]@add_rounding_spec(params_key="ges_rente") def grundr_zuschlag_vor_eink_anr_m( grundr_zuschlag_bonus_entgeltp: float, grundr_bew_zeiten: int, rentenwert: float, ges_rente_zugangsfaktor: float, ges_rente_params: dict, ) -> float: """Calculate additional monthly pensions payments resulting from Grundrente, without taking into account income crediting rules. The Zugangsfaktor is limited to 1 and considered Grundrentezeiten are limited to 35 years (420 months). Parameters ---------- grundr_zuschlag_bonus_entgeltp See :func:`grundr_zuschlag_bonus_entgeltp`. grundr_bew_zeiten See basic input variable :ref:`grundr_bew_zeiten <grundr_bew_zeiten>`. rentenwert See :func:`rentenwert`. ges_rente_zugangsfaktor See :func:`ges_rente_zugangsfaktor`. ges_rente_params See params documentation :ref:`ges_rente_params <ges_rente_params>`. Returns ------- """ # Winsorize Bewertungszeiten and Zugangsfaktor at maximum values grundr_bew_zeiten_wins = min( grundr_bew_zeiten, ges_rente_params["grundr_zeiten"]["max"] ) ges_rente_zugangsfaktor_wins = min( ges_rente_zugangsfaktor, ges_rente_params["grundr_zugangsfaktor_max"] ) out = ( grundr_zuschlag_bonus_entgeltp * grundr_bew_zeiten_wins * rentenwert * ges_rente_zugangsfaktor_wins ) return out
[docs]def grundr_bew_zeiten_avg_entgeltp( grundr_entgeltp: float, grundr_bew_zeiten: int ) -> float: """Compute average number of Entgeltpunkte earned per month of Grundrentenbewertungszeiten. Parameters ---------- grundr_entgeltp See basic input variable :ref:`grundr_entgeltp <grundr_entgeltp>`. grundr_bew_zeiten See basic input variable :ref:`grundr_bew_zeiten <grundr_bew_zeiten>`. Returns ------- """ if grundr_bew_zeiten > 0: out = grundr_entgeltp / grundr_bew_zeiten # Return 0 if grundr_bew_zeiten is 0. Then, grundr_entgeltp should be 0, too. else: out = 0 return out
[docs]@add_rounding_spec(params_key="ges_rente") def grundr_zuschlag_höchstwert_m(grundr_zeiten: int, ges_rente_params: dict) -> float: """Calculate the maximum allowed number of average Entgeltpunkte (per month) after adding bonus of Entgeltpunkte for a given number of Grundrentenzeiten. Parameters ---------- grundr_zeiten See basic input variable :ref:`grundr_zeiten <grundr_zeiten>`. ges_rente_params See params documentation :ref:`ges_rente_params <ges_rente_params>`. Returns ------- """ # Calculate number of months above minimum threshold months_above_thresh = ( min(grundr_zeiten, ges_rente_params["grundr_zeiten"]["max"]) - ges_rente_params["grundr_zeiten"]["min"] ) # Calculate höchstwert out = ( ges_rente_params["grundr_höchstwert"]["base"] + ges_rente_params["grundr_höchstwert"]["increment"] * months_above_thresh ) return out
[docs]@add_rounding_spec(params_key="ges_rente") def grundr_zuschlag_bonus_entgeltp( grundr_bew_zeiten_avg_entgeltp: float, grundr_zuschlag_höchstwert_m: float, grundr_zeiten: int, ges_rente_params: dict, ) -> float: """Calculate additional Entgeltpunkte for pensioner. In general, the average of monthly Entgeltpunkte earnd in Grundrentenzeiten is doubled, or extended to the individual Höchstwert if doubling would exceed the Höchstwert. Then, the value is multiplied by 0.875. Legal reference: § 76g SGB VI Parameters ---------- grundr_bew_zeiten_avg_entgeltp See :func:`grundr_bew_zeiten_avg_entgeltp`. grundr_zuschlag_höchstwert_m See :func:`grundr_zuschlag_höchstwert_m`. grundr_zeiten See basic input variable :ref:`grundr_zeiten <grundr_zeiten>`. ges_rente_params See params documentation :ref:`ges_rente_params <ges_rente_params>`. Returns ------- """ # Return 0 if Grundrentenzeiten below minimum if grundr_zeiten < ges_rente_params["grundr_zeiten"]["min"]: out = 0.0 else: # Case 1: Entgeltpunkte less than half of Höchstwert if grundr_bew_zeiten_avg_entgeltp <= (0.5 * grundr_zuschlag_höchstwert_m): out = grundr_bew_zeiten_avg_entgeltp # Case 2: Entgeltpunkte more than half of Höchstwert, but below Höchstwert elif grundr_bew_zeiten_avg_entgeltp < grundr_zuschlag_höchstwert_m: out = grundr_zuschlag_höchstwert_m - grundr_bew_zeiten_avg_entgeltp # Case 3: Entgeltpunkte above Höchstwert elif grundr_bew_zeiten_avg_entgeltp > grundr_zuschlag_höchstwert_m: out = 0.0 # Multiply additional Engeltpunkte by factor out = out * ges_rente_params["grundr_faktor_bonus"] return out
[docs]@add_rounding_spec(params_key="ges_rente") def rente_vorj_vor_grundr_proxy_m( # noqa: PLR0913 rentner: bool, rentenwert_vorjahr: float, priv_rente_m: float, jahr_renteneintr: int, geburtsjahr: int, alter: int, entgeltp: float, ges_rente_zugangsfaktor: float, ) -> float: """Estimated amount of public pensions of last year excluding Grundrentenzuschlag. Parameters ---------- rentner See basic input variable :ref:`rentner <rentner>`. rentenwert_vorjahr See :func:`rentenwert_vorjahr`. priv_rente_m See basic input variable :ref:`priv_rente_m <priv_rente_m>`. jahr_renteneintr See basic input variable :ref:`jahr_renteneintr <jahr_renteneintr>`. geburtsjahr See basic input variable :ref:`geburtsjahr <geburtsjahr>`. alter See basic input variable :ref:`alter <alter>`. entgeltp See basic input variable :ref:`entgeltp <entgeltp>`. ges_rente_zugangsfaktor See :func:`ges_rente_zugangsfaktor`. Returns ------- """ # Assume priv_rente_m did not change # ToDo: Use current_year as argument of this function once we addressed # ToDo: issue #211 # Calculate if subect was retired last year if rentner: rentner_vorjahr = jahr_renteneintr < geburtsjahr + alter else: rentner_vorjahr = False if rentner_vorjahr: out = entgeltp * ges_rente_zugangsfaktor * rentenwert_vorjahr + priv_rente_m else: out = 0.0 return out
[docs]def grundr_berechtigt(grundr_zeiten: int, ges_rente_params: dict) -> bool: """Whether person has accumulated enough insured years to be eligible. Parameters ---------- grundr_zeiten See :func:`grundr_zeiten`. ges_rente_params See params documentation :ref:`ges_rente_params <ges_rente_params>`. Returns ------- """ out = grundr_zeiten >= ges_rente_params["grundr_zeiten"]["min"] return out