Aktuell arbeite ich an einem größeren Laminas PHP Projekt zur Schadenregulierung in der Industrieversicherung. Gestern hat mein derzeitiger Kunde während einer Videokonferenz die deutsche Zinsberechnungsmethode erwähnt, um Zinsen vom Schadentag bis hin zur entgültigen Bereitstellung der Entschädigungsleistung zu berechnen. Mich als gelernten Bankkaufmann hat das natürlich ziemlich getriggert. Ich hab das alles mal gelernt und dann steht man da wie der Ochs vor dem Berg.
Wiederholung stärkt Wissen
Also habe ich mich heute mal hingesetzt und mir die deutsche Zinsberechnungsmethode angesehen. Schon lange nicht mehr gemacht. Machen wir uns mal ehrlich. Bei Google einen Zinsrechner zu finden ist einfacher, als sich den Rechenweg jedes mal selbst wieder ins Gedächtnis zu rufen. Andererseits ist es simple Mathematik. Das kann doch nicht so schwer sein.
Bereiten wir das mal programmatisch auf. Da es neben der deutschen Zinsberechnungsmethode auch noch andere Methoden zur Zinsberechnung gibt, gehe ich das Thema jetzt einfach mal der Logik eines Programmierers folgend an. Für die Zinsberechnung benötigen wir grundlegend vier Eigenschaften:
- Einen Betrag, den es zu verzinsen gilt
- Einen Zins, den wir zur Berechnung heran ziehen
- Ein Start Datum
- Ein End Datum
Da diese vier Eigenschaften immer gleich sind, kann man das doch ziemlich gut abstrahieren.
Abstraktion FTW!
In der Programmierung fährt man mit Interfaces und Abstraktionen eigentlich immer einen sicheren Kurs. Also machen wir das an dieser Stelle einfach mal. Denn wir wissen zu diesem Zeitpunkt ja schon, dass es nicht nur die deutsche Methode zur Berechnung von Zinsen gibt, sondern eben auch andere. Wir sollten also grundsätzlich erstmal verallgemeinern.
<?php
declare(strict_types=1);
namespace Marcel\Math\Interest\Calculator;
use DateTimeImmutable;
interface InterestCalculatorInterface
{
public function calculate(): float;
public function getInvestment(): float;
public function getInterest(): float;
public function getStartDate(): DateTimeImmutable;
public function getEndDate(): DateTimeImmutable;
}
Das Interface steht soweit. Neben den vier Getter-Methoden für unsere grundsätzlichen Eigenschaften besitzt das Interface eine calculate Methode, die die Zinsen berechnet.
<?php
declare(strict_types=1);
namespace Marcel\Math\Interest\Calculator;
use DateTimeImmutable;
abstract class AbstractInterestCalculator implements InterestCalculatorInterface
{
public function __construct(
protected readonly float $investment,
protected readonly float $interest,
protected readonly DateTimeImmutable $start,
protected readonly DateTimeImmutable $end
) {}
public function getInvestment(): float
{
return $this->investment;
}
public function getInterest(): float
{
return $this->interest;
}
public function getStartDate(): DateTimeImmutable
{
return $this->start;
}
public function getEndDate(): DateTimeImmutable
{
return $this->end;
}
}
Die Abstraktion für unseren Zinsrechner beinhaltet alle Getter-Methoden, die das Interface vorgibt. Darüber hinaus ist hier bereits unser Konstruktor enthalten, der mittels Constructor Property Promotion die entsprechenden Eigenschaften für unseren Zinsrechner setzt.
Somit hätten wir schon mal die Basis für unseren Zinsrechner.
Mathemathische Theorie
Die deutsche Methode zur Zinsberechnung geht davon aus, dass jeder Monat 30 Tage besitzt. Ja, auch der Februar besitzt unabhängig von einem Schaltjahr immer 30 Tage in diesem Szenario. Daraus folgend besitzt das Zins-Jahr 360 Tage. Auf Basis dieser Voraussetzungen werden dann die Tage zwischen dem Beginn und dem Ende der Zinsberechnung gezählt.
Beispiele:
- 10.01.2023 – 28.02.2023: 48 Tage (20 + 28 Tage)
- 10.01.2023 – 10.03.2023: 60 Tage (20 + 30 + 10 Tage)
- 28.02.2023 – 10.03.2023: 12 Tage (2 + 10 Tage)
Daraus ergeben sich zur Berechnung der zur Verzinsung heranzuziehenden Tage anhand des Beispiels 03. März 2023 – 16. Juli 2023 folgende Schritte:
- Berechnung der verbleibenden Tage im ersten Monat.
Die Differenz aus maximal 30 Tagen in einem Monat und den bereits vergangenen Tagen im ersten Monat des Zeitraums. (30 – 03 = 27 Tage) - Ermittlung der vollen Monate
Alle vollen Monate werden mit 30 multipliziert. (April, Mai und Juni * 30 = 90 Tage) - Die abgelaufenen Tage des letzten Monats.
Juli: 16 Tage - Die Werte aus dem ersten bis dritten Schritt addieren:
03.03.2023 – 16.07.2023: 27 + 90 + 16 = 133 Tage.
Easy, oder?
Programmatische Praxis
Aus der mathematischen Theorie lässt sich somit in sehr einfacher Zinsrechner nach deutscher Methode programmieren. Durch die bereits erledigte Abstraktion ist es auch nicht mehr so viel.
<?php
declare(strict_types=1);
namespace Marcel\Math\Interest\Calculator;
class GermanInterestCalculator extends AbstractInterestCalculator
{
protected int $maxDaysOfMonth = 30;
protected int $maxDaysOfYear = 360;
public function calculate(): float
{
$total = 0;
$daysOfFirstMonth = $this->getDaysOfFirstMonth();
$fullMonths = $this->getFullMonths();
$daysOfFullMonths = $fullMonths * $this->maxDaysOfMonth;
$daysOfLastMonth = $this->getDaysOfLastMonth();
$totalDays = $daysOfFirstMonth + $daysOfFullMonths + $daysOfLastMonth;
$total = round($this->getInvestment() * $this->getInterest() / 100 * $totalDays / $this->maxDaysOfYear, 2);
return $total;
}
protected function getDaysOfFirstMonth(): int
{
return $this->maxDaysOfMonth - $this->getStartDate()->format('j');
}
protected function getFullMonths(): int
{
$start = $this->getStartDate()->modify('first day of next month');
$interval = $start->diff($this->getEndDate());
$yearsInMonth = $interval->format('%r%y') * 12;
$months = $interval->format('%r%m');
$total = $yearsInMonth + $months;
return $total;
}
protected function getDaysOfLastMonth(): int
{
return (int) $this->getEndDate()->format('j');
}
}
Unser Zinsrechner implementiert die calculate Methode des Interfaces mit der wir unsere Berechnung ausführen können. Die zuvor genannten vier Schritte zur Ermittlung der zur Berechnung anzusetzenden Tage werden mit den Methoden getDaysOfFirstMonth(), getDaysOfLastMonth() und getFullMonths() ausgeführt.
Beim Beispiel vom 03.03.2023 bis zum 16.07.2023 ergibt sich bei einem Betrag von 5000,00 EUR und einem Zinsatz von 1,5% p.a. ein Ergebnis von 27,71 EUR (5000,00 * (133/360) * (1,5 / 100)).
Fazit
Manchmal ist es ganz gut schon längst Verlerntes wieder ins Gedächtnis zu rufen. Ich ereinnere mich noch sehr genau, wie ich damals in der Berufsschule gerade beim Thema Zins- und Zinseszins-Berechnung eher medium abschnitt. Heute, in Verbindung mit PHP, hat es mir allerdings Spaß bereitet.
Was meint ihr? Würdet ihr einen Zinsrechner ähnlich abstrahieren? Habt ihr etwas hinzuzufügen? Habe ich Euch helfen können? Eure Meinung finde ich immer ganz spannend. Schreibt Eure Gedanken einfach in die Kommentare.
Danke Dir!