[][src]Function finance_solution::payment_solution

pub fn payment_solution<P, F>(
    rate: f64,
    periods: u32,
    present_value: P,
    future_value: F,
    due_at_beginning: bool
) -> PaymentSolution where
    P: Into<f64> + Copy,
    F: Into<f64> + Copy

Calculates the payment needed for each period for an amortized loan and creates a struct showing the interest, the formula, and optionally the period-by-period values.

Related functions:

  • To calculate the payment as a simple number instead of a struct when the payment is due at the end of each period use payment.

In the typical case where there's a present value and the future value is zero, and the payment is due at the end of the period, the formula is:

payment = ((present_value * (1 + rate)periods) * -rate) / ((1 + rate)periods - 1)

or with the more commonly used variables:

pmt = ((pv * (1 + r)n) * -r) / ((1 + r)n - 1)

Often the payment is shown as A and the present value is P for principal.

If there's a future value and the present value is zero, the formula is:

payment = (future_value * -rate) / ((1 + rate)periods - 1)

or:

pmt = (fv * -r) / ((1 + r)n - 1)

If both present value and future value are nonzero the formula is:

payment = (((present_value * (1 + rate)periods) + future_value) * -rate) / ((1 + rate)periods - 1)

or:

pmt = (((pv * (1 + r)n) + fv) * -r) / ((1 + r)n - 1)

If the payment is due at the beginning of the period, the only difference is that the payment is divided by (1 + rate). In our formulas this means multiplying the denominator by (1 + rate) so in the typical case where there's a present value and the future value is zero, the formula is:

payment = ((present_value * (1 + rate)periods) * -rate) / (((1 + rate)periods - 1) * (1 + rate))

or with the more commonly used variables:

pmt = ((pv * (1 + r)n) * -r) / (((1 + r)n - 1) * (1 + r))",

This is nearly the same formula as the one for payments due at the end of the period. The relationship between the two formulas is that:

payment_due(x) = payment(x) / (1 + rate)

Thus the payment is slightly smaller if it's due at the beginning of the month since the principal is paid down a bit faster.

If there's a future value and the present value is zero, the formula is:

payment = (future_value * -rate) / (((1 + rate)periods - 1) * (1 + rate))

or:

pmt = (fv * -r) / (((1 + r)n - 1) * (1 + r))

If both present value and future value are nonzero the formula is:

payment = (((present_value * (1 + rate)periods) + future_value) * -rate) / (((1 + rate)periods - 1) * (1 + rate))

or:

pmt = (((pv * (1 + r)n) + fv) * -r) / (((1 + r)n - 1) * (1 + r))

Arguments

  • rate - The interest rate per period, expressed as a floating point number. For instance 0.01 would mean 1% interest per period. The rate must match the period type. For instance if the periods are months and we're starting with an annual interest rate, the rate must be divided by 12 when calling the function as shown in the example below. The rate often appears as r or i (interest) in formulas.
  • periods - The number of periods such as quarters or periods. Often appears as n or t where t typically implies years.
  • present_value - In the case of an amortized loan this is the the principal. It may appear as pv in formulas, or C for cash flow or P for principal. Assuming that the future value is zero, the payment will be negative if the present value is positive and vice versa.
  • future_value - The value at the end of the last period. For a typical amortized loan this will be zero. It appears as fv in formulas.
  • due_at_beginning - True if the payment is due at the beginning of the period. Typically the payment will be due at the end of the period so this will be false.

Panics

The call will fail if rate is less than -1.0.

Examples

Calculate the payment for a simple amortized loan with the payment due at the end of the month, then examine the formulas and the period-by-period details such as the amount of the payment that goes to principal and interest.

// The interest rate is 11.75% per year. Each period is one month so we need to divide the rate
// by the number of months in a year.
let rate = 0.1175 / 12.0;

// The loan will be paid off in 48 months.
let periods = 48;

// The principal is $12,500.50. Here we'll express it as a negative number so that the payment,
// interest, and principal are all positive numbers for simplicity.
let present_value = -12_500.5;

// The loan will be fully paid off by the end of the last period.
let future_value = 0.0;

let due_at_beginning = false;

let solution = payment_solution(rate, periods, present_value, future_value, due_at_beginning);
// Display the inputs, payment amount, formulas, sum of interest, etc.
dbg!(&solution);

// The payment is $327.65/month. Since the principal/present value was negative the payment is
// positive.
assert_rounded_4(solution.payment(), 327.6538);

// The sum of payments is simply the monthly payment times the number of months.
assert_rounded_4(solution.sum_of_payments(), 15_727.3820);

// The sum of interest is the portion of the sum of payments that is over and above the original
// loan amount. Here we add the present value since it has the opposite sign of the payments.
assert_rounded_4(solution.sum_of_interest(), solution.sum_of_payments() + solution.present_value());
assert_rounded_4(solution.sum_of_interest(), 3_226.8820);

// Examine the formulas. Since the future value is zero we expect to see a slightly simplified
// formula.
let formula = solution.formula();
println!();
dbg!(&formula);
assert_eq!(formula, "327.6538 = (-12500.5000 * 1.009792^48 * -0.009792) / (1.009792^48 - 1)");
let symbolic_formula = solution.symbolic_formula();
println!();
dbg!(&symbolic_formula);
assert_eq!(symbolic_formula, "pmt = (pv * (1 + r)^n * -r) / ((1 + r)^n - 1)");

// Calculate the period-by-period values including the amount of the payment that goes toward
// interest and principle as well as the running tally of the remaining amounts.
let series = solution.series();
// Note that all of the period-by-period values are shown as of the end of the period after that
// period's payment has been made.
println!();
dbg!(&series);

// Print the period-by-period values in a table with two decimal places and the numbers aligned,
// with Vietnamese formatting for the thousands and decimal separators. Show all columns
// including running totals and remaining amounts.
let locale = &num_format::Locale::vi;
let include_running_totals = true;
let include_remaining_amounts = true;
println!();
series.print_table_locale(include_running_totals, include_remaining_amounts, &locale, 2);

// Print a table with only the last period of each year, that is all of the periods that can be
// divided by 12. Include the running totals columns but not remaining amounts. Also this time
// use default formatting without specifying the locale or number of decimal places.
let include_running_totals = true;
let include_remaining_amounts = false;
println!();
series
    .filter(|entry| entry.period() % 12 == 0)
    .print_table(include_running_totals, include_remaining_amounts);

// Print a table starting at the first period where at least 95% of the interest has been paid
// off, and round all dollar amounts to whole numbers by passing zero as the second argument to
// print_table_locale(). Include the remanining amounts columns but not the running totals.
let include_running_totals = false;
let include_remaining_amounts = true;
println!();
series
    .filter(|entry| entry.interest_to_date() >= solution.sum_of_interest() * 0.95)
    .print_table_locale(include_running_totals, include_remaining_amounts, locale, 0);