Sådan byggede jeg en låneberegner i PHP
Dette gæsteindlæg er skrevet af Casper Schneidereit, der her vil fortælle hvordan han byggede en god låneberegner i PHP.
I dette indlæg vil jeg gennemgå, hvordan jeg har bygget en god låneberegner i PHP. Jeg driver til daglig en blog, hvor jeg skriver om ejendomsinvestering, afkast m.v. og der har jeg ofte haft brug for, at kunne regne renter og tilbagebetalingstid på et lån. Mange af dem som er tilgængelige på nettet er direkte fejlagtige, eller i bedste fald blot lidt unøjagtige, da de typisk bygger på en simplificeret måde at beregner renter på, som ikke harmonerer med den måde, som bankerne bruger i dag. Jeg deler ikke hele koden, men jeg vil dele nogle af de nøglefunktioner, som gør, at du nemt kan konstruere en tilsvarende eller bedre selv.
For at kunne beregne tilbagebetalingen af lån, skal vi som udgangspunkt have følgende input:
- Hovedstol inklusive omkostninger – Hvor stort et lån skal betales tilbage?
- Afdrag – Hvor stort er afdraget?
- Frekvens for afdrag – Hvor ofte bliver der afdraget?
- Rente – Hvad er renten på lånet?
- Frekvens for rentetilskrivninger – Hvor ofte bliver renten tilskrevet?
Dette er nemt nok, da vi blot beder brugeren om at indtaste disse.
Rentekonvention
Den første problematik er rentekonvention, som beskriver længden af at år og en måned i en renteberegningsmæssig forstand. I gamle dage, da computeren endnu ikke eksisterede, benyttede de fleste typisk en rentekonvention der hed 360/30. Det betyder, at der regnes med et år på 360 dage og en måned på 30 dage, uanset om det var skudår eller almindeligt år, eller om det var december eller februar. Fordelen var naturligvis, at det gjorde det nemt at regne renter og afdrag for et lån, da man ikke behøvede at kende antallet af dage i de specifikke år og antallet af dage i de specifikke måneder.
En computer kan dog nemt løse det, og ovenstående rentekonvention er umiddelbart til låntagerens (bankkundens) fordel og långiveren (bankens) ulempe. I dag bruger man derfor en rentekonvention kaldet ACT/ACT, som tager udgangspunkt i det aktuelle antal dage for det specifikke år og det aktuelle antal dage for den specifikke måned (Actual / Actual).
ACT/ACT giver os en række problemstillinger. Vi skal kende længden på de enkelte måneder og år, før vi kan beregne renten. Dermed er det heller ikke ligegyldigt, om lånet er optaget i april 2017 eller januar 2015. Vi har derfor behov for endnu et brugerinput:
- Dato for låneoptagelsen – Altså præcis hvilken dato, lånet er optaget og begynder at være rentebærende for.
Rentedag
Den her artikel er lavet med udgangspunkt i, at jeg har kigget på, hvordan mine aktuelle lån bliver afbetalt og hvilke regler der tilsyneladende gør sig gældende herfor. Ud fra det, ser det ud til, at den mindste tidsmæssige bestanddel, der arbejdes med i forhold til rente er 1 dag. Derfor skal låneberegneren heller ikke arbejde med tidsintervaller mindre end en hel dag.
Hverdag eller helligdag
Et andet væsentligt parameter er, hvornår afdraget bliver tilskrevet lånet. Nogle af min lån bliver afdraget hævet den første dag i måneden og andre bliver hævet den sidste dag i måneden. Det kræver så endnu et input fra brugeren:
- Afdragstidspunkt – Om der afdrages den første eller sidste dag.
Hverdag eller helligdag (og lørdag)
Der er måneder, hvor afdraget først var tilskrevet den 2 eller 3 i måneden. Det skyldes, at der ikke er bevægelser lørdag eller søndag, og jeg skulle derfor tage højde for om en dag var en almindelig hverdag (bankdag) eller en søndag.
En helligdag giver også problemer, og der bør derfor også tages højde for dem. Det kan gøre lånet skævt med en mikroskopisk del, hvis beregneren tror, at et afdrag er registreret på lånet f.eks. mandag den 1 januar 2018, men det faktisk først sker tirsdag den 2 januar 2018 (da 1 januar er nytårsdag). Hermed bliver der fejlberegnet med værdien af en dags rente af størrelsen på det respektive afdrag. I min aktuelle beregner har jeg ikke taget højde for det, men det kommer i den næste version.
Kode til at løse en række af problemerne
Jeg har via mine bankudtog for lånene fået tegnet en masse problemer op, som der skal kodes en løsning på.
Jeg bruger de her to funktioner til at finde antallet af dage i et specifikt år og antallet af dage i en specifik måned:
# Find days in specific year function days_in_year($year) { return (date("z", mktime(0,0,0,12,31,$year)) + 1); } # Find days in specific month function days_in_month($year,$month) { return cal_days_in_month(CAL_GREGORIAN, $month, $year); }
Herudover har jeg denne funktion, som giver mig ugedagsnummeret på en specifik dato:
# Find number of weekday for a specific date function week_data($year,$month,$day) { return date('w', strtotime($year.'-'.$month.'-'.$day)); #sunday = 0, saturday = 6 }
Jeg bruger herudover denne funktion til at beregne den daglige rente for det pågældende år:
# Calc interest for this year function daily_interest($interest, $days) { return $interest/100/$days; }
For at løse problemet med at identificere (danske) helligdage, påtænker jeg primært at bruge strtotime(). Jeg skal blot have identificeret alle mulige helligdage, og hvordan reglerne er de for de enkelte.
Resten er stort set bare et loop, hvor hver gennemgang svarer til en dag. Der kan maksimalt regnes med 30.000 dage, og det er blandt andet for at undgå situationer, hvor brugeren taster lån ind, som vil kræve hundredvis af år at tilbagebetale. Kan gældes ikke afdrages – det vil sige at renteudgiften overstiger de månedlige afdrag, så afbrydes beregningen også efter 3 år.
I det her loop bliver der for den enkelte dag undersøgt om:
- Det er en dag, hvor der skal laves et afdrag
- Det er en dag, hvor der skal tilskrives renter
Herudover er der en række tællere, som hele tiden holder styr på datoen, antallet rente dage, renten, rentetilskrivninger o.s.v.
Optimeringsmuligheder
Alle mine lån er med månedlige afdrag, men realkreditlån har typisk kvartalvise afdrag (ved hver termin). Min låneberegner tager kun udgangspunkt i lån med månedlige afdrag, som enten afdrages i starten eller slutningen af en måned. Det forventer jeg også at rette i den nye version.
Du kan tage et kig på den her. Jeg er selv meget glad for simuleringsdelen, som tager udgangspunkt i input, men beregner lånet med andre afdrag og renteinput. Det giver et super godt billede af, hvor meget bare 0,25% ved renten, kan gøre for den samlede udgift.