Skip to main content

Cent-accurate mortgage amortization for Python — validated against 46 published sources across 6 countries. Zero dependencies.

Project description

mortgagemath logo

mortgagemath

tests

coverage PyPI License: MIT PyPI Downloads Documentation

Cent-accurate mortgage amortization for Python. Every payment, interest charge, and balance is computed with Decimal arithmetic and validated against 46 published worked examples from government regulators, bank servicing guides, and academic textbooks across six countries. Zero runtime dependencies.

Why mortgagemath?

Most mortgage libraries get the monthly payment right but diverge from real lender statements by 1–4 cents per row. That drift compounds over the schedule, breaks reconciliation against actual bank statements, and makes audit work painful. mortgagemath is built around the rounding and accounting conventions that actual lenders use:

  • Decimal arithmetic end-to-end (no float drift)
  • Configurable roundingROUND_UP, ROUND_DOWN, ROUND_HALF_UP, ROUND_HALF_EVEN
  • Two balance-tracking modesROUND_EACH (US lender statements) and CARRY_PRECISION (Excel / CRE textbooks)
  • Both day-count conventions — 30/360 and Actual/360
  • International compounding — monthly (US), semi-annual (Canadian Interest Act j₂), and effective-annual
  • Flexible payment frequency — monthly, bi-weekly, weekly, quarterly, semi-monthly, or annual
  • Adjustable-rate mortgages with rate schedules, payment caps, and negative amortization
  • Interest-only periods with automatic recast
  • Flat per-period fees for French assurance emprunteur and similar insurance loadings
  • Currency unit precisionDecimal("0.01") for cents or Decimal("1") for yen/won
  • Exact zero ending balance — the final row trues up so the schedule lands at exactly zero
  • 46 validated fixtures from the US, Canada, France, Japan, Italy, and South Korea

Installation

pip install mortgagemath

Requires Python 3.11+. Zero runtime dependencies.

python -m mortgagemath   # self-check against reference values

Quick example

A standard 30-year fixed-rate mortgage from the command line:

mortgagemath summary --principal 300000 --rate 6.5 --term-months 360

Or generate the full payment-by-payment schedule:

mortgagemath schedule --principal 300000 --rate 6.5 --term-months 360

The same loan from Python:

from mortgagemath import us_30_year_fixed, periodic_payment, amortization_schedule

loan = us_30_year_fixed("300000", "6.5")

print(periodic_payment(loan))         # Decimal("1896.21")
sched = amortization_schedule(loan)
print(sched[1].interest)              # Decimal("1625.00")  — payment #1
print(sched[1].principal)             # Decimal("271.21")
print(sched[-1].balance)              # Decimal("0.00")     — exact zero
print(sched[-1].total_interest)       # Decimal("382628.90") — lifetime interest

The schedule is a plain listsched[0] is the initial balance (no payment), sched[1] through sched[360] are the monthly payments.

For a quick summary without iterating the schedule:

from mortgagemath import us_30_year_fixed, loan_summary

s = loan_summary(us_30_year_fixed("300000", "6.5"))
print(s.periodic_payment)             # Decimal("1896.21")
print(s.total_interest)               # Decimal("382628.90")
print(s.total_paid)                   # Decimal("682628.90")
print(s.num_payments)                 # 360

Convenience constructors like us_30_year_fixed, us_15_year_fixed, canada_fixed_j2, canada_accelerated_biweekly, and us_actual_360_commercial handle common cases. The full LoanParams dataclass is available when you need every parameter explicitly:

from decimal import Decimal
from mortgagemath import LoanParams, PaymentRounding, amortization_schedule

loan = LoanParams(
    principal=Decimal("162000"),
    annual_rate=Decimal("3.875"),
    term_months=360,
    payment_rounding=PaymentRounding.ROUND_HALF_UP,
    interest_rounding=PaymentRounding.ROUND_HALF_UP,
)
sched = amortization_schedule(loan)
print(sched[1].payment)             # Decimal("761.78")

For Canadian j₂ mortgages, ARMs with rate and payment caps, commercial Actual/360 with balloon, interest-only periods, fee-loaded French schedules, and Japanese yen-precision loans, see the Worked examples vignette.

Pandas and Matplotlib integration

mortgagemath returns pure Python dataclasses, so converting to a pandas.DataFrame for analysis or plotting is one line:

Pandas Plot

import pandas as pd
from mortgagemath import us_30_year_fixed, amortization_schedule

loan = us_30_year_fixed("300000", "6.5")
df = pd.DataFrame(amortization_schedule(loan))

See the Pandas and Data Visualization vignette for plotting examples and scenario analysis.

What's validated

46 published amortization tables exercised by a test suite of more than 400 tests that runs on every push and release. Every committed fixture cell reproduces its source value to the cent (or yen). The sources span six countries and a wide range of loan structures:

  • US regulatory — CFPB sample disclosures, Reg Z Appendix H ARM with 15 years of historical rate adjustments, FHLBB 1935 direct-reduction plan
  • US commercial — Fannie Mae Multifamily Actual/360 with balloon, Geltner CRE carry-precision
  • US textbooks — OpenStax, Goldstein, Skinner (1913), Arcones SOA Exam FM, Las Positas, Mississippi State Extension
  • Canada — Olivier and eCampus Ontario semi-annual j₂ mortgages (monthly and quarterly), RBC accelerated bi-weekly
  • France — MoneyVox tableau d'amortissement with assurance emprunteur fee loading
  • Japan — JHF Flat 35 and LoanKeisan full 360-row schedule with yen-precision truncation rounding
  • Italy — Solution Bank and BCC Brescia regulatory transparency documents
  • South Korea — Tistory worked mortgage with won-precision
  • Reference works — TI BA II Plus official guidebook, Wikipedia mortgage calculator
  • Synthetic — half-cent rounding boundaries, zero-interest edge case

See the Validation vignette for the full 46-fixture parameter matrix and bibliography.

Documentation

Resource Audience
Read the Docs Installation, quickstart, full API reference, changelog
At a glance 60-second orientation
Validation Audit / risk review — full fixture matrix + bibliography
Worked examples Picking the right configuration by country and loan type
History Academic context — institutional and mathematical history of the level-payment mortgage
Pandas & Viz DataFrames, plotting, and scenario analysis
HTML site Vignettes with navigation and search

Reporting a discrepancy

Found a published example or a real lender statement that mortgagemath doesn't reproduce to the cent? Two paths:

  • Reporters / users — open an issue using the Mortgage example doesn't match template. Paste the published values; no pytest needed.
  • Contributors — add a paired TOML + CSV fixture under tests/schedules/. See tests/schedules/README.md for the schema and contribution workflow.

For unrelated bugs or feature requests, use the Bug or feature request template.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mortgagemath-0.7.1.tar.gz (4.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mortgagemath-0.7.1-py3-none-any.whl (31.1 kB view details)

Uploaded Python 3

File details

Details for the file mortgagemath-0.7.1.tar.gz.

File metadata

  • Download URL: mortgagemath-0.7.1.tar.gz
  • Upload date:
  • Size: 4.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.10 {"installer":{"name":"uv","version":"0.11.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for mortgagemath-0.7.1.tar.gz
Algorithm Hash digest
SHA256 e5c242a124730c6b506779bccdd32e171c2053adc431d572a382cb8a263b46e3
MD5 12b24355b583220827c7c157c2944f80
BLAKE2b-256 ef91ffa69cb94c15a1fe47b6bbcde6321ef419f7914ac375874bd036b90ca1a3

See more details on using hashes here.

File details

Details for the file mortgagemath-0.7.1-py3-none-any.whl.

File metadata

  • Download URL: mortgagemath-0.7.1-py3-none-any.whl
  • Upload date:
  • Size: 31.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.10 {"installer":{"name":"uv","version":"0.11.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for mortgagemath-0.7.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4ebb520ae826168ab03e11eb934d57df0c3fa007f0d13ca207757dc82afe9c04
MD5 12e7fa68618144a1fc713fb6a20ccd85
BLAKE2b-256 c231009a2393188c41f3455e8e91d53d6323d4996081ef119e0901e7b74578c3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page