Functional Weave
Code in Rust

lending.amortisation-schedule@1.0.1

README.md

3,116 bytes · view raw

# lending.amortisation-schedule

The repayment table for a level-payment loan: for every period, the payment,
the interest, the part that repays the loan, and the balance left. It is the
table a mortgage offer or a loan statement shows, built the way the lender's
ledger builds it.

## How each row is made

1. The level payment comes from lending.loan-payment, rounded with the mode
   you pass.
2. Each period's interest is the opening balance × rate / paymentsPerYear,
   rounded half-up to a whole minor unit: that is the amount actually posted.
3. The payment pays that interest first; the rest reduces the balance.
4. The final payment is not the level payment. It is whatever is owed:
   the remaining balance plus that period's interest. So the balance ends at
   exactly zero, never at -3p or +2p.

The final payment is where every penny of rounding collects. With the payment
rounded half-up it is within a few pence of the others; rounded `up` it is a
little smaller, rounded `down` a little larger. If a rounded-up payment would
clear the loan before the term ends (possible only for tiny loans, such as
25p over 12 months), the schedule stops at the payment that clears it, so it
can have fewer rows than the term has payments. It never has a row with a
payment of zero.

The totals are the sums of the posted rows: totalPaid = principal +
totalInterest, exactly.

## What it does not do

The periods are equal and the rate is nominal and fixed, as in
lending.loan-payment. It does not model daily interest, payment holidays,
rate changes, fees or overpayments (lending.overpayment-effect covers a one-off
overpayment).

## Limits

The same arguments as lending.loan-payment, so at most 3000 rows. A balance
whose interest product (balance × basis points) would exceed 2^63 - 1 is an
error ("balance too large for exact interest") in every language.

The module also exports `periodInterest(balance, annualRateBasisPoints,
paymentsPerYear)`, the rounding rule of step 2.

## Before you rely on this

**Not professional advice.** This capability calculates lending figures from published rules. It is a software component for developers, not financial advice. Rules change and every rate here has an effective date. Check that the dates cover your case. Verify results against the official sources listed above, and have a consumer-credit compliance specialist review how you use it, before anyone relies on the output. Provided "as is" under its licence, without warranty.

**Unreviewed.** This capability's implementations agree in every language and pass its published test vectors, which were worked out from the official sources cited. But no qualified consumer-credit compliance specialist has yet checked those vectors, or confirmed that the capability covers the cases it claims. Treat it as a draft. Do not use it for real people, money or decisions without your own expert review. Once a qualified reviewer signs off, this notice is replaced with their name, qualification and the date. Each new version needs fresh sign-off.

1.0.1 marks it unreviewed. The code and the tests are unchanged.