Skip to content

Commit

Permalink
Wohngeld on individual / BG level (#753)
Browse files Browse the repository at this point in the history
Closes #752 

Also, this PR fixes a bug through which Kindergeldübertrag was too high
(because Kindergeld was already counted as income when calculating the
difference between Regelbedarf and income).

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
MImmesberger and pre-commit-ci[bot] committed May 30, 2024
1 parent 84246be commit cd0cffd
Show file tree
Hide file tree
Showing 81 changed files with 1,945 additions and 399 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ releases are available on [Anaconda.org](https://anaconda.org/conda-forge/gettsi
- {gh}`755` Allow array returns when `skip_vectorization` is being used, enforce import
convention ({ghuser}`hmgaudecker`).
- {gh}`751` Kindergeldübertrag ({ghuser}`MImmesberger`).
- {gh}`750` Add Vorrangprüfung of Wohngeld on bg level ({ghuser}`MImmesberger`).
- {gh}`739` Unterhaltsvorschuss calculation on child level ({ghuser}`MImmesberger`).
- {gh}`725` KdU calculation on bg level and other small fixes ({ghuser}`MImmesberger`,
{ghuser}`ChristianZimpelmann`).
Expand Down
27 changes: 16 additions & 11 deletions docs/geps/gep-01.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,20 +125,25 @@ indicate the level of aggregation.
GETTSIM knows about the following units:

- `p_id`: person identifier
- `sn_id`: Steuernummer (same for spouses filing taxes jointly, not the same as the
Germany-wide Steuer-ID)
- `hh_id`: Haushalt, the relevant unit for Wohngeld. Encompasses more people than the
Bedarfsgemeinschaft (e.g., possibly more than 2 generations).
- `hh_id`: Haushalt, individuals living together in a household in the Wohngeld sense
(§5 WoGG).
- `wthh_id`: Wohngeldrechtlicher Teilhaushalt, i.e. members of a household for whom the
priority check for Wohngeld/ALG2 yields the same result ∈ {True, False}. This unit is
based on the priority check via `wohngeld_vorrang_bg` and
`wohngeld_kinderzuschl_vorrang_bg`.
- `fg_id`: Familiengemeinschaft. Maximum of two generations, the relevant unit for
Bürgergeld / Arbeitslosengeld 2. Another way to think about this is the potential
Bedarfsgemeinschaft before making checks for whether children have enough income fend
for themselves. Subset of `hh`.
- `bg_id`: Bedarfsgemeinschaft, i.e., Familiengemeinschaft plus for whether children
have enough income to fend for themselves. Subset of `fg_id`.
- `ehe_id`: Ehegemeinschaft, i.e., couples that are married or in a civil union.
- `eg_id`: Einstandsgemeinschaft, i.e., a couple whose members are deemed to be
responsible for each other. This includes couples that live together and may or may
not be married or in a civil union.
- `bg_id`: Bedarfsgemeinschaft, i.e., Familiengemeinschaft excluding children who have
enough income to fend for themselves (they will form separate `bg`s). Subset of
`fg_id`.
- `eg_id`: Einstandsgemeinschaft, a couple whose members are deemed to be responsible
for each other. This includes couples that live together and may or may not be married
or in a civil union.
- `ehe_id`: Ehegemeinschaft, i.e. couples that are married or in a civil union.
- `sn_id`: Steuernummer (same for spouses filing taxes jointly, not the same as the
Germany-wide Steuer-ID)

Note that households do not include flat shares etc.. Such broader definition are
currently not relevant in GETTSIM but may be added in the future (e.g., capping rules
Expand All @@ -163,7 +168,7 @@ general naming considerations here.
- Parameter names should be generally be aligned with relevant column names. However,
since the group is not repeated for the parameter, it is often better not to
abbreviate them (e.g., `wohngeld_params["vermögensgrundfreibetrag"]` for the parameter
and `wohngeld_nach_vermög_check_m_hh` for a column derived from it).
and `_wohngeld_nach_vermög_check_m_wthh` for a column derived from it).

## Other Python identifiers (Functions, Variables)

Expand Down
4 changes: 2 additions & 2 deletions docs/geps/gep-04.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,8 @@ aggregate_by_group_demographic_vars = {
}
```

The group identifier (`hh_id`, `sn_id`, `fg_id`, `bg_id`, `eg_id`, `ehe_id`) will be
automatically included as an argument; for `count` nothing else is necessary.
The group identifier (`hh_id`, `wthh_id`, `fg_id`, `bg_id`, `eg_id`, `ehe_id`, `sn_id`)
will be automatically included as an argument; for `count` nothing else is necessary.

The output type will be the same as the input type. Exceptions:

Expand Down
2 changes: 1 addition & 1 deletion docs/gettsim_objects/input_variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ household.

## `hh_id`

Household identifier
Household identifier following §5 WoGG

Type: int

Expand Down
2 changes: 1 addition & 1 deletion docs/gettsim_objects/variables_out.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ You can find their individual calculation in the documentation of all {ref}`func
- Monthly additional child benefit, household sum
* - {func}`elterngeld_m <_gettsim.functions.elterngeld_m>`
- Monthly parental leave benefit
* - {func}`wohngeld_m_hh <_gettsim.functions.wohngeld_m_hh>`
* - {func}`wohngeld_m_wthh <_gettsim.functions.wohngeld_m_wthh>`
- Monthly housing benefit on household level
* - {func}`grunds_im_alter_m_eg <_gettsim.functions.grunds_im_alter_m_eg>`
- Monthly subsistence payment for retirees on household level
Expand Down
26 changes: 16 additions & 10 deletions docs/tutorials/policy_functions.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,15 @@
"source": [
"def arbeitsl_geld_2_m_bg(\n",
" arbeitsl_geld_2_vor_vorrang_m_bg,\n",
" # wohngeld_vorrang_hh,\n",
" # wohngeld_vorrang_bg,\n",
" # kinderzuschl_vorrang_bg,\n",
" # wohngeld_kinderzuschl_vorrang_hh,\n",
" # wohngeld_kinderzuschl_vorrang_bg,\n",
" erwachsene_alle_rentner_hh,\n",
"):\n",
" if (\n",
" # wohngeld_vorrang_hh\n",
" # wohngeld_vorrang_bg\n",
" # | kinderzuschl_vorrang_bg\n",
" # | wohngeld_kinderzuschl_vorrang_hh\n",
" # | wohngeld_kinderzuschl_vorrang_bg\n",
" erwachsene_alle_rentner_hh\n",
" ):\n",
" out = 0.0\n",
Expand Down Expand Up @@ -166,9 +166,15 @@
"source": [
"For this data we can now compare the results of using GETTSIM with the `policy_functions_no_check` and the usual `policy_functions`. \n",
"\n",
"We should expect to see positive values for `wohngeld_m_hh`, `kinderzuschl_m_bg` and `arbeitsl_geld_2_m_bg` at the same time if we do not check which combination of transfers is optimal (`policy_functions_no_check`).\n",
"We should expect to see positive values for `wohngeld_m_wthh`, `kinderzuschl_m_bg` and\n",
"`arbeitsl_geld_2_m_bg` at the same time if we do not check which combination of\n",
"transfers is optimal (`policy_functions_no_check`).\n",
"\n",
"On the other hand, if we use the default version of the `policy_functions`, `wohngeld_m_hh` and `kinderzuschl_m_bg` should be zero as long as `arbeitsl_geld_2_m_bg` is positive (and the other way around), as it is a characteristic of the German taxes and transfers system that *Wohngeld* and *Kinderzuschlag* cannot be received in combination with *Arbeitslosengeld 2*."
"On the other hand, if we use the default version of the `policy_functions`,\n",
"`wohngeld_m_wthh` and `kinderzuschl_m_bg` should be zero as long as\n",
"`arbeitsl_geld_2_m_bg` is positive (and the other way around), as it is a characteristic\n",
"of the German taxes and transfers system that *Wohngeld* and *Kinderzuschlag* cannot be\n",
"received in combination with *Arbeitslosengeld 2*."
]
},
{
Expand All @@ -177,7 +183,7 @@
"metadata": {},
"outputs": [],
"source": [
"targets = [\"wohngeld_m_hh\", \"kinderzuschl_m_bg\", \"arbeitsl_geld_2_m_bg\"]"
"targets = [\"wohngeld_m_wthh\", \"kinderzuschl_m_bg\", \"arbeitsl_geld_2_m_bg\"]"
]
},
{
Expand Down Expand Up @@ -235,7 +241,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"On first glance, both figures look quite confusing because of the complexity of the German taxes and transfers system. But if we take a closer look, the figures confirm our expectations. If we let GETTSIM check for the most favorable combination of transfers, ```wohngeld_m_hh``` and ```kinderzuschl_m_bg``` are zero as long as `arbeitsl_geld_2_m_bg` is positive (i.e. the best option for the household) and the other way around. \n",
"On first glance, both figures look quite confusing because of the complexity of the German taxes and transfers system. But if we take a closer look, the figures confirm our expectations. If we let GETTSIM check for the most favorable combination of transfers, ```wohngeld_m_wthh``` and ```kinderzuschl_m_bg``` are zero as long as `arbeitsl_geld_2_m_bg` is positive (i.e. the best option for the household) and the other way around. \n",
"\n",
"If we do not let GETTSIM do this check, this does not hold any longer and all transfers can be positive at the same time (which is what we were trying to achieve). \n",
"\n",
Expand All @@ -255,7 +261,7 @@
" params=policy_params,\n",
" functions=[policy_functions, arbeitsl_geld_2_m_bg],\n",
" targets=[\n",
" \"wohngeld_m_hh\",\n",
" \"wohngeld_m_wthh\",\n",
" \"kinderzuschl_m_bg\",\n",
" \"arbeitsl_geld_2_m_bg\",\n",
" ],\n",
Expand Down Expand Up @@ -363,7 +369,7 @@
" params=policy_params,\n",
" functions=[policy_functions, arbeitsl_geld_2_m_bg, kindergeld_m],\n",
" targets=[\n",
" \"wohngeld_m_hh\",\n",
" \"wohngeld_m_wthh\",\n",
" \"kinderzuschl_m_bg\",\n",
" \"arbeitsl_geld_2_m_bg\",\n",
" \"kindergeld_m\",\n",
Expand Down
29 changes: 18 additions & 11 deletions src/_gettsim/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,17 @@ def set_array_backend(backend: str):
SUPPORTED_GROUPINGS = {
"hh": {
"name": "Haushalt",
"description": "The relevant unit for Wohngeld. Encompasses more people than"
" the Bedarfsgemeinschaft (e.g., possibly more than 2 generations). Relevant"
" unit for Wohngeld.",
"description": "Individuals living together in a household in the Wohngeld"
" sense (§5 WoGG).",
"potentially_endogenous": False,
},
"wthh": {
"name": "wohngeldrechtlicher Teilhaushalt",
"description": "The relevant unit for Wohngeld. Members of a household for whom"
" the Wohngeld priority check compared to Bürgergeld yields the same result"
" ∈ {True, False}.",
"potentially_endogenous": True,
},
"fg": {
"name": "Familiengemeinschaft",
"description": "Maximum of two generations, the relevant base unit for"
Expand All @@ -88,20 +94,21 @@ def set_array_backend(backend: str):
" to fend for themselves. Relevant unit for Bürgergeld / Arbeitslosengeld 2",
"potentially_endogenous": True,
},
"sn": {
"name": "Steuernummer",
"description": "Spouses filing taxes jointly or individuals.",
"eg": {
"name": "Einstandsgemeinschaft / Einstandspartner",
"description": "A couple whose members are deemed to be responsible for each"
" other.",
"potentially_endogenous": True,
},
"ehe": {
"name": "Ehepartner",
"description": "Couples that are either married or in a civil union.",
"potentially_endogenous": True,
},
"eg": {
"name": "Einstandsgemeinschaft / Einstandspartner",
"description": "A couple whose members are deemed to be responsible for each"
" other.",
"sn": {
"name": "Steuernummer",
"description": "Spouses filing taxes jointly or individuals.",
"potentially_endogenous": True,
},
}

Expand Down Expand Up @@ -133,7 +140,7 @@ def set_array_backend(backend: str):
"kindergeld_m",
"arbeitsl_geld_2_m_bg",
"kinderzuschl_m_bg",
"wohngeld_m_hh",
"wohngeld_m_wthh",
"unterhaltsvors_m",
"grunds_im_alter_m_eg",
"ges_rente_m",
Expand Down
19 changes: 19 additions & 0 deletions src/_gettsim/groupings.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

def create_groupings() -> dict[str, Callable]:
return {
"wthh_id": wthh_id_numpy,
"fg_id": fg_id_numpy,
"bg_id": bg_id_numpy,
"eg_id": eg_id_numpy,
Expand Down Expand Up @@ -211,3 +212,21 @@ def sn_id_numpy(
next_sn_id += 1

return numpy.asarray(result)


def wthh_id_numpy(
hh_id: numpy.ndarray[int],
wohngeld_vorrang_bg: numpy.ndarray[bool],
wohngeld_kinderzuschl_vorrang_bg: numpy.ndarray[bool],
) -> numpy.ndarray[int]:
"""
Compute the ID of the wohngeldrechtlicher Teilhaushalt.
"""
result = []
for index, current_hh_id in enumerate(hh_id):
if wohngeld_vorrang_bg[index] or wohngeld_kinderzuschl_vorrang_bg[index]:
result.append(current_hh_id * 100 + 1)
else:
result.append(current_hh_id * 100)

return numpy.asarray(result)
7 changes: 6 additions & 1 deletion src/_gettsim/parameters/wohngeld.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1970,7 +1970,12 @@ klimakomponente_m:
5: 39.20
jede_weitere_person: 4.8
rounding:
wohngeld_vor_vermög_check_m_hh:
wohngeld_vor_vermög_check_m_bg:
1970-01-01:
base: 1
direction: nearest
reference: § 19 WoGG Abs.2 Anlage 3
wohngeld_vor_vermög_check_m_wthh:
1970-01-01:
base: 1
direction: nearest
Expand Down
44 changes: 25 additions & 19 deletions src/_gettsim/transfers/arbeitsl_geld_2/arbeitsl_geld_2.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

def arbeitsl_geld_2_m_bg(
arbeitsl_geld_2_vor_vorrang_m_bg: float,
wohngeld_vorrang_hh: bool,
wohngeld_vorrang_bg: bool,
kinderzuschl_vorrang_bg: bool,
wohngeld_kinderzuschl_vorrang_hh: bool,
wohngeld_kinderzuschl_vorrang_bg: bool,
erwachsene_alle_rentner_hh: bool,
) -> float:
"""Calculate final monthly subsistence payment on household level.
Expand All @@ -16,12 +16,12 @@ def arbeitsl_geld_2_m_bg(
----------
arbeitsl_geld_2_vor_vorrang_m_bg
See :func:`arbeitsl_geld_2_vor_vorrang_m_bg`.
wohngeld_vorrang_hh
See :func:`wohngeld_vorrang_hh`.
wohngeld_vorrang_bg
See :func:`wohngeld_vorrang_bg`.
kinderzuschl_vorrang_bg
See :func:`kinderzuschl_vorrang_bg`.
wohngeld_kinderzuschl_vorrang_hh
See :func:`wohngeld_kinderzuschl_vorrang_hh`.
wohngeld_kinderzuschl_vorrang_bg
See :func:`wohngeld_kinderzuschl_vorrang_bg`.
erwachsene_alle_rentner_hh
See :func:`erwachsene_alle_rentner_hh`.
Expand All @@ -30,10 +30,16 @@ def arbeitsl_geld_2_m_bg(
float with the income by unemployment insurance on household level.
"""
# TODO (@MImmesberger): No interaction between Wohngeld/ALG2 and Grundsicherung im
# Alter (SGB XII) is implemented yet. We assume for now that households with only
# retirees are eligible for Grundsicherung im Alter but not for ALG2/Wohngeld. All
# other households are not eligible for SGB XII, but SGB II / Wohngeld. Once this is
# resolved, remove the `erwachsene_alle_rentner_hh` condition.
# https://github.com/iza-institute-of-labor-economics/gettsim/issues/703
if (
wohngeld_vorrang_hh
wohngeld_vorrang_bg
or kinderzuschl_vorrang_bg
or wohngeld_kinderzuschl_vorrang_hh
or wohngeld_kinderzuschl_vorrang_bg
or erwachsene_alle_rentner_hh
):
out = 0.0
Expand Down Expand Up @@ -70,9 +76,9 @@ def arbeitsl_geld_2_regelbedarf_m_bg(

def _arbeitsl_geld_2_alleinerz_mehrbedarf_m_bg(
alleinerz_bg: bool,
anz_kinder_bg: int,
anz_kinder_bis_6_bg: int,
anz_kinder_bis_15_bg: int,
anz_kinder_fg: int,
anz_kinder_bis_6_fg: int,
anz_kinder_bis_15_fg: int,
arbeitsl_geld_2_params: dict,
) -> float:
"""Compute additional need for single parents.
Expand All @@ -87,12 +93,12 @@ def _arbeitsl_geld_2_alleinerz_mehrbedarf_m_bg(
----------
alleinerz_bg
See :func:`alleinerz_bg`.
anz_kinder_bg
See :func:`anz_kinder_bg`.
anz_kinder_bis_6_bg
See :func:`anz_kinder_bis_6_bg`.
anz_kinder_bis_15_bg
See :func:`anz_kinder_bis_15_bg`.
anz_kinder_fg
See :func:`anz_kinder_fg`.
anz_kinder_bis_6_fg
See :func:`anz_kinder_bis_6_fg`.
anz_kinder_bis_15_fg
See :func:`anz_kinder_bis_15_fg`.
arbeitsl_geld_2_params
See params documentation :ref:`arbeitsl_geld_2_params <arbeitsl_geld_2_params>`.
Expand All @@ -110,13 +116,13 @@ def _arbeitsl_geld_2_alleinerz_mehrbedarf_m_bg(
max(
# Minimal Mehrbedarf share. Minimal rate times number of children
arbeitsl_geld_2_params["mehrbedarf_anteil"]["min_1_kind"]
* anz_kinder_bg,
* anz_kinder_fg,
# Special case if 1 kid below 6 or 2,3 below 15.
(
arbeitsl_geld_2_params["mehrbedarf_anteil"][
"kind_unter_7_oder_mehr"
]
if (anz_kinder_bis_6_bg >= 1) or (2 <= anz_kinder_bis_15_bg <= 3)
if (anz_kinder_bis_6_fg >= 1) or (2 <= anz_kinder_bis_15_fg <= 3)
else 0.0
),
),
Expand Down
Loading

0 comments on commit cd0cffd

Please sign in to comment.