Skip to content

Amortization

The apps.amortization module handles schedule generation, period status management, and financial calculations for loan repayment.

Schedule Types

Type Description
Fixed (level payment) Standard amortizing schedule with equal payments
Interest-only Interest-only payments for a configurable initial period, then amortizing
Balloon Regular payments with a large final payment for remaining balance
Graduated / step-rate Payment amount or rate changes at defined intervals

The schedule type is determined by the lending program and product configuration.

Schedule Generation

Amortization schedules are generated on loan disbursement by the lending program's generate_schedule() method. Each schedule row represents one payment period:

Field Type Description
period_number Integer Sequential period (1, 2, 3, ...)
due_date Date Payment due date for this period
principal_due MoneyField Principal portion of payment
interest_due MoneyField Interest portion of payment
total_due MoneyField Total payment due
balance_after MoneyField Expected balance after payment
status TextChoices Period status (see below)
actual_payment MoneyField Amount actually paid
actual_payment_date Date Date payment was received
is_deferred Boolean Whether this period is deferred

Period Status Transitions

Each amortization period progresses through a defined status lifecycle:

future → booked → due → overdue → paid
                              └──→ missed
Status Meaning
future Not yet active, payment not expected
booked Scheduled but not yet due
due Payment is currently due
overdue Past due date, payment not received
paid Payment received and applied
missed Payment was not made (past due + next period started)

Daily Status Transitions

A daily Celery task processes all active loans and transitions period statuses:

  1. future → due --- When the period's due date is reached
  2. due → overdue --- When the due date passes without full payment

These transitions trigger recalculation of the loan's tracking fields.

Loan Tracking Fields

When period statuses change, the loan's tracking fields are recalculated from the schedule:

Loan Field Derived From
current_period First non-paid/non-missed period
periods_past_due Count of overdue/missed periods
periods_remaining Count of future/booked periods
next_due_date Due date of the current period

Schedule Regeneration

Schedules are recalculated when loan terms change:

  • Rate change --- New interest rate, future periods recalculated
  • Term extension --- Additional periods added
  • Principal reduction/forgiveness --- Reduced balance, future periods recalculated
  • Capitalization --- Accrued interest/fees rolled into principal
  • Due date change --- Schedule shifted, odd-period interest adjusted

See Servicing Operations for modification workflows.

Deferred Periods

When a loan enters deferment, affected amortization periods are marked is_deferred = True. Deferred periods:

  • Are skipped during payment processing
  • Extend the loan's maturity date
  • Interest treatment depends on the deferment configuration (accruing, subsidized, or capitalized)

Financial Calculations

The amortization module provides pure financial calculation functions (no database dependency):

XIRR (Internal Rate of Return)

Computed via the Newton-Raphson method for irregular cash flows:

MOIC (Multiple on Invested Capital)

MOIC = Total Inflows / Total Outflows
  • Total inflows: all payments received
  • Total outflows: disbursement amount

Per-Diem Interest

Daily interest calculation used for payoff quotes:

per_diem = outstanding_balance × annual_rate / day_count_denominator

Where day_count_denominator is determined by the lending program's day-count convention (360, 365, or actual days in year).

See Also