Header menu logo FSharp.Finance.Personal

Add-On-Interest Calculations

Definition

Add-on interest is a method of calculating interest where the total interest accrued over the entire schedule is added to the beginning of the schedule, as an initial interest balance. Given that payments are applied in the order charges -> interest -> fees -> principal, this means that the interest balance is reduced before the principal balance, and therefore the principal balance remains higher for longer.

Relevant Code

The Scheduling module contains the functions that create the initial schedule. The initial schedule is a simple schedule that allows us to calculate the interest accrued over the schedule as well as the level and final payments.

Let's start by defining the parameters. Let's define a loan of £1000 advanced on 22 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. Interest is calculated using the add-on method.


Show/hide parameters
let parameters = {
    EvaluationDate = Date(2025, 4, 22)
    StartDate = Date(2025, 4, 22)
    Principal = 1000_00L<Cent>
    ScheduleConfig = AutoGenerateSchedule {
        UnitPeriodConfig = Monthly(1, 2025, 5, 22)
        ScheduleLength = PaymentCount 4
    }
    PaymentConfig = {
        LevelPaymentOption = LowerFinalPayment
        ScheduledPaymentOption = AsScheduled
        Rounding = RoundUp
        Minimum = DeferOrWriteOff 50L<Cent>
        Timeout = 3<DurationDay>
    }
    FeeConfig = None
    ChargeConfig = None
    InterestConfig = {
        Method = Interest.Method.AddOn
        StandardRate = Interest.Rate.Daily (Percent 0.798m)
        Cap = {
            TotalAmount = Amount.Percentage (Percent 100m, Restriction.NoLimit)
            DailyAmount = Amount.Percentage (Percent 0.8m, Restriction.NoLimit)
        }
        InitialGracePeriod = 3<DurationDay>
        PromotionalRates = [||]
        RateOnNegativeBalance = Interest.Rate.Zero
        Rounding = RoundDown
        AprMethod = Apr.CalculationMethod.UnitedKingdom 3
    }
}

Then we call the Scheduling.calculate function to generate the schedule:

let schedule = Scheduling.calculate parameters
Day Scheduled payment Simple interest Interest portion Principal portion Interest balance Principal balance Total simple interest Total interest Total principal
0 0.00 0.0000 0.00 0.00 816.56 1,000.00 0.0000 0.00 0.00
30 454.15 239.4000 454.15 0.00 362.41 1,000.00 239.4000 454.15 0.00
61 454.15 247.3800 362.41 91.74 0.00 908.26 486.7800 816.56 91.74
91 454.15 217.4374 0.00 454.15 0.00 454.11 704.2174 816.56 545.89
122 454.11 112.3377 0.00 454.11 0.00 0.00 816.5552 816.56 1,000.00

The schedule has calculated an initial interest balance of £816.56. We can see that the interest balance is paid off before the principal, meaning that the full principal remains outstanding for two months. Given that interest is accrued on the principal balance only (no interest on interest), maintaining a higher principal balance for longer means that the interest accrued is higher than it would be if the principal was paid off first.


Simple-interest comparison (click to expand) To illustrate this, we can compare the add-on-interest schedule with a simple-interest schedule:
let simpleInterestSchedule = Scheduling.calculate { parameters with InterestConfig.Method = Interest.Method.Simple }
Day Scheduled payment Simple interest Interest portion Principal portion Interest balance Principal balance Total simple interest Total interest Total principal
0 0.00 0.0000 0.00 0.00 0.00 1,000.00 0.0000 0.00 0.00
30 417.72 239.4000 239.40 178.32 0.00 821.68 239.4000 239.40 178.32
61 417.72 203.2672 203.26 214.46 0.00 607.22 442.6672 442.66 392.78
91 417.72 145.3685 145.36 272.36 0.00 334.86 588.0357 588.02 665.14
122 417.69 82.8377 82.83 334.86 0.00 0.00 670.8733 670.85 1,000.00

Here, as there is no initial interest balance, the principal starts to be paid off immediately, and the total interest accrued is therefore lower.

Calculation Details

Scheduling.calculate is the function that generates the schedule. Here is a summary of the calculation steps:

  1. Generate payment days: generate the payment days based on the unit-period (e.g. monthly) and the first payment date
  2. Estimate total interest: estimate the total interest accruing over the entire schedule
  3. Solve for payment values: use the bisection method to determine the level payments required
  4. Iterate to maximise interest: for the add-on interest method, iterate until the initial interest matches the total interest
  5. Tweak final payment: ensure the final payment fully amortises the schedule

Let's look at each of these items in more detail.

Step 1: Generate payment days

Here we take the schedule config from the parameters and generate the payment days. In this example, the schedule is auto-generated, so the Scheduling.generatePaymentMap function takes the start date of the schedule, the unit period and the first payment date, and generates the payment days. It is also possible to specify the payment days manually or specify multiple ranges of dates at different intervals. However, the auto-generated schedule is the most common use case, and ensures respect for varying month lengths and month-end tracking dates.

let paymentMap = generatePaymentMap parameters.StartDate parameters.ScheduleConfig
let paymentDays = paymentMap |> Map.keys |> Seq.toArray

Result:

30, 61, 91, 122

Step 2: Estimate total interest

The Scheduling.totalAddOnInterest function calculates the total interest by taking

principal × dailyInterestRate × totalNumberOfDays

and capping this at 100% of the principal amount (as specified in the parameters under the interest Cap).

let finalScheduledPaymentDay = paymentDays |> Array.tryLast |> Option.defaultValue 0<OffsetDay>
let initialInterestBalance = totalAddOnInterest parameters finalScheduledPaymentDay

Result:

973.56

Step 3: Solve for payment values

Determining the payment values requires the use of a solver, because payment values determine how much principal is paid off each unit-period, and therefore how much interest is accrued, which in turn affects the payment values. We use the bisection method (Array.solveBisection) for this. This method runs a generator function (Scheduling.generatePaymentValue) on the schedule, which calculates the final principal balance for a given payment value. The bisection method then iteratively narrows down the level payment value until the final principal balance is close to zero (usually just below zero, so the final payment can be slightly smaller). To make the iteration more efficient, we use an initial guess for the payment value, which is calculated based on the estimated total interest and the number of payments. (In this instance, the initial guess is actually the correct payment value, as the schedule is simple, but for more complex schedules, several iterations may be required.)


Show/hide code
// precalculations
let firstItem = { SimpleItem.initial with InterestBalance = initialInterestBalance; PrincipalBalance = parameters.Principal }
let paymentCount = Array.length paymentDays
let interest = Cent.toDecimalCent initialInterestBalance
let roughPayment =
    calculateLevelPayment paymentCount parameters.PaymentConfig.Rounding parameters.Principal 0L<Cent> interest
    |> Cent.toDecimalCent
    |> decimal
// the following calculations are part of `cref:M:FSharp.Finance.Personal.Scheduling.generatePaymentValue` but modified to show the intermediate steps
let scheduledPayment =
    roughPayment
    |> Cent.round parameters.PaymentConfig.Rounding
    |> fun rp -> ScheduledPayment.quick (ValueSome rp) ValueNone
let simpleItems =
    paymentDays
    |> Array.scan(fun simpleItem pd ->
        generateItem parameters parameters.InterestConfig.Method scheduledPayment simpleItem pd
    ) firstItem
Day Scheduled payment Simple interest Interest portion Principal portion Interest balance Principal balance Total simple interest Total interest Total principal
0 0.00 0.0000 0.00 0.00 973.56 1,000.00 0.0000 0.00 0.00
30 493.39 239.4000 493.39 0.00 480.17 1,000.00 239.4000 493.39 0.00
61 493.39 247.3800 480.17 13.22 0.00 986.78 486.7800 973.56 13.22
91 493.39 236.2351 0.00 493.39 0.00 493.39 723.0151 973.56 506.61
122 493.39 122.0548 0.00 493.39 0.00 0.00 845.0700 973.56 1,000.00

Step 4: Iterate to equalise interest

Now the schedule days and payment values are known, we iterate through the schedule until the final principal balance is zero.

This step is required because the initial interest balance is non-zero, meaning that any payments are apportioned to interest first, meaning that the principal balance is paid off at a difference pace than it would otherwise be; this, in turn, generates different interest, which leads to a different initial interest balance, so the process must be repeated until the total interest and the initial interest are equalised.


Show/hide code
let finalInterestTotal =
    simpleItems
    |> Array.last
    |> _.TotalSimpleInterest
let simpleItems' =
    ValueSome { Iteration = 0; InterestBalance = finalInterestTotal }
    |> Array.unfold (equaliseInterest parameters paymentDays firstItem paymentCount 0L<Cent> paymentMap)
    |> Array.last
Day Scheduled payment Simple interest Interest portion Principal portion Interest balance Principal balance Total simple interest Total interest Total principal
0 0.00 0.0000 0.00 0.00 816.56 1,000.00 0.0000 0.00 0.00
30 454.15 239.4000 454.15 0.00 362.41 1,000.00 239.4000 454.15 0.00
61 454.15 247.3800 362.41 91.74 0.00 908.26 486.7800 816.56 91.74
91 454.15 217.4374 0.00 454.15 0.00 454.11 704.2174 816.56 545.89
122 454.15 112.3377 0.00 454.15 0.00 -0.04 816.5552 816.56 1,000.04

Step 5: Tweak final payment

The final payment is adjusted (Scheduling.adjustFinalPayment) to ensure that the final principal balance is zero.

let items =
    simpleItems'
    |> adjustFinalPayment finalScheduledPaymentDay parameters.ScheduleConfig.IsAutoGenerateSchedule
Day Scheduled payment Simple interest Interest portion Principal portion Interest balance Principal balance Total simple interest Total interest Total principal
0 0.00 0.0000 0.00 0.00 816.56 1,000.00 0.0000 0.00 0.00
30 454.15 239.4000 454.15 0.00 362.41 1,000.00 239.4000 454.15 0.00
61 454.15 247.3800 362.41 91.74 0.00 908.26 486.7800 816.56 91.74
91 454.15 217.4374 0.00 454.15 0.00 454.11 704.2174 816.56 545.89
122 454.11 112.3377 0.00 454.11 0.00 0.00 816.5552 816.56 1,000.00

As an extra step, the library calculates a number of statistics for the schedule, including the total interest accrued, the total fees and charges, the total payments made, and the final principal balance. The full output for this schedule, including stats, is available in the Output section in the page Unit-Test Outputs, under Compliance. This particular example is defined as ComplianceTest022.

Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
namespace FSharp.Finance
namespace FSharp.Finance.Personal
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 parameters: Parameters
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: Map<int<OffsetDay>,ScheduledPayment>
<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 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 PaymentConfig from FSharp.Finance.Personal.Scheduling
<summary> how to treat scheduled payments </summary>

--------------------
type PaymentConfig = { LevelPaymentOption: LevelPaymentOption ScheduledPaymentOption: ScheduledPaymentOption Rounding: Rounding Minimum: MinimumPayment Timeout: int<DurationDay> }
<summary> how to treat scheduled payments </summary>
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>
[<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>
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 MinimumPayment.DeferOrWriteOff: 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>
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 = | Simple | AddOn member Html: string with get
<summary> the method used to calculate the interest </summary>
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>
Multiple items
module Rate from FSharp.Finance.Personal.Interest

--------------------
[<Struct>] type Rate = | Zero | Annual of Annual: Percent | Daily of Daily: 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: 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 Percentage: Percent * Restriction: Restriction | Simple of Simple: 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: Percentage: Percent * Restriction: 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 LowerLimit: int64<Cent> | UpperLimit of UpperLimit: 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 Interest.Rate.Zero: Interest.Rate
<summary> a zero rate </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 = | 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>
val schedule: SimpleSchedule
val calculate: sp: Parameters -> SimpleSchedule
<summary> calculates the number of days between two offset days on which interest is chargeable </summary>
Multiple items
module SimpleSchedule from FSharp.Finance.Personal.Scheduling
<summary> a schedule of payments, with statistics </summary>

--------------------
type SimpleSchedule = { EvaluationDay: int<OffsetDay> Items: SimpleItem array Stats: InitialStats }
<summary> a schedule of payments, with statistics </summary>
val toHtmlTable: schedule: SimpleSchedule -> string
<summary> formats the schedule items as an HTML table (stats can be rendered separately) </summary>
val simpleInterestSchedule: SimpleSchedule
union case Interest.Method.Simple: Interest.Method
<summary> simple interest method, where interest is based on the principal balance and the number of days outstanding </summary>
val paymentMap: Map<int<OffsetDay>,ScheduledPayment>
val generatePaymentMap: startDate: Date -> paymentSchedule: ScheduleConfig -> Map<int<OffsetDay>,ScheduledPayment>
<summary> generates a map of offset days and payments based on a start date and payment schedule </summary>
Parameters.StartDate: Date
<summary> the start date of the schedule, typically the day on which the principal is advanced </summary>
Parameters.ScheduleConfig: ScheduleConfig
<summary> the scheduled payments or the parameters for generating them </summary>
val paymentDays: int<OffsetDay> array
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 keys: table: Map<'Key,'T> -> System.Collections.Generic.ICollection<'Key> (requires comparison)
module Seq from Microsoft.FSharp.Collections
val toArray: source: 'T seq -> 'T array
Multiple items
module Array from FSharp.Finance.Personal.Calculation
<summary> functions for working with arrays </summary>

--------------------
module Array from Microsoft.FSharp.Collections
val map: mapping: ('T -> 'U) -> array: 'T array -> 'U array
Multiple items
val string: value: 'T -> string

--------------------
type string = System.String
module String from Microsoft.FSharp.Core
val concat: sep: string -> strings: string seq -> string
val finalScheduledPaymentDay: int<OffsetDay>
val tryLast: array: 'T array -> 'T option
module Option from Microsoft.FSharp.Core
val defaultValue: value: 'T -> option: 'T option -> 'T
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>
val initialInterestBalance: int64<Cent>
val totalAddOnInterest: sp: Parameters -> finalPaymentDay: int<OffsetDay> -> int64<Cent>
val toDecimal: c: int64<Cent> -> decimal
<summary> raise to the standard currency unit, e.g. 1234¢ -&gt; $12.34 </summary>
val m: decimal
val firstItem: SimpleItem
Multiple items
module SimpleItem from FSharp.Finance.Personal.Scheduling
<summary> a scheduled payment item, with running calculations of interest and principal balance </summary>

--------------------
type SimpleItem = { Day: int<OffsetDay> ScheduledPayment: ScheduledPayment SimpleInterest: decimal<Cent> InterestPortion: int64<Cent> PrincipalPortion: int64<Cent> InterestBalance: int64<Cent> PrincipalBalance: int64<Cent> TotalSimpleInterest: decimal<Cent> TotalInterest: int64<Cent> TotalPrincipal: int64<Cent> }
<summary> a scheduled payment item, with running calculations of interest and principal balance </summary>
val initial: SimpleItem
<summary> a default value with no data </summary>
Parameters.Principal: int64<Cent>
<summary> the principal </summary>
val paymentCount: int
val length: array: 'T array -> int
val interest: decimal<Cent>
val toDecimalCent: c: int64<Cent> -> decimal<Cent>
<summary> convert an integer cent value to a decimal cent value, e.g. for precise interest calculation, 1234¢ -&gt; 1234.0000¢ </summary>
val roughPayment: decimal
val calculateLevelPayment: paymentCount: int -> paymentRounding: Rounding -> principal: int64<Cent> -> fee: int64<Cent> -> interest: decimal<Cent> -> int64<Cent>
Parameters.PaymentConfig: PaymentConfig
<summary> options relating to scheduled payments </summary>
PaymentConfig.Rounding: Rounding
<summary> how to round payments </summary>
Multiple items
val decimal: value: 'T -> decimal (requires member op_Explicit)

--------------------
type decimal = System.Decimal

--------------------
type decimal<'Measure> = decimal
val scheduledPayment: ScheduledPayment
val round: rounding: Rounding -> m: decimal -> int64<Cent>
<summary> derive a rounded cent value from a decimal according to the specified rounding method </summary>
val rp: int64<Cent>
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 quick: originalAmount: int64<Cent> voption -> rescheduledAmount: RescheduledPayment voption -> ScheduledPayment
<summary> a quick convenient method to create a basic scheduled payment </summary>
union case ValueOption.ValueSome: 'T -> ValueOption<'T>
union case ValueOption.ValueNone: ValueOption<'T>
val simpleItems: SimpleItem array
val scan<'T,'State> : folder: ('State -> 'T -> 'State) -> state: 'State -> array: 'T array -> 'State array
val simpleItem: SimpleItem
val pd: int<OffsetDay>
val generateItem: sp: Parameters -> interestMethod: Interest.Method -> scheduledPayment: ScheduledPayment -> previousItem: SimpleItem -> day: int<OffsetDay> -> SimpleItem
Parameters.InterestConfig: Interest.Config
<summary> options relating to interest </summary>
Interest.Config.Method: Interest.Method
<summary> the method for calculating interest </summary>
module Unchecked from Microsoft.FSharp.Core.Operators
val defaultof<'T> : 'T
Multiple items
module InitialStats from FSharp.Finance.Personal.Scheduling
<summary> statistics resulting from the simple schedule calculations </summary>

--------------------
[<Struct>] type InitialStats = { InitialInterestBalance: int64<Cent> LastScheduledPaymentDay: int<OffsetDay> LevelPayment: int64<Cent> FinalPayment: int64<Cent> ScheduledPaymentTotal: int64<Cent> PrincipalTotal: int64<Cent> InterestTotal: int64<Cent> InitialApr: Percent InitialCostToBorrowingRatio: Percent }
<summary> final statistics based on the payments being made on time and in full </summary>
val finalInterestTotal: decimal<Cent>
val last: array: 'T array -> 'T
val simpleItems': SimpleItem array
val unfold<'T,'State> : generator: ('State -> ('T * 'State) option) -> state: 'State -> 'T array
val equaliseInterest: sp: Parameters -> paymentDays: int<OffsetDay> array -> firstItem: SimpleItem -> paymentCount: int -> feeTotal: int64<Cent> -> paymentMap: Map<int<OffsetDay>,ScheduledPayment> -> stateOption: EqualiseInterestState voption -> (SimpleItem array * EqualiseInterestState voption) option
val items: SimpleItem array
val adjustFinalPayment: finalScheduledPaymentDay: int<OffsetDay> -> isAutoGenerateSchedule: bool -> simpleItems: SimpleItem array -> SimpleItem array
<summary> handle any principal balance overpayment (due to rounding) on the final payment of a schedule </summary>
property ScheduleConfig.IsAutoGenerateSchedule: bool with get

Type something to start searching.