Header menu logo FSharp.Finance.Personal

Amortisation FAQ

How is interest calculated?

Initial calculations

When setting up a schedule, interest is calculated based on a simple schedule that assumes that all payments will be made on time and in full.

Running calculations

While a schedule is active (i.e. it has started and the principal balance is non-zero), the interest is calculated based on the scheduled and actual payments made. The day of any scheduled or actual payment constitutes an event in the amortisation schedule, and simple interest is calculated based on the principal (+ fees) balance and the number of days since the last event.

For a flowchart, see Amortisation Flowchart.

Basis of calculations for the following questions

The basic schedule we will use here is a loan of £1000 advanced on 24 April 2025, paid back over 4 months starting one month after the advance date. The loan has a daily interest rate of 0.798% and a cap of 0.8% per day as well as a cap of 100% of the principal amount. The examples may use either the actuarial-interest method or the add-on-interest method.


Show/hide parameters
let parameters0: Parameters = {
    Basic = {
        EvaluationDate = Date(2025, 4, 24) // the date we're evaluating the schedule
        StartDate = Date(2025, 4, 24)
        Principal = 1000_00L<Cent>
        ScheduleConfig =
            AutoGenerateSchedule {
                UnitPeriodConfig = Monthly(1, 2025, 5, 24)
                ScheduleLength = PaymentCount 4
            }
        PaymentConfig = {
            LevelPaymentOption = LowerFinalPayment
            Rounding = RoundUp
        }
        FeeConfig = ValueNone
        InterestConfig = {
            Method = Interest.Method.Actuarial
            StandardRate = Interest.Rate.Daily(Percent 0.798m)
            Cap = {
                TotalAmount = Amount.Percentage(Percent 100m, Restriction.NoLimit)
                DailyAmount = Amount.Percentage(Percent 0.8m, Restriction.NoLimit)
            }
            Rounding = RoundDown
            AprMethod = Apr.CalculationMethod.UnitedKingdom 3
        }
    }
    Advanced = {
        PaymentConfig = {
            ScheduledPaymentOption = AsScheduled
            Minimum = DeferOrWriteOff 50L<Cent>
            Timeout = 3<DurationDay>
        }
        FeeConfig = ValueNone
        ChargeConfig = None
        InterestConfig = {
            InitialGracePeriod = 3<DurationDay>
            PromotionalRates = [||]
            RateOnNegativeBalance = Interest.Rate.Zero
        }
        SettlementDay = SettlementDay.NoSettlement // no settlement quotation requested
        TrimEnd = false // don't clip unrequired payments from the end of the schedule
    }
}

What happens if a customer were to not make their repayment on time?

Let's take a look at the amortisation schedules to illustrate this. First we will look at the actuarial-interest method and then the add-on-interest method.

Note: As a general principle, for payments that are not yet due it is assumed that they will be paid on time and in full. This is to provide for a more realistic projection of the schedule.

Actuarial Interest

Here's the schedule prior to any actual payments being made (looking at it from day 0). The main thing to note is that the principal balance at the end of the schedule is zero, meaning it is fully amortised.

Show/hide code
let amortisation0 =
    amortise
        parameters0 //the parameters defined above
        Map.empty // no actual payments made
Day Datestamp Advances Scheduled payment Window Payment due Actual payments Net effect Payment status Balance status Actuarial interest New interest Interest portion Principal portion Interest balance Principal balance Settlement figure
★ 0 2025-04-24 1,000.00 n/a 0 0.00 n/a 0.00 information only open 0.0000 0.0000 0.00 0.00 0.0000 1,000.00 1,000.00
30 2025-05-24 n/a original 417.72 1 417.72 n/a 417.72 not yet due open 239.4000 239.4000 239.40 178.32 0.0000 821.68 821.68
61 2025-06-24 n/a original 417.72 2 417.72 n/a 417.72 not yet due open 203.2672 203.2672 203.26 214.46 0.0000 607.22 607.22
91 2025-07-24 n/a original 417.72 3 417.72 n/a 417.72 not yet due open 145.3685 145.3685 145.36 272.36 0.0000 334.86 334.86
122 2025-08-24 n/a original 417.69 4 417.69 n/a 417.69 not yet due closed 82.8377 82.8377 82.83 334.86 0.0000 0.00 0.00

Now, let's assume that it's day 35 and no payments have been made, so the payment due on day 30 has been missed. The schedule would look like this:

Show/hide code
let parameters1 = {
    parameters0 with
        Basic.EvaluationDate = Date(2025, 5, 29) // evaluate the schedule on day 35
}

let amortisation1 = amortise parameters1 Map.empty // no actual payments made
Day Datestamp Advances Scheduled payment Window Payment due Actual payments Net effect Payment status Balance status Actuarial interest New interest Interest portion Principal portion Interest balance Principal balance Settlement figure
0 2025-04-24 1,000.00 n/a 0 0.00 n/a 0.00 none scheduled open 0.0000 0.0000 0.00 0.00 0.0000 1,000.00 1,000.00
30 2025-05-24 n/a original 417.72 1 417.72 n/a 0.00 missed payment open 239.4000 239.4000 0.00 0.00 239.4000 1,000.00 1,239.40
★ 35 2025-05-29 n/a n/a 1 0.00 n/a 0.00 information only open 39.9000 39.9000 0.00 0.00 279.3000 1,000.00 1,279.30
61 2025-06-24 n/a original 417.72 2 417.72 n/a 417.72 not yet due open 207.4800 207.4800 417.72 0.00 69.0600 1,000.00 1,069.06
91 2025-07-24 n/a original 417.72 3 417.72 n/a 417.72 not yet due open 239.4000 239.4000 308.46 109.26 0.0000 890.74 890.74
122 2025-08-24 n/a original 417.69 4 417.69 n/a 417.69 not yet due open 220.3513 220.3513 220.35 197.34 0.0000 693.40 693.40

Note: You can see that a new event at day 35 has been created, as we are observing the schedule on that day. This capitalises the interest that has accrued so far so that we can see the principal balance on that day.

As the payment due on day 30 has been missed, the interest that has accrued is not paid off and is added to the interest balance. This means that any subsequent payments would need to clear the interest balance before the principal balance is reduced, and this means that the principal balance remains higher for longer. Looking at the principal balance at the end of the schedule shows that this has not-insubstantial consequences, as there is still £693.40 outstanding.

Add-On Interest

Here's the schedule prior to any actual payments being made (looking at it from day 0). This time the interest is added up-front, with an initial interest balance of £815.56. The interest is paid off before the principal, so more interest is accrued in total than under the actuarial-interest method. The principal at the end of the schedule is zero, meaning it is fully amortised.

Show/hide code
let parameters2 = {
    parameters0 with
        Basic.InterestConfig.Method = Interest.Method.AddOn // use the add-on interest method
}

let amortisation2 = amortise parameters2 Map.empty // no actual payments made
Day Datestamp Advances Scheduled payment Window Payment due Actual payments Net effect Payment status Balance status Actuarial interest New interest Interest portion Principal portion Interest balance Principal balance Settlement figure
★ 0 2025-04-24 1,000.00 n/a 0 0.00 n/a 0.00 information only open 0.0000 0.0000 0.00 0.00 816.5600 1,000.00 1,000.00
30 2025-05-24 n/a original 454.15 1 454.15 n/a 454.15 not yet due open 239.4000 0.0000 454.15 0.00 362.4100 1,000.00 1,239.40
61 2025-06-24 n/a original 454.15 2 454.15 n/a 454.15 not yet due open 247.3800 0.0000 362.41 91.74 0.0000 908.26 908.26
91 2025-07-24 n/a original 454.15 3 454.15 n/a 454.15 not yet due open 217.4374 0.0000 0.00 454.15 0.0000 454.11 454.11
122 2025-08-24 n/a original 454.11 4 454.11 n/a 454.11 not yet due closed 112.3377 0.0000 0.00 454.11 0.0000 0.00 0.00

Let's again assume that it's day 35 and no payments have been made, so the payment due on day 30 has been missed. The schedule would look like this:

Show/hide code
let parameters3 = {
    parameters0 with
        Basic.EvaluationDate = Date(2025, 5, 29) // evaluate the schedule on day 35
        Basic.InterestConfig.Method = Interest.Method.AddOn // use the add-on interest method
}

let amortisation3 = amortise parameters3 Map.empty // no actual payments made
Day Datestamp Advances Scheduled payment Window Payment due Actual payments Net effect Payment status Balance status Actuarial interest New interest Interest portion Principal portion Interest balance Principal balance Settlement figure
0 2025-04-24 1,000.00 n/a 0 0.00 n/a 0.00 none scheduled open 0.0000 0.0000 0.00 0.00 816.5600 1,000.00 1,000.00
30 2025-05-24 n/a original 454.15 1 454.15 n/a 0.00 missed payment open 239.4000 0.0000 0.00 0.00 816.5600 1,000.00 1,239.40
★ 35 2025-05-29 n/a n/a 1 0.00 n/a 0.00 information only open 39.9000 0.0000 0.00 0.00 816.5600 1,000.00 1,279.30
61 2025-06-24 n/a original 454.15 2 454.15 n/a 454.15 not yet due open 207.4800 0.0000 454.15 0.00 362.4100 1,000.00 1,362.41
91 2025-07-24 n/a original 454.15 3 454.15 n/a 454.15 not yet due open 239.4000 0.0000 362.41 91.74 0.0000 908.26 908.26
122 2025-08-24 n/a original 454.11 4 454.11 n/a 454.11 not yet due open 224.6854 134.3054 134.30 319.81 0.0000 588.45 588.45

As the payment due on day 30 has been missed, the interest balance stays higher for longer, meaning that the principal balance remains higher for longer. This means that more interest is accrued in total than the initial interest balance. To correct for this, new interest of £134.30 is added to the final schedule item. The principal balance at the end of the schedule is therefore £588.45.


Why is the final settlement amount lower for the add-on method?

You may well wonder, given that the add-on-interest method results in a higher amount of interest accruing than actuarial-interest method, why the final settlement amount (i.e. the final principal balance) is lower for the add-on method.

One interesting feature of the add-on method is that in the early days of the schedule, missed payments have no effect on the principal balance. Looking at the original add-on schedule, we see that the principal balance remains at £1000 until day 30. Any extra interest is only accrued if the principal balance remains outstanding at this level for longer than this. Looking at the schedule on day 35, we see that the principal balance remains at £1000 until day 61, meaning that extra interest is accrued, but only for 31 days out of 60 compared to the actuarial-interest method.


Why is the new interest only added at the very end of the schedule?

During the schedule, actual-payment amounts and timings may vary, some of which may well have an effect on the total interest accrued. If we were to make constant adjustments to the interest balance, this would become difficult to track. If subsequent payments were paid earlier than due this could even lead to a situation where interest was overpaid and a refund might be required. By making the interest adjustment at the end, we can avoid this situation.

How is the additional interest calculated?

Actuarial Interest

Given that the interest rate is usually fixed for the duration of the schedule, the interest accrued is purely a function of the principal balance and how many days it is outstanding:

graph LR A["$$\text{interest} = \text{principal balance} \times \text{daily interest rate} \times \text{days}$$"]

Therefore any variations will affect the interest accrued:

Add-On Interest

Though the interest is calculated up-front and added to the schedule as an initial interest balance, adjustments will need to be made if the payment schedule is not adhered to. At the end of the schedule, the total actuarial interest (calculated as stated in the Actuarial Interest section above) is compared to the initial interest balance and a correction is made to the final schedule item if necessary.

Is the additional interest calculated on the outstanding loan principal?

Indirectly, yes. At the end of the schedule, the total actuarial interest (calculated as stated in the Actuarial Interest section above) is compared to the initial interest balance and a correction is made to the final schedule item if necessary.

Where is the additional interest added?

For actuarial-interest, the interest is automatically adjusted during the schedule. For add-on interest, the adjustment is made at the end of the schedule.

When is the customer expected to pay off this additional interest?

If additional interest has accrued, the effect of this will be that the schedule is not fully amortised, i.e. the final principal balance is not zero. Deciding how to handle this is outside the scope of the library, and depends on business rules. There are a number of ways, including:

Is there a set maximum amount of days that are used as a limit for additional interest to be charged?

No, caps on interest charges are not based on the number of days, but on the interest caps set in the loan parameters. Both daily and total caps can be set, and these are defined as either a simple amount or a percentage of the principal amount.

What happens when a customer settles earlier than the agreed term?

First we will look at the actuarial-interest method and then the add-on-interest method.

Actuarial Interest

As a reminder, here's the schedule prior to any actual payments being made (looking at it from day 0).

Day Datestamp Advances Scheduled payment Window Payment due Actual payments Net effect Payment status Balance status Actuarial interest New interest Interest portion Principal portion Interest balance Principal balance Settlement figure
★ 0 2025-04-24 1,000.00 n/a 0 0.00 n/a 0.00 information only open 0.0000 0.0000 0.00 0.00 0.0000 1,000.00 1,000.00
30 2025-05-24 n/a original 417.72 1 417.72 n/a 417.72 not yet due open 239.4000 239.4000 239.40 178.32 0.0000 821.68 821.68
61 2025-06-24 n/a original 417.72 2 417.72 n/a 417.72 not yet due open 203.2672 203.2672 203.26 214.46 0.0000 607.22 607.22
91 2025-07-24 n/a original 417.72 3 417.72 n/a 417.72 not yet due open 145.3685 145.3685 145.36 272.36 0.0000 334.86 334.86
122 2025-08-24 n/a original 417.69 4 417.69 n/a 417.69 not yet due closed 82.8377 82.8377 82.83 334.86 0.0000 0.00 0.00

Now, let's assume that the first two payments have been made on time, and the customer decides to repay in full on day 70. The schedule would look like this:

Show/hide code
let parameters4 = {
    parameters0 with
        Basic.EvaluationDate = Date(2025, 7, 3) // evaluate the schedule on day 70
        Advanced.SettlementDay = SettlementDay.SettlementOnEvaluationDay // settlement quotation requested on day 70
}

let amortisation4 =
    amortise
        parameters4
        (Map [
            30<OffsetDay>, [| ActualPayment.quickConfirmed 417_72L<Cent> |]
            61<OffsetDay>, [| ActualPayment.quickConfirmed 417_72L<Cent> |]
        ]) // actual payments made on days 30 and 61
Day Datestamp Advances Scheduled payment Window Payment due Actual payments Generated payment Net effect Payment status Balance status Actuarial interest New interest Interest portion Principal portion Interest balance Principal balance Settlement figure
0 2025-04-24 1,000.00 n/a 0 0.00 n/a n/a 0.00 none scheduled open 0.0000 0.0000 0.00 0.00 0.0000 1,000.00 1,000.00
30 2025-05-24 n/a original 417.72 1 417.72 confirmed 417.72 n/a 417.72 payment made open 239.4000 239.4000 239.40 178.32 0.0000 821.68 821.68
61 2025-06-24 n/a original 417.72 2 417.72 confirmed 417.72 n/a 417.72 payment made open 203.2672 203.2672 203.26 214.46 0.0000 607.22 607.22
✓ 70 2025-07-03 n/a n/a 2 0.00 n/a 650.83 650.83 generated closed 43.6105 43.6105 43.61 607.22 0.0000 0.00 0.00
91 2025-07-24 n/a original 417.72 3 0.00 n/a n/a 0.00 no longer required closed 0.0000 0.0000 0.00 0.00 0.0000 0.00 0.00
122 2025-08-24 n/a original 417.69 4 0.00 n/a n/a 0.00 no longer required closed 0.0000 0.0000 0.00 0.00 0.0000 0.00 0.00

Note: You can see that a new event at day 70 has been created, as we are observing the schedule on that day, and have requested a settlement quotation on that day too.

The settlement quotation is £650.83, which is the sum required to pay off all outstanding balances, including any interest accrued up to that day. This fully amortises the schedule, and the remaining two payments on days 91 and 122 are no longer required. The total of the two payments is £835.41, meaning that the customer has saved £184.58 in interest.

Add-On Interest

As a reminder, here's the schedule prior to any actual payments being made (looking at it from day 0). This time the interest is added up-front, with an initial interest balance of £815.56.

Day Datestamp Advances Scheduled payment Window Payment due Actual payments Net effect Payment status Balance status Actuarial interest New interest Interest portion Principal portion Interest balance Principal balance Settlement figure
★ 0 2025-04-24 1,000.00 n/a 0 0.00 n/a 0.00 information only open 0.0000 0.0000 0.00 0.00 816.5600 1,000.00 1,000.00
30 2025-05-24 n/a original 454.15 1 454.15 n/a 454.15 not yet due open 239.4000 0.0000 454.15 0.00 362.4100 1,000.00 1,239.40
61 2025-06-24 n/a original 454.15 2 454.15 n/a 454.15 not yet due open 247.3800 0.0000 362.41 91.74 0.0000 908.26 908.26
91 2025-07-24 n/a original 454.15 3 454.15 n/a 454.15 not yet due open 217.4374 0.0000 0.00 454.15 0.0000 454.11 454.11
122 2025-08-24 n/a original 454.11 4 454.11 n/a 454.11 not yet due closed 112.3377 0.0000 0.00 454.11 0.0000 0.00 0.00

Let's assume again that the first two payments have been made on time, and the customer decides to repay in full on day 70. The schedule would look like this:

Show/hide code
let parameters5 = {
    parameters0 with
        Basic.EvaluationDate = Date(2025, 7, 3) // evaluate the schedule on day 70
        Basic.InterestConfig.Method = Interest.Method.AddOn // use the add-on interest method
        Advanced.SettlementDay = SettlementDay.SettlementOnEvaluationDay // settlement quotation requested on day 70
}

let amortisation5 =
    amortise
        parameters5
        (Map [
            30<OffsetDay>, [| ActualPayment.quickConfirmed 454_15L<Cent> |]
            61<OffsetDay>, [| ActualPayment.quickConfirmed 454_15L<Cent> |]
        ]) // actual payments made on days 30 and 61
Day Datestamp Advances Scheduled payment Window Payment due Actual payments Generated payment Net effect Payment status Balance status Actuarial interest New interest Interest portion Principal portion Interest balance Principal balance Settlement figure
0 2025-04-24 1,000.00 n/a 0 0.00 n/a n/a 0.00 none scheduled open 0.0000 0.0000 0.00 0.00 816.5600 1,000.00 1,000.00
30 2025-05-24 n/a original 454.15 1 454.15 confirmed 454.15 n/a 454.15 payment made open 239.4000 0.0000 454.15 0.00 362.4100 1,000.00 785.25
61 2025-06-24 n/a original 454.15 2 454.15 confirmed 454.15 n/a 454.15 payment made open 247.3800 0.0000 362.41 91.74 0.0000 908.26 578.48
✓ 70 2025-07-03 n/a n/a 2 0.00 n/a 643.71 643.71 generated closed 65.2312 -264.5488 -264.55 908.26 0.0000 0.00 0.00
91 2025-07-24 n/a original 454.15 3 0.00 n/a n/a 0.00 no longer required closed 0.0000 0.0000 0.00 0.00 0.0000 0.00 0.00
122 2025-08-24 n/a original 454.11 4 0.00 n/a n/a 0.00 no longer required closed 0.0000 0.0000 0.00 0.00 0.0000 0.00 0.00

The settlement quotation is £643.71, which is the sum required to pay off all outstanding balances, including any interest accrued up to that day. As this is an early settlement, and the interest for the full schedule was charged up-front, an interest rebate of £264.55 has been calculated. The principal balance of £908.26, minus the interest rebate of £264.55, leaves a final settlement payment of £643.71 to pay. This would fully amortise the schedule, and the remaining two payments on days 91 and 122 are no longer required. In contrast to the actuarial-interest method, where you have to add up the unrequired payments and deduct the settlement figure to calculate the saved interest, in the add-on-interest method the interest rebate is explicitly calculated.

Is overcharged interest refunded?

As shown above, if a customer settles early and has overpaid interest, this is rebated as part of the settlement quotation. It would be termed a rebate rather than a refund, as the settlement quotation is generally a positive amount and so is a net flow from the customer to the lender.

The exception to this is if the customer has somehow managed to overpay, i.e. to pay an amount greater than the settlement figure. In this case, the lender would need to refund the customer the difference between the settlement figure and the amount paid. This is illustrated in the example below:

Show/hide code
let parameters6 = {
    parameters0 with
        Basic.EvaluationDate = Date(2025, 4, 29) // evaluate the schedule on day 5
        Basic.InterestConfig.Method = Interest.Method.AddOn // use the add-on interest method
        Advanced.TrimEnd = true // clip unrequired payments from the end of the schedule
}

let amortisation6 =
    amortise parameters6 (Map [ 5<OffsetDay>, [| ActualPayment.quickConfirmed 1050_00L<Cent> |] ]) // single overpayment made on day 5
Day Datestamp Advances Scheduled payment Window Payment due Actual payments Net effect Payment status Balance status Actuarial interest New interest Interest portion Principal portion Interest balance Principal balance Settlement figure
0 2025-04-24 1,000.00 n/a 0 0.00 n/a 0.00 none scheduled open 0.0000 0.0000 0.00 0.00 816.5600 1,000.00 1,000.00
★ 5 2025-04-29 n/a n/a 0 0.00 confirmed 1,050.00 1,050.00 extra payment refund due 39.9000 -776.6600 39.90 1,010.10 0.0000 -10.10 -10.10
30 2025-05-24 n/a original 454.15 1 0.00 n/a 0.00 no longer required refund due 0.0000 0.0000 0.00 0.00 0.0000 -10.10 -10.10
61 2025-06-24 n/a original 454.15 2 0.00 n/a 0.00 no longer required refund due 0.0000 0.0000 0.00 0.00 0.0000 -10.10 -10.10
91 2025-07-24 n/a original 454.15 3 0.00 n/a 0.00 no longer required refund due 0.0000 0.0000 0.00 0.00 0.0000 -10.10 -10.10
122 2025-08-24 n/a original 454.11 4 0.00 n/a 0.00 no longer required refund due 0.0000 0.0000 0.00 0.00 0.0000 -10.10 -10.10

Here, the customer has paid £1050.00 on day 5, which is greater than the settlement figure of £1039.90. The lender would need to refund the customer the difference of £10.10. This is a rare case, as the lender would normally expect to receive the settlement figure and not more than this.

Can customers make partial payments? Can the customer make a payment of any amount towards the amount owed?

Yes, this is possible, though it may increase the total interest accrued. The schedule will automatically calculate the balances, but if the schedule is not fully amortised, the customer will need to pay off the remaining balance at some point in the future.

What is the minimum partial payment a customer can make?

There is no minimum partial payment, but payment processors may have a minimum amount that they will accept.

How does refinancing work?

There are two types of refinancing:

Note: both of these options may be limited by regulatory requirements, particularly in relation to responsible lending. There may be limits on the number of times a loan can be refinanced, and the amount of interest that can be charged. This is outside the scope of this library.

Let's take a look at these two options in more detail.

For both of these scenarios, we will take the same example as above, where a customer has taken a loan of £1000 advanced on 24 April 2025, paid back over 4 months starting one month after the advance date. The loan has a daily interest rate of 0.798% and a cap of 0.8% per day as well as a cap of 100% of the principal amount. We'll use the add-on interest method, though the rescheduling/rollover functions work identically for both methods, just the interest amounts are different. The customer already paid the first two payments on time, but missed the remaining two payments. The customer has requested refinancing on day 152.

Show/hide code

let refinanceExampleParameters = {
    parameters0 with
        Basic.EvaluationDate = Date(2025, 9, 23) // evaluate the schedule on day 152
        Basic.InterestConfig.Method = Interest.Method.AddOn // use the add-on interest method
        Advanced.SettlementDay = SettlementDay.SettlementOnEvaluationDay // settlement quotation requested on day 152
}

let actualPayments =
    Map [
        30<OffsetDay>, [| ActualPayment.quickConfirmed 454_15L<Cent> |]
        61<OffsetDay>, [| ActualPayment.quickConfirmed 454_15L<Cent> |]
    ] // actual payments made on days 30 and 61

let refinanceExampleSchedule = amortise refinanceExampleParameters actualPayments

Here is the status of the schedule on day 152 prior to any refinancing, where a settlement quotation has been requested so the interest is capitalised:

Day Datestamp Advances Scheduled payment Window Payment due Actual payments Generated payment Net effect Payment status Balance status Actuarial interest New interest Interest portion Principal portion Interest balance Principal balance Settlement figure
0 2025-04-24 1,000.00 n/a 0 0.00 n/a n/a 0.00 none scheduled open 0.0000 0.0000 0.00 0.00 816.5600 1,000.00 1,000.00
30 2025-05-24 n/a original 454.15 1 454.15 confirmed 454.15 n/a 454.15 payment made open 239.4000 0.0000 454.15 0.00 362.4100 1,000.00 785.25
61 2025-06-24 n/a original 454.15 2 454.15 confirmed 454.15 n/a 454.15 payment made open 247.3800 0.0000 362.41 91.74 0.0000 908.26 578.48
91 2025-07-24 n/a original 454.15 3 454.15 n/a n/a 0.00 missed payment open 217.4374 0.0000 0.00 0.00 0.0000 908.26 795.91
122 2025-08-24 n/a original 454.11 4 454.11 n/a n/a 0.00 paid later in full open 224.6854 112.3428 0.00 0.00 112.3428 908.26 1,020.60
✓ 152 2025-09-23 n/a n/a 4 0.00 n/a 1,091.70 1,091.70 generated closed 71.0972 71.0972 183.44 908.26 0.0000 0.00 0.00

Rescheduling

Here, the customer has agreed to pay £50 per week from 1 October 2025.

Show/hide code
let rescheduleParameters: RescheduleParameters = {
    FeeSettlementRebate = Fee.SettlementRebate.Zero // no fees, so irrelevant
    PaymentSchedule =
        FixedSchedules [|
            {
                UnitPeriodConfig = Weekly(1, Date(2025, 10, 1)) // weekly payments starting on 1 October 2025
                PaymentCount = 100 // more than enough payments to cover the schedule (this will be automatically curtailed)
                PaymentValue = 50_00L<Cent> // £50 per week
                ScheduleType = ScheduleType.Rescheduled 152<OffsetDay> // indicate that rescheduling was requested on day 152
            }
        |]
    RateOnNegativeBalance = Interest.Rate.Zero // no negative balance, so irrelevant
    PromotionalInterestRates = [||] // no promotional rates
    SettlementDay = SettlementDay.NoSettlement //no settlement requested, just generate a statement
}

let rescheduleSchedules =
    reschedule refinanceExampleParameters rescheduleParameters actualPayments

The rescheduled amortisation is as follows:

Day Datestamp Advances Scheduled payment Window Payment due Actual payments Generated payment Net effect Payment status Balance status Actuarial interest New interest Interest portion Principal portion Interest balance Principal balance Settlement figure
0 2025-04-24 1,000.00 n/a 0 0.00 n/a n/a 0.00 none scheduled open 0.0000 0.0000 0.00 0.00 0.0000 1,000.00 1,000.00
30 2025-05-24 n/a original 454.15 1 454.15 confirmed 454.15 n/a 454.15 payment made open 239.4000 239.4000 239.40 214.75 0.0000 785.25 785.25
61 2025-06-24 n/a original 454.15 2 454.15 confirmed 454.15 n/a 454.15 payment made open 194.2551 194.2551 194.25 259.90 0.0000 525.35 525.35
91 2025-07-24 n/a original 454.15 3 454.15 n/a n/a 0.00 missed payment open 125.7688 125.7688 0.00 0.00 125.7688 525.35 651.11
122 2025-08-24 n/a original 454.11 4 454.11 n/a n/a 0.00 missed payment open 129.9611 129.9611 0.00 0.00 255.7299 525.35 781.07
★ 152 2025-09-23 n/a n/a 4 0.00 n/a n/a 0.00 information only open 125.7688 125.7688 0.00 0.00 381.4987 525.35 906.84
160 2025-10-01 n/a rescheduled 50.00 5 50.00 n/a n/a 50.00 not yet due open 33.5383 33.5383 50.00 0.00 365.0370 525.35 890.38
167 2025-10-08 n/a rescheduled 50.00 6 50.00 n/a n/a 50.00 not yet due open 29.3461 29.3461 50.00 0.00 344.3831 525.35 869.73
174 2025-10-15 n/a rescheduled 50.00 7 50.00 n/a n/a 50.00 not yet due open 29.3461 29.3461 50.00 0.00 323.7291 525.35 849.07
181 2025-10-22 n/a rescheduled 50.00 8 50.00 n/a n/a 50.00 not yet due open 29.3461 29.3461 50.00 0.00 303.0752 525.35 828.42
188 2025-10-29 n/a rescheduled 50.00 9 50.00 n/a n/a 50.00 not yet due open 29.3461 29.3461 50.00 0.00 282.4212 525.35 807.77
195 2025-11-05 n/a rescheduled 50.00 10 50.00 n/a n/a 50.00 not yet due open 29.3461 29.3461 50.00 0.00 261.7673 525.35 787.11
202 2025-11-12 n/a rescheduled 50.00 11 50.00 n/a n/a 50.00 not yet due open 4.5776 4.5776 50.00 0.00 216.3449 525.35 741.69
209 2025-11-19 n/a rescheduled 50.00 12 50.00 n/a n/a 50.00 not yet due open 0.0000 0.0000 50.00 0.00 166.3449 525.35 691.69
216 2025-11-26 n/a rescheduled 50.00 13 50.00 n/a n/a 50.00 not yet due open 0.0000 0.0000 50.00 0.00 116.3449 525.35 641.69
223 2025-12-03 n/a rescheduled 50.00 14 50.00 n/a n/a 50.00 not yet due open 0.0000 0.0000 50.00 0.00 66.3449 525.35 591.69
230 2025-12-10 n/a rescheduled 50.00 15 50.00 n/a n/a 50.00 not yet due open 0.0000 0.0000 50.00 0.00 16.3449 525.35 541.69
237 2025-12-17 n/a rescheduled 50.00 16 50.00 n/a n/a 50.00 not yet due open 0.0000 0.0000 16.34 33.66 0.0000 491.69 491.69
244 2025-12-24 n/a rescheduled 50.00 17 50.00 n/a n/a 50.00 not yet due open 0.0000 0.0000 0.00 50.00 0.0000 441.69 441.69
251 2025-12-31 n/a rescheduled 50.00 18 50.00 n/a n/a 50.00 not yet due open 0.0000 0.0000 0.00 50.00 0.0000 391.69 391.69
258 2026-01-07 n/a rescheduled 50.00 19 50.00 n/a n/a 50.00 not yet due open 0.0000 0.0000 0.00 50.00 0.0000 341.69 341.69
265 2026-01-14 n/a rescheduled 50.00 20 50.00 n/a n/a 50.00 not yet due open 0.0000 0.0000 0.00 50.00 0.0000 291.69 291.69
272 2026-01-21 n/a rescheduled 50.00 21 50.00 n/a n/a 50.00 not yet due open 0.0000 0.0000 0.00 50.00 0.0000 241.69 241.69
279 2026-01-28 n/a rescheduled 50.00 22 50.00 n/a n/a 50.00 not yet due open 0.0000 0.0000 0.00 50.00 0.0000 191.69 191.69
286 2026-02-04 n/a rescheduled 50.00 23 50.00 n/a n/a 50.00 not yet due open 0.0000 0.0000 0.00 50.00 0.0000 141.69 141.69
293 2026-02-11 n/a rescheduled 50.00 24 50.00 n/a n/a 50.00 not yet due open 0.0000 0.0000 0.00 50.00 0.0000 91.69 91.69
300 2026-02-18 n/a rescheduled 50.00 25 50.00 n/a n/a 50.00 not yet due open 0.0000 0.0000 0.00 50.00 0.0000 41.69 41.69
307 2026-02-25 n/a rescheduled 50.00 26 41.69 n/a n/a 41.69 not yet due closed 0.0000 0.0000 0.00 41.69 0.0000 0.00 0.00

There are some interesting points to note:

  • The first rescheduled payments, from day 160 to day 237, are paying off the interest balance, and only then does the principal balance start to be paid off.
  • On day 202, the new interest drops significantly and falls to zero on all subsequent days. This is because the 100% interest cap has been reached.

Rollover

Here, the customer has agreed to roll over the loan to a new 8-month loan, starting on 1 October 2025.

Show/hide code
let originalFinalPaymentDay = // get the final payment day from the original schedule
    refinanceExampleSchedule.AmortisationSchedule.ScheduleItems
    |> Map.filter (fun _ si -> ScheduledPayment.isSome si.ScheduledPayment)
    |> Map.maxKeyValue
    |> fst

let rolloverParameters: RolloverParameters = {
    OriginalFinalPaymentDay = originalFinalPaymentDay
    PaymentSchedule =
        AutoGenerateSchedule {
            UnitPeriodConfig = Monthly(1, 2025, 10, 1) // monthly payments starting on 1 October 2025
            ScheduleLength = PaymentCount 8 // 8 payments
        }
    InterestConfig = refinanceExampleParameters.Basic.InterestConfig // use the same interest config as the original schedule
    PaymentConfig = refinanceExampleParameters.Basic.PaymentConfig // use the same payment config as the original schedule
    FeeHandling = Fee.FeeHandling.CarryOverAsIs // no fees, so irrelevant
}

let rolloverSchedules =
    rollOver refinanceExampleParameters rolloverParameters actualPayments

The old loan would be closed as per the settlement quote above. The new rolled-over loan amortisation schedule is as follows:

Day Datestamp Advances Scheduled payment Window Payment due Actual payments Generated payment Net effect Payment status Balance status Actuarial interest New interest Interest portion Principal portion Interest balance Principal balance Settlement figure
★ 0 2025-09-23 1,091.70 n/a 0 0.00 n/a n/a 0.00 information only open 0.0000 0.0000 0.00 0.00 1,091.7000 1,091.70 1,091.70
8 2025-10-01 n/a original 272.93 1 272.93 n/a n/a 272.93 not yet due open 69.6941 0.0000 272.93 0.00 818.7700 1,091.70 1,161.39
39 2025-11-01 n/a original 272.93 2 272.93 n/a n/a 272.93 not yet due open 270.0647 0.0000 272.93 0.00 545.8400 1,091.70 1,431.45
69 2025-12-01 n/a original 272.93 3 272.93 n/a n/a 272.93 not yet due open 261.3530 0.0000 272.93 0.00 272.9100 1,091.70 1,364.61
100 2026-01-01 n/a original 272.93 4 272.93 n/a n/a 272.93 not yet due open 270.0647 0.0000 272.91 0.02 0.0000 1,091.68 1,091.68
131 2026-02-01 n/a original 272.93 5 272.93 n/a n/a 272.93 not yet due open 220.5234 0.0000 0.00 272.93 0.0000 818.75 818.75
159 2026-03-01 n/a original 272.93 6 272.93 n/a n/a 272.93 not yet due open 0.0000 0.0000 0.00 272.93 0.0000 545.82 545.82
190 2026-04-01 n/a original 272.93 7 272.93 n/a n/a 272.93 not yet due open 0.0000 0.0000 0.00 272.93 0.0000 272.89 272.89
220 2026-05-01 n/a original 272.89 8 272.89 n/a n/a 272.89 not yet due closed 0.0000 0.0000 0.00 272.89 0.0000 0.00 0.00

There are some interesting points to note:

  • The settlement figure is £1091.70, which is greater than the original loan amount due to the capitalised interest.
  • By comparison, the settlement figure on day 152 when rescheduling (rather than rolling over) is only £908.64, because the interest is not capitalised.
  • On day 131 of the new loan, you can see that the actuarial interest hits the 100% total cap, and interest is no longer accrued from that point on.

What happens to the payment amounts?

Payment amounts can be:

What happens to the loan term?

Depending on the payment schedule, the loan term will either be amortised over a set number of payments, or the number of payments will be determined by how long it takes to amortise the schedule based on the payment amount.

If forbearance is offered, how is this calculated?

The schedule can be partially or fully paid off by using write-off payments.

Let's take our actuarial-interest loan, where the customer has already made the first two payments on time.

Single-payment write-off

Show/hide code
let parameters7 = {
    parameters0 with
        Basic.EvaluationDate = Date(2025, 7, 3) // evaluate the schedule on day 70
}

let amortisation7 =
    amortise
        parameters7
        (Map [
            30<OffsetDay>, [| ActualPayment.quickConfirmed 417_72L<Cent> |]
            61<OffsetDay>, [| ActualPayment.quickConfirmed 417_72L<Cent> |]
            91<OffsetDay>, [| ActualPayment.quickWriteOff 417_72L<Cent> |]
        ]) // actual payments made on days 30 and 61, and a single-payment write-off on day 91
Day Datestamp Advances Scheduled payment Window Payment due Actual payments Net effect Payment status Balance status Actuarial interest New interest Interest portion Principal portion Interest balance Principal balance Settlement figure
0 2025-04-24 1,000.00 n/a 0 0.00 n/a 0.00 none scheduled open 0.0000 0.0000 0.00 0.00 0.0000 1,000.00 1,000.00
30 2025-05-24 n/a original 417.72 1 417.72 confirmed 417.72 417.72 payment made open 239.4000 239.4000 239.40 178.32 0.0000 821.68 821.68
61 2025-06-24 n/a original 417.72 2 417.72 confirmed 417.72 417.72 payment made open 203.2672 203.2672 203.26 214.46 0.0000 607.22 607.22
★ 70 2025-07-03 n/a n/a 2 0.00 n/a 0.00 information only open 43.6105 43.6105 0.00 0.00 43.6105 607.22 650.83
91 2025-07-24 n/a original 417.72 3 417.72 write-off 417.72 417.72 not yet due open 101.7579 101.7579 145.36 272.36 0.0000 334.86 334.86
122 2025-08-24 n/a original 417.69 4 417.69 n/a 417.69 not yet due closed 82.8377 82.8377 82.83 334.86 0.0000 0.00 0.00

You can see that the single-payment write-off has no effect on the remainder of the schedule, and the remaining payment is still due on day 122.

Full write-off

Show/hide code
// first, run the amortisation with the existing actual payments to get the settlement figure
let parameters8 = {
    parameters0 with
        Basic.EvaluationDate = Date(2025, 7, 24) // evaluate the schedule on day 91
        Advanced.SettlementDay = SettlementDay.SettlementOnEvaluationDay // settlement quotation requested
}

let amortisation8 =
    amortise
        parameters8
        (Map [
            30<OffsetDay>, [| ActualPayment.quickConfirmed 417_72L<Cent> |]
            61<OffsetDay>, [| ActualPayment.quickConfirmed 417_72L<Cent> |]
        ]) // actual payments made on days 30 and 61, and a single-payment write-off on day 91
// get the generated settlement figure
let settlementFigure =
    amortisation8.AmortisationSchedule.FinalStats.SettlementFigure
// use the settlement figure as the full write-off amount
let fullWriteOffAmount =
    settlementFigure |> ValueOption.map snd |> ValueOption.defaultValue 0L<Cent>
// run the amortisation again with the full write-off payment
let amortisation8' =
    amortise
        {
            parameters8 with
                Basic.EvaluationDate = OffsetDay.toDate parameters8.Basic.StartDate 92<OffsetDay>
                Advanced.SettlementDay = SettlementDay.NoSettlement
        }
        (Map [
            30<OffsetDay>, [| ActualPayment.quickConfirmed 417_72L<Cent> |]
            61<OffsetDay>, [| ActualPayment.quickConfirmed 417_72L<Cent> |]
            91<OffsetDay>, [| ActualPayment.quickWriteOff fullWriteOffAmount |]
        ]) // actual payments made on days 30 and 61, and a full write-off on day 91
Day Datestamp Advances Scheduled payment Window Payment due Actual payments Generated payment Net effect Payment status Balance status Actuarial interest New interest Interest portion Principal portion Interest balance Principal balance Settlement figure
0 2025-04-24 1,000.00 n/a 0 0.00 n/a n/a 0.00 none scheduled open 0.0000 0.0000 0.00 0.00 0.0000 1,000.00 1,000.00
30 2025-05-24 n/a original 417.72 1 417.72 confirmed 417.72 n/a 417.72 payment made open 239.4000 239.4000 239.40 178.32 0.0000 821.68 821.68
61 2025-06-24 n/a original 417.72 2 417.72 confirmed 417.72 n/a 417.72 payment made open 203.2672 203.2672 203.26 214.46 0.0000 607.22 607.22
91 2025-07-24 n/a original 417.72 3 417.72 write-off 752.58 n/a 752.58 overpayment closed 145.3685 145.3685 145.36 607.22 0.0000 0.00 0.00
★ 92 2025-07-25 n/a n/a 3 0.00 n/a n/a 0.00 information only closed 0.0000 0.0000 0.00 0.00 0.0000 0.00 0.00
122 2025-08-24 n/a original 417.69 4 0.00 n/a n/a 0.00 no longer required closed 0.0000 0.0000 0.00 0.00 0.0000 0.00 0.00

A settlement payment of £752.58 was determined on day 91, and this is used as the write-off amount. This amount is less than the remaining two payments (£417.72 + £417.69 = £835.41) as this is effectively an early settlement and so less interest is accrued. The remaining payment on day 122 is no longer required as the schedule is fully amortised.

Can interest be frozen for a period of time?

Yes, the library supports promotional interest rates, essentially ranges of dates during which a different interest rate is applied. To freeze interest, these can be used with the interest rate set to zero. This is illustrated in the example below:

Show/hide code
let parameters9 = {
    parameters0 with
        Advanced.InterestConfig.PromotionalRates = [|
            { // promotional rate to freeze interest for a month
                DateRange = {
                    DateRangeStart = Date(2025, 6, 25)
                    DateRangeEnd = Date(2025, 7, 24)
                }
                Rate = Interest.Rate.Zero // zero interest rate
            }
        |]
}

let amortisation9 = amortise parameters9 Map.empty // no actual payments made
Day Datestamp Advances Scheduled payment Window Payment due Actual payments Net effect Payment status Balance status Actuarial interest New interest Interest portion Principal portion Interest balance Principal balance Settlement figure
★ 0 2025-04-24 1,000.00 n/a 0 0.00 n/a 0.00 information only open 0.0000 0.0000 0.00 0.00 0.0000 1,000.00 1,000.00
30 2025-05-24 n/a original 417.72 1 417.72 n/a 417.72 not yet due open 239.4000 239.4000 239.40 178.32 0.0000 821.68 821.68
61 2025-06-24 n/a original 417.72 2 417.72 n/a 417.72 not yet due open 203.2672 203.2672 203.26 214.46 0.0000 607.22 607.22
91 2025-07-24 n/a original 417.72 3 417.72 n/a 417.72 not yet due open 0.0000 0.0000 0.00 417.72 0.0000 189.50 189.50
122 2025-08-24 n/a original 417.69 4 236.37 n/a 236.37 not yet due closed 46.8785 46.8785 46.87 189.50 0.0000 0.00 0.00

You can see that the interest accrued over the month up to the payment on day 91 is zero. The scheduled payments are lowered to account for this as we've set this up from the start of the loan.

It would be equally possible to set this up after a schedule has started, but depending on the actual promotional rates applied, this might end up requiring a rebate of existing interest paid or even a refund to the customer if it meant that existing payments exceeded the revised settlement figure. The library would automatically calculate this, but it would be up to the lender to decide how to handle it.

When does accrued interest start?

Accrued interest starts from the first day of the schedule, i.e. the advance date.

The parameters used in these examples have a 3-day initial grace period, meaning that if the customer pays back the principal amount within 3 days of the advance date, no interest is charged. If they wanted to settle the schedule after this date, interest would be charged from the advance date.

If there were no initial grace period, a customer could pay back the principal amount on the advance date and no interest would be charged. If they wanted to settle the schedule after this date, interest would be charged from the advance date. So if they wanted to settle the schedule on day 1, one day's interest would be charged.

Do we allow up until 11:59pm for payment to be made on due date of the scheduled repayment?

The library does not have a concept of time, so all dates are treated as whole days. It is up to the lender to decide how to handle this, e.g. deciding on what day to record any payment as having been made.

The parameters used in these examples have a 3-day payment timeout, allowing us to mark payments as pending for up to 3 days after the scheduled payment date. This means that if a payment is made on day 30, it will be marked as pending until day 33. If the payment is not made by then, it will be marked as missed.

Can a customer delay one payment and keep all subsequent payments the same?

This kind of scenario could be handled in a number of ways:

Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
namespace FSharp.Finance
namespace FSharp.Finance.Personal
module Amortisation from FSharp.Finance.Personal
<summary> calculating the principal balance over time, taking into account the effects of charges, interest and fee </summary>
module Calculation from FSharp.Finance.Personal
<summary> convenience functions and options to help with calculations </summary>
module DateDay from FSharp.Finance.Personal
<summary> a .NET Framework polyfill equivalent to the DateOnly structure in .NET Core </summary>
module Scheduling from FSharp.Finance.Personal
<summary> functions for generating a regular payment schedule, with payment amounts, interest and APR </summary>
module UnitPeriod from FSharp.Finance.Personal
<summary> an unambiguous way to represent regular date intervals and generate schedules based on them note: unit-period definitions are based on US federal legislation but the definitions are universally applicable </summary>
val parameters0: Parameters
type Parameters = { Basic: BasicParameters Advanced: AdvancedParameters }
<summary> basic schedule generation parameters and advanced parameters for amortisation </summary>
Multiple items
[<Struct>] type Date = new: year: int * month: int * day: int -> Date val Year: int val Month: int val Day: int member AddDays: i: int -> Date member AddMonths: i: int -> Date member AddYears: i: int -> Date member ToDateTime: unit -> DateTime static member (-) : d1: Date * d2: Date -> TimeSpan static member DaysInMonth: year: int * month: int -> int ...
<summary> the date at the customer's location - ensure any time-zone conversion is performed before using this - as all calculations are date-only with no time component, summer time or other such time artefacts </summary>

--------------------
Date ()
new: year: int * month: int * day: int -> Date
Multiple items
module Cent from FSharp.Finance.Personal.Calculation
<summary> utility functions for base currency unit values </summary>

--------------------
[<Measure>] type Cent
<summary> the base unit of a currency (cent, penny, øre etc.) </summary>
Multiple items
module ScheduleConfig from FSharp.Finance.Personal.Scheduling
<summary> whether a payment plan is generated according to a regular schedule or is an irregular array of payments </summary>

--------------------
[<Struct>] type ScheduleConfig = | AutoGenerateSchedule of AutoGenerateSchedule: AutoGenerateSchedule | FixedSchedules of FixedSchedules: FixedSchedule array | CustomSchedule of CustomSchedule: PaymentMap
<summary> whether a payment plan is generated according to a regular schedule or is an irregular array of payments </summary>
Multiple items
union case ScheduleConfig.AutoGenerateSchedule: AutoGenerateSchedule: AutoGenerateSchedule -> ScheduleConfig
<summary> a schedule based on a unit-period config with a specific number of payments with an auto-calculated amount, optionally limited to a maximum duration </summary>

--------------------
[<Struct>] type AutoGenerateSchedule = { UnitPeriodConfig: Config ScheduleLength: ScheduleLength }
<summary> a regular schedule based on a unit-period config with a specific number of payments with an auto-calculated amount </summary>
union case Config.Monthly: MonthMultiple: int * Year: int * Month: int * Day: int -> Config
<summary> (multi-)monthly: every n months starting on the date given by year, month and day, which tracks month-end (see config) </summary>
[<Struct>] type ScheduleLength = | PaymentCount of Payments: int | MaxDuration of StartDate: Date * Days: int<DurationDay> member Html: string with get
<summary> defines the length of a payment schedule, either by the number of payments or by the maximum duration </summary>
union case ScheduleLength.PaymentCount: Payments: int -> ScheduleLength
Multiple items
module LevelPaymentOption from FSharp.Finance.Personal.Scheduling
<summary> when calculating the level payments, whether the final payment should be lower or higher than the level payment </summary>

--------------------
[<Struct>] type LevelPaymentOption = | LowerFinalPayment | SimilarFinalPayment | HigherFinalPayment member Html: string with get
<summary> when calculating the level payments, whether the final payment should be lower or higher than the level payment </summary>
union case LevelPaymentOption.LowerFinalPayment: LevelPaymentOption
<summary> the final payment must be lower than the level payment </summary>
Multiple items
module Rounding from FSharp.Finance.Personal.Calculation
<summary> the type of rounding, specifying midpoint-rounding where necessary </summary>

--------------------
[<Struct>] type Rounding = | NoRounding | RoundUp | RoundDown | RoundWith of MidpointRounding member Html: string with get
<summary> the type of rounding, specifying midpoint-rounding where necessary </summary>
union case Rounding.RoundUp: Rounding
<summary> round up to the specified precision (= ceiling) </summary>
union case ValueOption.ValueNone: ValueOption<'T>
module Interest from FSharp.Finance.Personal
<summary> methods for calculating interest and unambiguously expressing interest rates, as well as enforcing regulatory caps on interest chargeable </summary>
[<Struct>] type Method = | Actuarial | AddOn member Html: string with get
<summary> the method used to calculate the interest </summary>
union case Interest.Method.Actuarial: Interest.Method
<summary> actuarial interest method, where interest is based on the principal balance and the number of days outstanding </summary>
Multiple items
module Rate from FSharp.Finance.Personal.Interest

--------------------
[<Struct>] type Rate = | Zero | Annual of Percent | Daily of Percent member Html: string with get
<summary> the interest rate expressed as either an annual or a daily rate </summary>
union case Interest.Rate.Daily: Percent -> Interest.Rate
<summary> the daily interest rate, or the annual interest rate divided by 365 </summary>
Multiple items
union case Percent.Percent: decimal -> Percent

--------------------
module Percent from FSharp.Finance.Personal.Calculation
<summary> utility functions for percent values </summary>

--------------------
[<Struct>] type Percent = | Percent of decimal member Html: string with get
<summary> a percentage, e.g. 42%, as opposed to its decimal representation 0.42m </summary>
Multiple items
module Amount from FSharp.Finance.Personal.Calculation
<summary> an amount specified either as a simple amount or as a percentage of another amount, optionally restricted to lower and/or upper limits </summary>

--------------------
[<Struct>] type Amount = | Percentage of Percent * Restriction | Simple of int64<Cent> | Unlimited member Html: string with get
<summary> an amount specified either as a simple amount or as a percentage of another amount, optionally restricted to lower and/or upper limits </summary>
union case Amount.Percentage: Percent * Restriction -> Amount
<summary> a percentage of the principal, optionally restricted </summary>
Multiple items
module Restriction from FSharp.Finance.Personal.Calculation
<summary> the type of restriction placed on a possible value </summary>

--------------------
[<Struct>] type Restriction = | NoLimit | LowerLimit of int64<Cent> | UpperLimit of int64<Cent> | WithinRange of MinValue: int64<Cent> * MaxValue: int64<Cent> member Html: string with get
<summary> the type of restriction placed on a possible value </summary>
union case Restriction.NoLimit: Restriction
<summary> does not constrain values at all </summary>
union case Rounding.RoundDown: Rounding
<summary> round down to the specified precision (= floor) </summary>
module Apr from FSharp.Finance.Personal
<summary> calculating the APR according to various country-specific regulations </summary>
[<Struct>] type CalculationMethod = | EuropeanUnion of EuPrecision: int | UnitedKingdom of UkPrecision: int | UsActuarial of UsPrecision: int | UnitedStatesRule member Html: string with get
<summary> the calculation method used to determine the APR </summary>
union case Apr.CalculationMethod.UnitedKingdom: UkPrecision: int -> Apr.CalculationMethod
<summary> calculates the APR according to UK FCA rules to the stated decimal precision (note that this is two places more than the percent precision) </summary>
[<Struct>] type ScheduledPaymentOption = | AsScheduled | AddChargesAndInterest member Html: string with get
<summary> whether to stick to scheduled payment amounts or add charges and interest to them </summary>
union case ScheduledPaymentOption.AsScheduled: ScheduledPaymentOption
<summary> keep to the scheduled payment amounts even if this results in an open balance </summary>
union case MinimumPayment.DeferOrWriteOff: int64<Cent> -> MinimumPayment
<summary> add the payment due to the next payment or close the balance if the final payment </summary>
[<Measure>] type DurationDay
<summary> a duration of a number of days </summary>
union case Option.None: Option<'T>
union case Interest.Rate.Zero: Interest.Rate
<summary> a zero rate </summary>
[<Struct>] type SettlementDay = | SettlementOnEvaluationDay | NoSettlement member Html: string with get
<summary> the intended day on which to quote a settlement </summary>
union case SettlementDay.NoSettlement: SettlementDay
<summary> no settlement figure is required </summary>
val amortisation0: GenerationResult
val amortise: p: Parameters -> actualPayments: Map<int<OffsetDay>,ActualPayment array> -> GenerationResult
<summary> generates an amortisation schedule and final statistics </summary>
Multiple items
module Map from FSharp.Finance.Personal.Calculation
<summary> functions for working with maps </summary>

--------------------
module Map from Microsoft.FSharp.Collections

--------------------
type Map<'Key,'Value (requires comparison)> = interface IReadOnlyDictionary<'Key,'Value> interface IReadOnlyCollection<KeyValuePair<'Key,'Value>> interface IEnumerable interface IStructuralEquatable interface IComparable interface IEnumerable<KeyValuePair<'Key,'Value>> interface ICollection<KeyValuePair<'Key,'Value>> interface IDictionary<'Key,'Value> new: elements: ('Key * 'Value) seq -> Map<'Key,'Value> member Add: key: 'Key * value: 'Value -> Map<'Key,'Value> ...

--------------------
new: elements: ('Key * 'Value) seq -> Map<'Key,'Value>
val empty<'Key,'T (requires comparison)> : Map<'Key,'T> (requires comparison)
Multiple items
module Schedule from FSharp.Finance.Personal.Amortisation
<summary> a schedule showing the amortisation, itemising the effects of payments and calculating balances for each item, and producing some final statistics resulting from the calculations </summary>

--------------------
[<Struct>] type Schedule = { ScheduleItems: Map<int<OffsetDay>,ScheduleItem> FinalStats: FinalStats }
<summary> a schedule showing the amortisation, itemising the effects of payments and calculating balances for each item, and producing some final statistics resulting from the calculations </summary>
val toHtmlTable: p: Parameters -> schedule: Schedule -> string
<summary> formats the schedule items as an HTML table (stats can be rendered separately) </summary>
val html: string
val parameters1: Parameters
val amortisation1: GenerationResult
val parameters2: Parameters
union case Interest.Method.AddOn: Interest.Method
<summary> add-on interest method, where the interest accrued over the loan is added to the initial balance and the interest is paid off before the principal balance </summary>
val amortisation2: GenerationResult
val parameters3: Parameters
val amortisation3: GenerationResult
val parameters4: Parameters
union case SettlementDay.SettlementOnEvaluationDay: SettlementDay
<summary> quote a settlement figure on the evaluation day </summary>
val amortisation4: GenerationResult
Multiple items
module OffsetDay from FSharp.Finance.Personal.DateDay
<summary> functions for converting offset days to and from dates </summary>

--------------------
[<Measure>] type OffsetDay
<summary> the offset of a date from the start date, in days </summary>
Multiple items
module ActualPayment from FSharp.Finance.Personal.Scheduling
<summary> an actual payment made by the customer, optionally including metadata such as bank references etc. </summary>

--------------------
type ActualPayment = { ActualPaymentStatus: ActualPaymentStatus Metadata: Map<string,obj> } member Html: string with get
<summary> an actual payment made by the customer, optionally including metadata such as bank references etc. </summary>
val quickConfirmed: amount: int64<Cent> -> ActualPayment
<summary> a quick convenient method to create a confirmed actual payment </summary>
val parameters5: Parameters
val amortisation5: GenerationResult
val parameters6: Parameters
val amortisation6: GenerationResult
val refinanceExampleParameters: Parameters
val actualPayments: Map<int<OffsetDay>,ActualPayment array>
val refinanceExampleSchedule: GenerationResult
module Refinancing from FSharp.Finance.Personal
<summary> functions for refinancing payments after an original schedule failed to amortise </summary>
val rescheduleParameters: RescheduleParameters
Multiple items
module RescheduleParameters from FSharp.Finance.Personal.Refinancing
<summary> the parameters used for setting up additional items for an existing schedule or new items for a new schedule </summary>

--------------------
type RescheduleParameters = { FeeSettlementRebate: SettlementRebate PaymentSchedule: ScheduleConfig RateOnNegativeBalance: Rate PromotionalInterestRates: PromotionalRate array SettlementDay: SettlementDay }
<summary> the parameters used for setting up additional items for an existing schedule or new items for a new schedule </summary>
module Fee from FSharp.Finance.Personal
<summary> a product fee &gt; NOTE: differences between fee and charge: &gt; - a fee is an up-front amount paid under agreed terms for receiving an advance &gt; - a fee is added to the principal balance and therefore accrues interest </summary>
[<Struct>] type SettlementRebate = | Zero | ProRata | ProRataRescheduled of OriginalFinalPaymentDay: int<OffsetDay> | Balance member Html: string with get
<summary> how the fee is treated in the event of an early settlement </summary>
union case Fee.SettlementRebate.Zero: Fee.SettlementRebate
<summary> fee is due in full with no discount or rebate </summary>
union case ScheduleConfig.FixedSchedules: FixedSchedules: FixedSchedule array -> ScheduleConfig
<summary> a schedule based on one or more unit-period configs each with a specific number of payments of a specified amount and type </summary>
union case Config.Weekly: WeekMultiple: int * WeekStartDate: Date -> Config
<summary> (multi-)weekly: every n weeks starting on the given date </summary>
[<Struct>] type ScheduleType = | Original | Rescheduled of RescheduleDay: int<OffsetDay> member Html: string with get
<summary> the type of the schedule; for scheduled payments, this affects how any payment due is calculated </summary>
union case ScheduleType.Rescheduled: RescheduleDay: int<OffsetDay> -> ScheduleType
<summary> a new schedule created after the original schedule, indicating the day it was created </summary>
val rescheduleSchedules: {| NewSchedules: GenerationResult; OldSchedules: GenerationResult |}
val reschedule: p: Parameters -> rp: RescheduleParameters -> actualPayments: Map<int<OffsetDay>,ActualPayment array> -> {| NewSchedules: GenerationResult; OldSchedules: GenerationResult |}
<summary> take an existing schedule and reschedule the remaining payments e.g. to allow the customer more time to pay </summary>
anonymous record field NewSchedules: GenerationResult
GenerationResult.AmortisationSchedule: Schedule
val originalFinalPaymentDay: int<OffsetDay>
Schedule.ScheduleItems: Map<int<OffsetDay>,ScheduleItem>
<summary> a list of amortisation items, showing the events and calculations for a particular offset day </summary>
val filter: predicate: ('Key -> 'T -> bool) -> table: Map<'Key,'T> -> Map<'Key,'T> (requires comparison)
val si: ScheduleItem
Multiple items
module ScheduledPayment from FSharp.Finance.Personal.Scheduling

--------------------
type ScheduledPayment = { Original: int64<Cent> voption Rescheduled: RescheduledPayment voption PreviousRescheduled: RescheduledPayment array Adjustment: int64<Cent> Metadata: Map<string,obj> } member Html: string with get
<summary> any original or rescheduled payment, affecting how any payment due is calculated </summary>
val isSome: sp: ScheduledPayment -> bool
<summary> whether the payment has either an original or a rescheduled value </summary>
ScheduleItem.ScheduledPayment: ScheduledPayment
<summary> any payment scheduled on the current day </summary>
val maxKeyValue: table: Map<'Key,'T> -> 'Key * 'T (requires comparison)
val fst: tuple: ('T1 * 'T2) -> 'T1
val rolloverParameters: RolloverParameters
Multiple items
module RolloverParameters from FSharp.Finance.Personal.Refinancing
<summary> parameters for creating a rolled-over schedule </summary>

--------------------
type RolloverParameters = { OriginalFinalPaymentDay: int<OffsetDay> PaymentSchedule: ScheduleConfig InterestConfig: BasicConfig PaymentConfig: BasicConfig FeeHandling: FeeHandling }
<summary> parameters for creating a rolled-over schedule </summary>
Parameters.Basic: BasicParameters
<summary> the basic schedule generation parameters </summary>
BasicParameters.InterestConfig: Interest.BasicConfig
<summary> options relating to interest </summary>
BasicParameters.PaymentConfig: Payment.BasicConfig
<summary> options relating to scheduled payments </summary>
[<Struct>] type FeeHandling = | CapitaliseAsPrincipal | CarryOverAsIs | WriteOffFeeBalance
<summary> how to handle any fee when rescheduling or rolling over </summary>
union case Fee.FeeHandling.CarryOverAsIs: Fee.FeeHandling
<summary> carry any outstanding fee balance over as an initial fee balance, maintaining the original final payment day if pro-rated </summary>
val rolloverSchedules: {| NewSchedules: GenerationResult; OldSchedules: GenerationResult |}
val rollOver: p: Parameters -> rp: RolloverParameters -> actualPayments: Map<int<OffsetDay>,ActualPayment array> -> {| NewSchedules: GenerationResult; OldSchedules: GenerationResult |}
<summary> take an existing schedule and settle it, then use the result to create a new schedule to pay it off under different terms </summary>
val parameters7: Parameters
val amortisation7: GenerationResult
val quickWriteOff: amount: int64<Cent> -> ActualPayment
<summary> a quick convenient method to create a written off actual payment </summary>
val parameters8: Parameters
val amortisation8: GenerationResult
val settlementFigure: (int<OffsetDay> * int64<Cent>) voption
Schedule.FinalStats: FinalStats
<summary> final stats resulting from the calculations </summary>
FinalStats.SettlementFigure: (int<OffsetDay> * int64<Cent>) voption
<summary> the generated settlement figure from the schedule </summary>
val fullWriteOffAmount: int64<Cent>
Multiple items
module ValueOption from Microsoft.FSharp.Core

--------------------
[<Struct>] type ValueOption<'T> = | ValueNone | ValueSome of 'T static member Some: value: 'T -> 'T voption static member op_Implicit: value: 'T -> 'T voption member IsNone: bool with get member IsSome: bool with get member Value: 'T with get static member None: 'T voption with get
val map: mapping: ('T -> 'U) -> voption: 'T voption -> 'U voption
val snd: tuple: ('T1 * 'T2) -> 'T2
val defaultValue: value: 'T -> voption: 'T voption -> 'T
val amortisation8': GenerationResult
val toDate: startDate: Date -> offsetDay: int<OffsetDay> -> Date
<summary> convert an offset day to an offset date based on a given start date </summary>
BasicParameters.StartDate: Date
<summary> the start date of the schedule, typically the day on which the principal is advanced </summary>
val parameters9: Parameters
[<Struct>] type DateRange = { DateRangeStart: Date DateRangeEnd: Date } member Html: string with get
<summary> a holiday, i.e. a period when no interest and/or charges are accrued </summary>
val amortisation9: GenerationResult

Type something to start searching.