Präsenzphase: Solidaritätszuschlag#

import numpy as np
import pandas as pd

pd.options.plotting.backend = "plotly"

Wie Sie bei der Arbeit mit dem Steuerrechner gemerkt haben, hat uns letzte Woche mit dem Solidaritätszuschlag noch ein wesentliches Element der Einkommensteuer gefehlt.

Der Solidaritätszuschlag auf die Einkommensteuer wurde zu Jahresbeginn 2021 für die meisten Einkommensteuerzahler abgeschafft, so dass seitdem ausschließlich Haushalte mit hohem Einkommen ihn noch zahlen müssen. Alles in allem war diese Veränderung des Solidaritätszuschlags die größte Einkommensteuerrefom der letzten 20 Jahre. Im Jahr 2023 wurde der Solidaritätszuschlag nochmals leicht angepasst. Die große Reform war allerdings im Jahr 2021, weshalb wir heute auch Zahlen für 2021 betrachten.

Da die Reform uns zudem hilft, ein Verständnis für die Komplexität des Steuersystems zu gewinnen, werden wir uns zunächst die Formel für den 2020er Solidaritätszuschlag stückweise aufbauen und dann die 2021er Reform modellieren.

Im Vergleich zu letzter Woche nutzen Sie heute die folgenden neuen Python-Skills:

  • Selbstständig eigene Funktionen schreiben

  • Inputs zu Funktionen hinzufügen

  • Mehrere Informationen in einem Graphen zu plotten

Aufgabe 1: Solidaritätszuschlag verstehen (70 Minuten)#

Der Solidaritätszuschlag ist leider nicht ganz einfach zu verstehen, deshalb werden wir ihn schrittweise herleiten. Am Ende von Aufgabe 1 werden Sie eine Funktion für den Solidaritätszuschlag haben, mit der wir dann in Aufgabe 2 die Reform 2021 untersuchen können.

Von letzter Woche haben wir noch die Funktion für die Einkommensteuer 2020…

def einkommensteuer_2020(zu_versteuerndes_einkommen):
    """Berechne Einkommensteuer 2020.

    Args:
        zu_versteuerndes_einkommen (float): Zu versteuerndes Einkommen

    Output:
        Steuerlast(float): Steuerlast 2020
    """
    x = np.floor(zu_versteuerndes_einkommen)
    y = (x - 9_408) / 10_000
    z = (x - 14_532) / 10_000

    if x <= 9_408:
        return 0
    elif x <= 14_532:
        return np.floor((972.87 * y + 1_400) * y)
    elif x <= 57_051:
        return np.floor((212.02 * z + 2_397) * z + 972.79)
    elif x <= 270_500:
        return np.floor(0.42 * x - 8_963.74)
    else:
        return np.floor(0.45 * x - 17_078.74)

…und Code, der uns ein DataFrame erzeugt.

max_einkommen = 100_000
anzahl_schritte = 100
data = pd.DataFrame(columns=["einkommen"])
data["einkommen"] = np.linspace(1000, max_einkommen, anzahl_schritte)

Aufwärmen (5 Minuten)#

Fügen Sie eine Spalte einkommensteuer mit der Einkommensteuerlast in 2020 zu data hinzu.

Aufgabe 1.1: Ergänzungssteuern generell (5 Minuten)#

In der vereinfachenden öffentlichen Diskussion wurde es häufig so dargestellt, dass der Soli die Steuerlast um 5,5% erhöhte. Wie wir gleich sehen werden, ist das nicht vollständig richtig.

Fügen Sie nichtsdestotrotz dem DataFrame die Spalte soli_vereinfacht hinzu, in der Sie einen entsprechend vereinfachten Soli des Jahres 2020 berechnen.

Für Jahreseinkommen oberhalb von ca. 16.000€ sollten Sie, abgesehen von der Rundung, identische Werte wie der Steuerrechner erhalten.

data.loc[data["einkommen"] == 17_000]

Aufgabe 1.2: Fast korrekter Solidaritätszuschlag (20 Minuten)#

Auch der Soli hat ein progressives Element. Einkommen, für welche die Steuerlast niedriger war als die Freigrenze von 972€, waren komplett vom Soli befreit.

Schreiben Sie eine Funktion soli_fast_korrekt, die den so vereinfachten Solidaritätszuschlag berechnet.

  • Die Funktion hat zwei Skalare als Inputs: einkommensteuer und freigrenze.

  • In der Funktion setzen Sie mit Hilfe einer if-Bedingung den Soli für Einkommensteuerlasten unterhalb der Freigrenze auf Null.

  • Die Funktion gibt einen Skalar zurück (den so berechneten Solidaritätszuschlag)

Hier wird die Funktion soli_fast_korrekt auf den DataFrame data angewendet und die Spalte soli_fast_korrekt erstellt.

data["soli_fast_korrekt"] = data["einkommensteuer"].apply(
    lambda x: soli_fast_korrekt(einkommensteuer=x, freigrenze=972),
)

Überprüfen Sie die Plausibilität Ihrer Ergebnisse, indem Sie die Spalten mit Steuerlasten des vereinfachten und des fast korrekten Solis miteinander vergleichen.

display(data.head())
display(data.tail())

Aufgabe 1.3: Sprung in der Steuerlast bei fast korrektem Solidaritätszuschlag (20 Minuten)#

Erstellen Sie das DataFrame data_kleine_schritte ebenso wie zuvor data; allerdings sollte hier das Einkommen nur Werte in 1€-Schritten in einem sinnvollen Bereich rund um eine Steuerlast von 972€ annehmen.

In data_kleine_schritte sollten folgende Spalten vorhanden sein:

  • einkommen

  • einkommensteuer

  • soli_fast_korrekt

Plotten Sie die Soli-Steuerlast für

data_kleine_schritte["soli_fast_korrekt"]

gegen das Einkommen.

Was fällt Ihnen auf? Warum ist das problematisch?

Aufgabe 1.4: Vollständiger Solidaritätszuschlag (20 Minuten)#

Diese Aufgabe ist schwer, wenn Sie keine Python-Vorkenntnisse haben. Bitte brechen Sie in jedem Fall nach 20 Minuten ab / überspringen Sie die Aufgabe komplett, falls Sie spät dran sind. Sie kommen auch ohne eigene Lösung weiter!

Um das Problem zu lösen, ist im Gesetz festgelegt, dass der Grenzsteuersatz des Soli nie größer als 20% sein darf. Wörtlich steht im Gesetzestext: “Der Solidaritätszuschlag beträgt 5,5 Prozent der Bemessungsgrundlage. Er beträgt nicht mehr als 20 Prozent des Unterschiedsbetrages zwischen der Einkommensteuer (…) und der (…) Freigrenze.”

Schreiben Sie eine Funktion soli, die den Soli korrekt abbildet. Die Funktion sollte drei Skalare als Inputs nehmen: einkommensteuer, freigrenze und soli_rate_max, wobei soli_rate_max den Faktor bezeichnet, der für das Jahr 2020 20% beträgt.

Die Vorgabe hinsichtlich des Grenzsteuersatzes können Sie mittels einer weiteren if-Abfrage implementieren, die ungefähr so aussehen sollte:

if 0.055 * einkommensteuer > soli_rate_max * unterschiedbetrag:

Fügen Sie dem DataFrame data_kleine_schritte die Spalte soli mit dem korrekten Solidaritätszuschlag hinzu.

Plotten Sie die Spalten soli_fast_korrekt und soli gegen das Einkommen.

Aufgabe 1.5 Bonus-/Kontrollaufgabe: Solidaritätszuschlag in GETTSIM#

In wenigen Wochen werden wir anfangen mit GETTSIM zu arbeiten. In diesem Simulationsprogramm ist nahezu vollständig das deutsche Steuer- und Sozialsystem implementiert, dementsprechend findet man dort auch den Soli. Er ist dort deutlich eleganter implementiert. Wenn Sie Zeit haben, vollziehen Sie nach, warum Sie das gleiche Ergebnis erhalten.

Falls Sie in Aufgabe 1.4 keine funktionierende Funktion bauen konnten, können Sie auch mit dieser Funktion weiterarbeiten. Sie können die GETTSIM Funktion natürlich auch zum Abgleich der Ergebnisse aus der Aufgabe 1.4 nutzen.

def gettsim_soli(einkommensteuer, freigrenze, soli_rate_max):
    """Berechne Solidaritätszuschlag.

    Args:
        einkommensteuer (float): Einkommensteuerlast
        freigrenze (float): Solidaritätszuschlagsfreigrenze für die Einkommensteuerlast
        soli_rate_max (float): Maximaler Grenzsteuersatz des Solidaritätszuschlags

    Output:
        soli (float): Steuerlast aus dem Solidaritätszuschlag
    """
    soli = np.minimum(
        0.055 * einkommensteuer,
        np.maximum(soli_rate_max * (einkommensteuer - freigrenze), 0),
    )

    return soli

Aufgabe 2: Reform des Solidaritätszuschlags 2021 (35 Minuten)#

Die technische Einführung in den Solidaritätszuschlag in Aufgabe 1 hat Ihnen hoffentlich einen guten ersten Eindruck dafür gegeben, dass es im Steuer- und Sozialsystem selbst bei auf den ersten Blick einfach aussehenden Regelungen sehr schnell kompliziert wird. Im Regelfall werden wir in Zukunft die Politiken nicht selbst implementieren, sondern auf GETTSIM zurückgreifen.

Sie können jetzt, zumindest für Einpersonenhaushalte, die deutsche Einkommensteuer vollständig ausrechnen. Das ermöglicht es uns, die große Reform des Solidaritätszuschlags von 2020 auf 2021 zu untersuchen.

Die Reform besteht aus zwei Elementen:

  1. Der Freibetrag erhöht sich von 972€ auf 16.956€.

  2. Der Faktor soli_rate_max sinkt von 20% auf 11,9%.

Im Jahr 2023 ist der Freibetrag nochmal auf 17.543€ gestiegen.

Aufgabe 2.1: Solidaritätszuschlag 2021 (5 Minuten)#

Nehmen Sie an, dass die Formel zur Berechung der Einkommensteuer im Jahr 2021 unverändert zum Jahr 2020 ist. (Die Änderungen an der Einkommensteuer sind von 2020 auf 2021 tatsächlich nicht groß.)

Berechnen Sie den Soli im Jahr 2021 und anschließend die gesamte Steuerlast (inklusive Soli) für das Jahr 2021. Nutzen Sie dafür entweder Ihre Funktion soli oder die für Sie bereitgestellte Funktion gettsim_soli. Sie können Ihre Ergebnisse mit diesem Soli Rechner abgleichen.

Nutzen Sie für die gesamte zweite Aufgabe das DataFrame data_reform.

max_einkommen = 120_000
anzahl_schritte = 121
data_reform = pd.DataFrame(columns=["einkommen"])
data_reform["einkommen"] = np.linspace(0, max_einkommen, anzahl_schritte)

data_reform["einkommensteuer"] = data_reform["einkommen"].apply(
    lambda x: einkommensteuer_2020(x),
)

Aufgabe 2.2: Solidaritätszuschlag 2020 (5 Minuten)#

Fügen Sie dem DataFrame data_reform zwei weitere Spalten mit a) dem Solidaritätszuschlag 2020 und b) der gesamten Steuerlast 2020 (inklusive Soli) hinzu.

Aufgabe 2.3: Effekt der Reform 2020 (18 Minuten)#

Berechnen Sie

  1. Die Änderung im Absolutbetrag der Steuerlast in Abhängigkeit vom Einkommen.

  2. Die prozentuale Änderung der Steuerlast in Abhängigkeit vom Einkommen.

Plotten Sie anschließend die absolute und die prozentuale Änderung in getrennten Graphen.

Die Kommunikation von Steuerreformen ist schwierig, weil die Änderung der Steuerlast abhängig vom Einkommen ist. Was sind die Vor- und Nachteile der beiden Darstellungsformen?

Aufgabe 2.4: Vollständige Abschaffung des Solidaritätszuschlags (7 Minuten)#

Fügen Sie dem Graphen mit der absoluten Änderung noch das Szenario hinzu, dass der Solidaritätszuschlag vollständig abgeschafft wird.

Aufgabe 3: Pentabilities (10min)#

Bitte bewerten Sie die Beiträge zur Gruppenarbeit in der Pentabilities-App. Bitte vergeben Sie über alle 5 Dimensionen hinweg Punkte für die Verhaltensweisen, welche Sie heute beobachten konnten. Denken Sie bitte daran, sowohl die Beiträge der Kommiliton:innen Ihrer Gruppe als auch Ihre eigenen zu bewerten.