#!/usr/bin/env python3 """ Amortance — worked examples behind site/dental.html and site/bhph.html. A tiny event-sourced engine: an obligation is a pure function of its terms and an ordered log of postings. Every number printed here appears on the pages, and every number on the pages comes from here. Run it and the pages reproduce. python3 examples.py # both examples, full audit trail python3 examples.py --json # test vectors for the pages Conventions, stated because they are inputs and not laws of nature: * interest accrues on outstanding principal only (simple interest, no capitalisation), is computed per interval and rounded half-up to the cent before it is posted; * a payment is applied to accrued interest first, then to principal; * a retroactive change is not an adjustment: the log is replayed from origination with the change inserted at its effective date. """ from __future__ import annotations import json import pathlib import sys from dataclasses import dataclass, field from datetime import date, timedelta from decimal import Decimal, ROUND_HALF_UP CENT = Decimal("0.01") def d(x) -> Decimal: return Decimal(str(x)) def r2(x: Decimal) -> Decimal: return x.quantize(CENT, rounding=ROUND_HALF_UP) def days360(d1: date, d2: date) -> int: """US 30/360 day count.""" dd1, dd2 = d1.day, d2.day if dd1 == 31: dd1 = 30 if dd2 == 31 and dd1 == 30: dd2 = 30 return (d2.year - d1.year) * 360 + (d2.month - d1.month) * 30 + (dd2 - dd1) def day_count(d1: date, d2: date, conv: str) -> tuple[int, Decimal]: if conv == "30/360": return days360(d1, d2), d(360) if conv == "actual/365": return (d2 - d1).days, d(365) if conv == "actual/360": return (d2 - d1).days, d(360) raise ValueError(conv) def started_months(d1: date, d2: date) -> int: """Whole months elapsed plus a started one — how service contracts count.""" whole = (d2.year - d1.year) * 12 + (d2.month - d1.month) - (1 if d2.day < d1.day else 0) return whole + (0 if add_months(d1, whole) == d2 else 1) def add_months(dt: date, n: int) -> date: m = dt.month - 1 + n y = dt.year + m // 12 m = m % 12 + 1 return date(y, m, min(dt.day, [31, 29 if y % 4 == 0 and (y % 100 or y % 400 == 0) else 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][m - 1])) def basis_of(conv: str) -> Decimal: return d(365) if conv == "actual/365" else d(360) def nominal_rate(apr: Decimal, period_days: int, conv: str) -> Decimal: """The rate a contract quotes its installment at: the day count in force, applied to a nominal period. Under 30/360 monthly this is APR/12; under actual/360 biweekly it is APR x 14 / 360. Pricing a payment on one convention and accruing on another is how a schedule ends up not retiring the balance.""" return apr * d(period_days) / basis_of(conv) def annuity(principal: Decimal, rate: Decimal, n: int) -> Decimal: """Level payment at a periodic rate, rounded half-up to the cent.""" if rate == 0: return r2(principal / n) v = (1 + rate) ** -n return r2(principal * rate / (1 - v)) # ----------------------------------------------------------------- the engine @dataclass class Posting: on: date kind: str # principal | payment | fee amount: Decimal # signed for principal, positive for payment/fee note: str = "" tag: str = "" @dataclass class Row: on: date days: int interest: Decimal kind: str amount: Decimal to_interest: Decimal to_principal: Decimal principal: Decimal accrued: Decimal note: str @dataclass class Ledger: rows: list[Row] = field(default_factory=list) principal: Decimal = Decimal("0") accrued: Decimal = Decimal("0") interest_charged: Decimal = Decimal("0") interest_paid: Decimal = Decimal("0") paid: Decimal = Decimal("0") overpaid: Decimal = Decimal("0") # payments that met a zero balance def replay(origination: date, apr: Decimal, conv: str, postings: list[Posting], through: date | None = None) -> Ledger: """Replay a posting log into a ledger. Pure function of its arguments.""" lg = Ledger() cursor = origination log = sorted(postings, key=lambda p: (p.on, {"principal": 0, "fee": 1, "payment": 2}[p.kind])) for p in log: if through and p.on > through: break n, basis = day_count(cursor, p.on, conv) interest = r2(lg.principal * apr * d(n) / basis) if n else Decimal("0") lg.accrued += interest lg.interest_charged += interest cursor = p.on to_i = to_p = Decimal("0") if p.kind == "principal": lg.principal += p.amount if lg.principal < 0: # order shrank below what is owed excess = -lg.principal lg.principal = Decimal("0") settled = min(lg.accrued, excess) # the credit settles accrued interest first lg.accrued -= settled lg.interest_paid += settled lg.overpaid += excess - settled elif p.kind == "fee": lg.principal += p.amount # fee financed into the balance elif p.kind == "payment": to_i = min(lg.accrued, p.amount) lg.accrued -= to_i lg.interest_paid += to_i rest = p.amount - to_i to_p = min(lg.principal, rest) lg.principal -= to_p lg.overpaid += rest - to_p lg.paid += p.amount lg.rows.append(Row(p.on, n, interest, p.kind, p.amount, to_i, to_p, lg.principal, lg.accrued, p.note)) if through and cursor < through: n, basis = day_count(cursor, through, conv) interest = r2(lg.principal * apr * d(n) / basis) if n else Decimal("0") lg.accrued += interest lg.interest_charged += interest lg.rows.append(Row(through, n, interest, "accrual", Decimal("0"), Decimal("0"), Decimal("0"), lg.principal, lg.accrued, "accrual to date")) return lg def schedule(balance: Decimal, accrued: Decimal, rate: Decimal, dates: list[date], apr: Decimal | None = None, conv: str | None = None, start: date | None = None) -> tuple[Decimal, list]: """Re-amortize: dates stay, the installment moves. Last payment absorbs the residual. The installment is priced off the nominal periodic rate, the way a contract quotes it. The projected rows accrue on the day count actually in force, so the two only coincide when the periods happen to be uniform. """ pay = annuity(balance + accrued, rate, len(dates)) bal, acc, rows = balance, accrued, [] cursor = start for i, dt in enumerate(dates): if apr is not None and cursor is not None: n, basis = day_count(cursor, dt, conv) interest = r2(bal * apr * d(n) / basis) cursor = dt else: interest = r2(bal * rate) acc += interest amount = pay if i < len(dates) - 1 else r2(bal + acc) to_i = min(acc, amount) acc -= to_i to_p = amount - to_i bal -= to_p rows.append((dt, amount, interest, to_i, to_p, bal)) return pay, rows def money(x: Decimal) -> str: return f"${x:,.2f}" def show(title: str, lg: Ledger, since: date | None = None) -> None: print(f"\n {title}") print(f" {'date':<12}{'days':>5}{'interest':>11} {'posting':<10}{'amount':>11}" f"{'→int':>10}{'→prin':>11}{'principal':>12} note") for r in lg.rows: if since and r.on < since: continue print(f" {r.on.isoformat():<12}{r.days:>5}{money(r.interest):>11} {r.kind:<10}" f"{money(r.amount):>11}{money(r.to_interest):>10}{money(r.to_principal):>11}" f"{money(r.principal):>12} {r.note}") # --------------------------------------------------------- example 1: dental def dental(verbose=True, conv="30/360", adjudication="service") -> dict: """conv: 30/360 | actual/365 | actual/360. adjudication: service (effective the date of service) | received (effective when it posts).""" apr = d("0.099") rate = nominal_rate(apr, 30, conv) start = date(2026, 3, 1) dues = [add_months(start, i) for i in range(1, 13)] items = [ ("D2740", "Crown, porcelain/ceramic — #14", d(1450), d(435), d(1015)), ("D2740", "Crown, porcelain/ceramic — #15", d(1450), d(435), d(1015)), ("D6010", "Implant body, endosteal — #19", d(2100), d(315), d(1785)), ("D0367", "CBCT capture, both jaws", d(260), d(75), d(185)), ] order_total = sum(i[2] for i in items) est_ins = sum(i[3] for i in items) patient = sum(i[4] for i in items) down = d(400) financed = patient - down pay0 = annuity(financed, rate, 12) as_signed = replay(start, apr, conv, [Posting(start, "principal", financed, "amount financed", "origination")] + [Posting(dt, "payment", pay0, f"installment {i+1}", "installment") for i, dt in enumerate(dues)]) _, as_signed_rows = schedule(financed, d(0), rate, dues, apr, conv, start) ev_eob, ev_add, ev_cancel = date(2026, 4, 23), date(2026, 5, 14), date(2026, 10, 5) eob_delta, add_delta, cancel_delta = d(-870), d(238), d(-1785) log = [Posting(start, "principal", financed, "amount financed", "origination"), Posting(dues[0], "payment", pay0, "installment 1", "installment"), # adjudication: a correction of the patient's share. Effective the date of # service (the share was always this, the estimate was wrong) or effective # when the money posts — a term of the contract, not a property of the code. Posting(start if adjudication == "service" else ev_eob, "principal", eob_delta, f"EOB posted {ev_eob:%b %-d}, effective " + ("date of service" if adjudication == "service" else "on receipt"), "event")] at_eob = replay(start, apr, conv, log, through=ev_eob) pay1, _ = schedule(at_eob.principal, at_eob.accrued, rate, dues[1:]) def run(pay: Decimal, dates: list[date]) -> Ledger: return replay(start, apr, conv, log[:3] + [Posting(dt, "payment", pay, "p", "") for dt in dates], through=dates[-1]) def level(dates: list[date]) -> Decimal: """The installment that leaves the last one level with the rest: the smallest whole cent whose repetition retires the balance without the final payment exceeding it. Binary search in cents, because the predicate is monotone.""" lo, hi = 1, int(pay0 * 200) while lo < hi: mid = (lo + hi) // 2 pay = d(mid) / 100 lg = replay(start, apr, conv, log[:3] + [Posting(dt, "payment", pay, "p", "") for dt in dates[:-1]], through=dates[-1]) if lg.principal + lg.accrued <= pay: hi = mid else: lo = mid + 1 return d(lo) / 100 tail = run(pay1, dues[1:]) pay1_final = pay1 - tail.overpaid pay1_level = level(dues[1:]) log += [Posting(dues[1], "payment", pay1, "installment 2", "installment"), # production added: effective the date performed — credit was extended that day. Posting(ev_add, "principal", add_delta, "D4341 perio treatment, effective date performed", "event")] at_add = replay(start, apr, conv, log, through=ev_add) pay2, _ = schedule(at_add.principal, at_add.accrued, rate, dues[2:]) paid_dues = dues[2:7] # 06-01 … 10-01, paid on time at the new installment log += [Posting(dt, "payment", pay2, f"installment {i+3}", "installment") for i, dt in enumerate(paid_dues)] before_cancel = replay(start, apr, conv, log, through=ev_cancel) # the fork: D6010 was financed but never performed fwd = replay(start, apr, conv, log + [Posting(ev_cancel, "principal", cancel_delta, "D6010 removed, effective today", "event")], through=ev_cancel) ret = replay(start, apr, conv, log + [Posting(start, "principal", cancel_delta, "D6010 removed, effective date of service", "event")], through=ev_cancel) def closed_on(lg: Ledger) -> date: """The date the balance first reached zero.""" for r in lg.rows: if r.principal == 0 and r.kind in ("payment", "principal"): return r.on return ev_cancel paid_total = down + pay0 + pay1 + pay2 * len(paid_dues) corrected_share = patient + eob_delta + add_delta + cancel_delta out = dict(order_total=order_total, est_ins=est_ins, patient=patient, down=down, financed=financed, pay0=pay0, pay1=pay1, pay2=pay2, apr=apr, rate=rate, items=items, dues=dues, start=start, ev_eob=ev_eob, ev_add=ev_add, ev_cancel=ev_cancel, eob_delta=eob_delta, add_delta=add_delta, cancel_delta=cancel_delta, as_signed_interest=as_signed.interest_charged, at_eob=at_eob, at_add=at_add, before_cancel=before_cancel, fwd=fwd, ret=ret, paid_total=paid_total, corrected_share=corrected_share, conv=conv, adjudication=adjudication, as_signed_rows=as_signed_rows, eob_pv=at_eob.principal, pay1_final=pay1_final, pay1_level=pay1_level, fwd_closed=closed_on(fwd), ret_closed=closed_on(ret), accrued_to_eob=at_eob.accrued, accrued_at_add=at_add.accrued, credit_gap=ret.overpaid - fwd.overpaid, interest_gap=fwd.interest_charged - ret.interest_charged) if verbose: print("=" * 100) print(" DENTAL — practice-financed treatment plan, 12 months, 9.90% APR, 30/360") print("=" * 100) print(f"\n order {money(order_total)} estimated benefit {money(est_ins)} " f"patient share {money(patient)} down {money(down)} financed {money(financed)}") print(f" installment as signed {money(pay0)} ×12, first {dues[0]}, last {dues[-1]}; " f"interest if nothing changed {money(as_signed.interest_charged)}") print(f"\n {ev_eob} EOB patient share {money(eob_delta):>10} → installment {money(pay1)}") print(f" {ev_add} D2950 added patient share {money(add_delta):>10} → installment {money(pay2)}") print(f" {ev_cancel} D6010 removed patient share {money(cancel_delta):>10} → the fork") show("A — effective today (forward only)", fwd) print(f" principal {money(fwd.principal)} accrued {money(fwd.accrued)} " f"interest charged {money(fwd.interest_charged)} CREDIT DUE {money(fwd.overpaid)}") show("B — effective date of service (replayed)", ret) print(f" principal {money(ret.principal)} accrued {money(ret.accrued)} " f"interest charged {money(ret.interest_charged)} CREDIT DUE {money(ret.overpaid)}") print(f"\n paid to date {money(paid_total)} = down {money(down)} + {money(pay0)} + " f"{money(pay1)} + 5 × {money(pay2)}") print(f" corrected patient share {money(corrected_share)}; " f"cash difference {money(paid_total - corrected_share)}") print(f" the two readings differ by {money(out['credit_gap'])} of credit and " f"{money(out['interest_gap'])} of interest") return out # ----------------------------------------------------------- example 2: bhph def bhph(verbose=True, conv="actual/365", refund_basis="days") -> dict: """conv: actual/365 | actual/360 | 30/360. refund_basis: days (pro rata by elapsed days) | months (by started months).""" apr = d("0.199") sale = date(2026, 1, 16) first = sale + timedelta(days=14) n = 91 # 42 months, biweekly dues = [first + timedelta(days=14 * i) for i in range(n)] items = [ ("Vehicle", "2018 Chevrolet Equinox LT, 96,412 mi", d(13995)), ("Service contract", "24 months / 24,000 miles", d(1795)), ("GAP waiver", "term of the contract", d(495)), ("Documentary fee", "", d(199)), ("Sales tax", "state and local", d("874.69")), ("Title and registration", "", d(215)), ] order_total = sum(i[2] for i in items) down = d(2175) financed = order_total - down period_rate = nominal_rate(apr, 14, conv) pay0 = annuity(financed, period_rate, n) base = [Posting(sale, "principal", financed, "amount financed", "origination")] + \ [Posting(dt, "payment", pay0, f"payment {i+1}", "installment") for i, dt in enumerate(dues)] # event 1 — deferral: payment 12 moved to the end of the term, $25 fee financed deferred = dues[11] after_end = dues[-1] + timedelta(days=14) log = [p for p in base if not (p.on == deferred and p.kind == "payment")] log += [Posting(deferred, "fee", d(25), "deferral fee, financed", "event"), Posting(after_end, "payment", pay0, "deferred payment", "installment")] # event 2 — service contract canceled; unearned premium refunded to the dealer cancel_on, refund_on = date(2026, 8, 7), date(2026, 8, 28) in_force, term_days = (cancel_on - sale).days, 730 used, of = ((in_force, term_days) if refund_basis == "days" else (started_months(sale, cancel_on), 24)) # Washington caps the fee on a service contract returned after 30 days with no claim # at $25 — RCW 48.110.075(4)(b) — and this example is written to that cap rather than # to a larger number nobody would have to justify. cancel_fee = d(25) refund = r2(d(1795) * (1 - d(used) / d(of))) - cancel_fee def run_to_payoff(effective: date | None): """Payment stays, term shortens. Returns (last date, its amount, count, interest).""" postings = list(log) + ([Posting(effective, "principal", -refund, "service contract refund", "event")] if effective else []) pay_dates = sorted({p.on for p in postings if p.kind == "payment"}) while True: # extend if a residual survives the last payment for i, dt in enumerate(pay_dates): lg = replay(sale, apr, conv, postings, through=dt) if lg.principal <= 0: return dt, r2(pay0 - lg.overpaid), i + 1, lg.interest_charged nxt = pay_dates[-1] + timedelta(days=14) postings.append(Posting(nxt, "payment", pay0, "residual", "installment")) pay_dates.append(nxt) end_none = run_to_payoff(None) end_cancel = run_to_payoff(cancel_on) end_receipt = run_to_payoff(refund_on) # event 3 — total loss; the customer stops paying, interest keeps running loss_on, settle_on, acv = date(2026, 10, 2), date(2026, 10, 24), d(9850) live = [p for p in log + [Posting(cancel_on, "principal", -refund, "service contract refund", "event")] if not (p.kind == "payment" and p.on > loss_on)] at_loss = replay(sale, apr, conv, live, through=loss_on) at_settle = replay(sale, apr, conv, live, through=settle_on) payoff_loss = at_loss.principal + at_loss.accrued payoff_settle = at_settle.principal + at_settle.accrued # What the waiver does not cover: what was added to the balance after origination (the # deferral fee) and the installment that fell due and was never collected (payment 12, # moved past the loss). Both exclusions are in the waiver's own words; only the first # one used to be in this arithmetic. excluded_fee = d(25) excluded_skipped = pay0 if deferred <= loss_on < after_end else d(0) out = dict(items=items, order_total=order_total, down=down, financed=financed, apr=apr, pay0=pay0, n=n, sale=sale, first=first, dues=dues, period_rate=period_rate, deferred=deferred, after_end=after_end, cancel_on=cancel_on, refund_on=refund_on, in_force=in_force, refund=refund, conv=conv, refund_basis=refund_basis, used=used, of=of, cancel_fee=cancel_fee, premium=d(1795), term_days=term_days, refund_gross=r2(d(1795) * (1 - d(used) / d(of))), end_none=end_none, end_cancel=end_cancel, end_receipt=end_receipt, loss_on=loss_on, settle_on=settle_on, acv=acv, live=live, base=base, opening=schedule(financed, d(0), period_rate, dues, apr, conv, sale)[1], at_loss=at_loss, at_settle=at_settle, payoff_loss=r2(payoff_loss), payoff_settle=r2(payoff_settle), gap_loss=r2(payoff_loss - acv), gap_settle=r2(payoff_settle - acv), loss_gap=r2(payoff_settle - payoff_loss), daily=r2(at_loss.principal * apr / d(365)), excluded_fee=excluded_fee, excluded_skipped=excluded_skipped, waiver_excludes=excluded_fee + excluded_skipped) if verbose: print("\n" + "=" * 100) print(" BHPH — retail installment contract, 91 biweekly payments, 19.90% APR, actual/365") print("=" * 100) print(f"\n order {money(order_total)} down {money(down)} amount financed {money(financed)}") print(f" payment {money(pay0)} every 14 days ({first.strftime('%A')}s), " f"first {first}, last {dues[-1]}") print(f"\n event 1 {deferred} payment 12 deferred to {after_end}, $25 fee financed") print(f" event 2 {cancel_on} service contract canceled, {in_force} of {term_days} days used") print(f" refund $1,795 × (1 − {in_force}/{term_days}) − {money(cancel_fee)} = {money(refund)}, " f"received {refund_on}") for label, e in (("no refund ", end_none), ("credited " + str(cancel_on), end_cancel), ("credited " + str(refund_on), end_receipt)): print(f" {label}: ends {e[0]} payment #{e[2]} final {money(e[1])} " f"interest {money(e[3])}") print(f" the 21-day float adds " f"{money(end_receipt[1] - end_cancel[1])} to the customer's final payment") print(f"\n event 3 {loss_on} total loss; insurer pays ACV {money(acv)} on {settle_on}") print(f" payoff at date of loss {money(payoff_loss):>12} = principal " f"{money(at_loss.principal)} + accrued {money(at_loss.accrued)}") print(f" payoff at date of payment {money(payoff_settle):>12} = principal " f"{money(at_settle.principal)} + accrued {money(at_settle.accrued)}") print(f" deficiency the waiver covers: {money(out['gap_loss'])} or " f"{money(out['gap_settle'])}; the 22 days between them are " f"{money(out['loss_gap'])} ({money(out['daily'])}/day)") show("ledger, deferral to total loss (full replay, tail shown)", at_settle, since=date(2026, 6, 19)) return out # ------------------------------------------------------------------- figure map # # The same keys the browser engine produces, formatted the same way. `check_pages.py` # asserts the two agree in every state the pages expose, and that the static HTML # carries the default state. def fmt(x: Decimal) -> str: s = f"{abs(x):,.2f}" return ("\u2212" + s) if x < 0 else s def dental_figures(conv="30/360", adjudication="service") -> dict: r = dental(verbose=False, conv=conv, adjudication=adjudication) apr, start, dues = d("0.099"), r["start"], r["dues"] charged1 = r["as_signed_rows"][0] replayed1 = [x for x in r["fwd"].rows if x.note.startswith("installment 1")][0] eob_effective = start if adjudication == "service" else r["ev_eob"] opening = r["financed"] + (r["eob_delta"] if eob_effective == start else d(0)) n, basis = day_count(start, dues[0], conv) exact = opening * apr * d(n) / basis f = { "convLabel": conv, "adjLabel": "the date of service" if adjudication == "service" else "the date it posts", "adjAlt": ("effective when the money posts" if adjudication == "service" else "effective the date of service"), "financed": fmt(r["financed"]), "pay0": fmt(r["pay0"]), "asSignedInterest": fmt(sum(x[2] for x in r["as_signed_rows"])), "accruedToEob": fmt(r["accrued_to_eob"]), "instAfterEob": fmt(r["pay1"]), "eobBalance": fmt(r["eob_pv"]), "instAfterEobFinal": fmt(r["pay1_final"]), "instAfterEobLevel": fmt(r["pay1_level"]), "accruedAtAdd": fmt(r["accrued_at_add"]), "instAfterAdd": fmt(r["pay2"]), "daysToAdd": str(day_count(dues[1], r["ev_add"], conv)[0]), "paidToDate": fmt(r["paid_total"]), "correctedShare": fmt(r["corrected_share"]), "overCollected": fmt(r["paid_total"] - r["corrected_share"]), "forkAccrued": fmt(r["fwd"].rows[-1].interest), "aInterest": fmt(r["fwd"].interest_charged), "aCredit": fmt(r["fwd"].overpaid), "aClose": str(r["fwd_closed"]), "aCloseMonth": r["fwd_closed"].strftime("%B"), "bInterest": fmt(r["ret"].interest_charged), "bCredit": fmt(r["ret"].overpaid), "bClose": str(r["ret_closed"]), "bCloseMonth": r["ret_closed"].strftime("%B"), "gap": fmt(r["ret"].overpaid - r["fwd"].overpaid), "gapInterest": fmt(r["fwd"].interest_charged - r["ret"].interest_charged), "charged1Interest": fmt(charged1[2]), "charged1Principal": fmt(charged1[4]), "charged1Balance": fmt(charged1[5]), "replayed1Interest": fmt(replayed1.to_interest), "replayed1Principal": fmt(replayed1.to_principal), "replayed1Balance": fmt(replayed1.principal), "diff1Interest": fmt(replayed1.to_interest - charged1[2]), "diff1Principal": fmt(replayed1.to_principal - charged1[4]), "diff1Balance": fmt(replayed1.principal - charged1[5]), "ruleBalance": fmt(opening), "ruleDays": str(n), "ruleBasis": str(int(basis)), "ruleExact": f"{exact:.4f}", "ruleResult": fmt(replayed1.to_interest), "ruleWhy": (f"principal ${fmt(r['financed'])} less ${fmt(-r['eob_delta'])} effective {start}" if eob_effective == start else f"principal ${fmt(r['financed'])}; the adjudication lands later, on {r['ev_eob']}"), "replayNote": ("The replay does not reverse it; it re-splits it against a principal that was $" + fmt(opening) + " all along:") if eob_effective == start else ("Under this policy the correction lands on 23 April, so nothing about " "installment 1 moves \u2014 which is the whole point of naming the date:"), } for k in range(3): row = r["as_signed_rows"][k] f[f"as{k+1}Payment"], f[f"as{k+1}Interest"] = fmt(row[1]), fmt(row[2]) f[f"as{k+1}Principal"], f[f"as{k+1}Balance"] = fmt(row[4]), fmt(row[5]) last = r["as_signed_rows"][11] f["asLastPayment"], f["asLastInterest"] = fmt(last[1]), fmt(last[2]) f["asLastPrincipal"], f["asLastBalance"] = fmt(last[4]), fmt(last[5]) return f def bhph_figures(conv="actual/365", refund_basis="days") -> dict: r = bhph(verbose=False, conv=conv, refund_basis=refund_basis) apr, sale, dues = d("0.199"), r["sale"], r["dues"] full = replay(sale, apr, conv, r["live"], through=r["settle_on"]) row = lambda note: [x for x in full.rows if x.note == note][0] p11, fee, p13, p14 = row("payment 11"), row("deferral fee, financed"), row("payment 13"), row("payment 14") no_defer = replay(sale, apr, conv, r["base"], through=dues[12]) p13_plain = no_defer.rows[-1] # A payment already collected, split twice: as it was split on the day it was taken, # with the refund not yet credited, and as it is split once the refund arrives three # weeks later and is credited as of the cancellation date. Same payment, same terms. p15_on = dues[14] no_refund = [p for p in r["live"] if not (p.kind == "principal" and p.amount == -r["refund"])] charged15 = [x for x in replay(sale, apr, conv, no_refund, through=p15_on).rows if x.on == p15_on and x.kind == "payment"][0] replayed15 = row("payment 15") f = { "convLabel": conv, "basisLabel": "elapsed days" if refund_basis == "days" else "started months", "financed": fmt(r["financed"]), "pay0": fmt(r["pay0"]), "firstDay": r["first"].strftime("%A"), "refundGross": fmt(r["refund_gross"]), "refund": fmt(r["refund"]), "refundUsed": str(r["used"]), "refundOf": str(r["of"]), "refundNoun": "days" if refund_basis == "days" else "months", "refundCalc": (f"${fmt(r['premium'])} \u00d7 (1 \u2212 {r['used']} \u00f7 {r['of']}) = " f"${fmt(r['refund_gross'])}; ${fmt(r['refund_gross'])} \u2212 " f"${fmt(r['cancel_fee'])} = ${fmt(r['refund'])}"), "feeBalance": fmt(fee.principal), "p11Balance": fmt(p11.principal), "p11Interest": fmt(p11.to_interest), "p11Principal": fmt(p11.to_principal), "feeInterest": fmt(fee.interest), "p13Interest": fmt(p13.to_interest), "p13Principal": fmt(p13.to_principal), "p13Balance": fmt(p13.principal), "p13Accrued1": fmt(fee.interest), "p13Accrued2": fmt(p13.interest), "p13Plain": fmt(p13_plain.to_principal), "charged15Interest": fmt(charged15.to_interest), "charged15Principal": fmt(charged15.to_principal), "charged15Balance": fmt(charged15.principal), "replayed15Interest": fmt(replayed15.to_interest), "replayed15Principal": fmt(replayed15.to_principal), "replayed15Balance": fmt(replayed15.principal), "diff15Interest": fmt(replayed15.to_interest - charged15.to_interest), "diff15Principal": fmt(replayed15.to_principal - charged15.to_principal), "diff15Balance": fmt(replayed15.principal - charged15.principal), "p14Interest": fmt(p14.to_interest), "p14Principal": fmt(p14.to_principal), "p14Balance": fmt(p14.principal), "endNoneDate": str(r["end_none"][0]), "endNoneNo": str(r["end_none"][2]), "endNoneFinal": fmt(r["end_none"][1]), "endNoneInterest": fmt(r["end_none"][3]), "endCancelDate": str(r["end_cancel"][0]), "endCancelNo": str(r["end_cancel"][2]), "endCancelFinal": fmt(r["end_cancel"][1]), "endCancelInterest": fmt(r["end_cancel"][3]), "endReceiptDate": str(r["end_receipt"][0]), "endReceiptNo": str(r["end_receipt"][2]), "endReceiptFinal": fmt(r["end_receipt"][1]), "endReceiptInterest": fmt(r["end_receipt"][3]), "float21": fmt(r2(r["refund"] * apr * d(21) / day_count(r["cancel_on"], r["refund_on"], conv)[1])), "floatLife": fmt(r["end_receipt"][1] - r["end_cancel"][1]), "earlyBy": str(r["end_none"][2] - r["end_cancel"][2]), "principalLoss": fmt(r["at_loss"].principal), "accruedLoss": fmt(r["at_loss"].accrued), "payoffLoss": fmt(r["payoff_loss"]), "deficiencyLoss": fmt(r["gap_loss"]), "principalSettle": fmt(r["at_settle"].principal), "accruedSettle": fmt(r["at_settle"].accrued), "payoffSettle": fmt(r["payoff_settle"]), "deficiencySettle": fmt(r["gap_settle"]), "lossGap": fmt(r["loss_gap"]), "waiverExcludedFee": fmt(r["excluded_fee"]), "waiverExcludedSkipped": fmt(r["excluded_skipped"]), "waiverExcludes": fmt(r["waiver_excludes"]), "waiverWaives": fmt(r["gap_loss"] - r["waiver_excludes"]), "remainder": fmt(r["payoff_settle"] - r["acv"] - (r["gap_loss"] - r["waiver_excludes"])), "acv": fmt(r["acv"]), "daily": fmt(r2(r["at_loss"].principal * apr / day_count(r["loss_on"], r["loss_on"] + timedelta(days=1), conv)[1])), } for k in range(3): o = r["opening"][k] f[f"op{k+1}Interest"], f[f"op{k+1}Principal"] = fmt(o[2]), fmt(o[4]) f[f"op{k+1}Balance"] = fmt(o[5]) f[f"op{k+1}Days"] = str(day_count(sale if k == 0 else dues[k-1], dues[k], conv)[0]) f["op11Interest"], f["op11Principal"] = fmt(p11.interest), fmt(p11.to_principal) f["op11Balance"], f["op11Days"] = fmt(p11.principal), str(p11.days) return f # ------------------------------------- example 3: the self-check a platform runs itself # # The two examples above are long on purpose: they follow one contract through everything # that can happen to it. This one is the opposite. It is short enough to key into another # system by hand, every date is in the past so the events can actually be posted, and the # only thing in dispute is the date one credit takes effect. A platform runs it through # its own module and sees which of the two answers comes back. def selfcheck(credited: str = "cancellation", verbose: bool = True) -> dict: """One contract, one credit, two readings of the date it takes effect. credited: cancellation (the date the contract says it takes effect) | receipt (the day the money arrived). Everything else — terms, dates, amounts — is identical. """ apr, conv = d("0.18"), "30/360" sale = date(2025, 1, 15) financed, refund, n = d(6000), d(1200), 12 cancel_on, refund_on = date(2025, 6, 1), date(2025, 7, 10) dues = [add_months(sale, i) for i in range(1, n + 1)] # monthly rate = APR / 12, which on 30/360 is also what a month accrues: the two agree # here by construction, so a difference between the columns cannot be a day-count one pay0 = annuity(financed, apr / d(12), n) effective = cancel_on if credited == "cancellation" else refund_on log = [Posting(sale, "principal", financed, "amount financed", "origination")] + \ [Posting(dt, "payment", pay0, f"payment {i + 1}", "installment") for i, dt in enumerate(dues)] + \ [Posting(effective, "principal", -refund, "service contract refund", "event")] def run_to_payoff(): """Payment holds, term moves. Returns (last date, its amount, count, interest).""" postings, pay_dates = list(log), sorted({p.on for p in log if p.kind == "payment"}) while True: for i, dt in enumerate(pay_dates): lg = replay(sale, apr, conv, postings, through=dt) if lg.principal <= 0: return dt, r2(pay0 - lg.overpaid), i + 1, lg.interest_charged, postings nxt = add_months(pay_dates[-1], 1) postings.append(Posting(nxt, "payment", pay0, "residual", "installment")) pay_dates.append(nxt) last, final, count, life, postings = run_to_payoff() def split(on: date) -> Row: lg = replay(sale, apr, conv, postings, through=on) return [r for r in lg.rows if r.on == on and r.kind == "payment"][0] checked = [dues[4], dues[5]] # the two collected inside the gap if verbose: show(f"self-check — refund credited on {effective}", replay(sale, apr, conv, postings, through=last)) return {"apr": apr, "conv": conv, "sale": sale, "financed": financed, "refund": refund, "n": n, "dues": dues, "pay0": pay0, "cancel_on": cancel_on, "refund_on": refund_on, "effective": effective, "checked": checked, "rows": [split(dt) for dt in checked], "last": last, "final": final, "count": count, "life": r2(life)} def selfcheck_figures(credited: str = "cancellation") -> dict: r = selfcheck(credited=credited, verbose=False) first, second = r["rows"] return { "financed": fmt(r["financed"]), "pay0": fmt(r["pay0"]), "refund": fmt(r["refund"]), "firstInterest": fmt(first.to_interest), "firstPrincipal": fmt(first.to_principal), "firstBalance": fmt(first.principal), "secondInterest": fmt(second.to_interest), "secondBalance": fmt(second.principal), "finalAmount": fmt(r["final"]), "lastDate": str(r["last"]), "payments": str(r["count"]), "interestLife": fmt(r["life"]), } def vectors(dn: dict, bh: dict) -> str: """Test vectors: terms in, events in, numbers out. Reproduce them or argue with them.""" return json.dumps({ "dental": { "terms": {"apr": "0.0990", "day_count": "30/360", "compounding": "none", "periods": 12, "first_due": str(dn["dues"][0]), "amount_financed": str(dn["financed"]), "installment_as_signed": str(dn["pay0"]), "on_change": "dates hold, installment moves", "allocation": "accrued interest, then principal"}, "events": [ {"on": str(dn["ev_eob"]), "type": "adjudication", "patient_share": str(dn["eob_delta"]), "effective": str(dn["start"]), "policy": "date_of_service"}, {"on": str(dn["ev_add"]), "type": "production_added", "patient_share": str(dn["add_delta"]), "effective": str(dn["ev_add"]), "policy": "date_performed"}, {"on": str(dn["ev_cancel"]), "type": "production_removed", "patient_share": str(dn["cancel_delta"]), "effective": "POLICY FORK"}, ], "expected": { "installment_after_adjudication": str(dn["pay1"]), "installment_after_addition": str(dn["pay2"]), "paid_to_date": str(dn["paid_total"]), "corrected_patient_share": str(dn["corrected_share"]), "A_effective_today": {"interest_charged": str(dn["fwd"].interest_charged), "credit_due_patient": str(dn["fwd"].overpaid)}, "B_effective_date_of_service": {"interest_charged": str(dn["ret"].interest_charged), "credit_due_patient": str(dn["ret"].overpaid)}, }, }, "bhph": { "terms": {"apr": "0.1990", "day_count": "actual/365", "compounding": "none", "payments": bh["n"], "every_days": 14, "first_due": str(bh["first"]), "amount_financed": str(bh["financed"]), "payment": str(bh["pay0"]), "on_change": "payment holds, term moves", "allocation": "accrued interest, then principal"}, "events": [ {"on": str(bh["deferred"]), "type": "payment_deferred", "fee": "25.00", "fee_financed": True, "moved_to": str(bh["after_end"])}, {"on": str(bh["cancel_on"]), "type": "service_contract_canceled", "days_in_force": bh["in_force"], "of": 730, "refund": str(bh["refund"]), "received": str(bh["refund_on"]), "effective": "POLICY FORK"}, {"on": str(bh["loss_on"]), "type": "total_loss", "acv": str(bh["acv"]), "insurer_paid": str(bh["settle_on"])}, ], "expected": { "payoff_at_date_of_loss": str(bh["payoff_loss"]), "payoff_at_date_of_insurer_payment": str(bh["payoff_settle"]), "deficiency_at_date_of_loss": str(bh["gap_loss"]), "deficiency_at_date_of_payment": str(bh["gap_settle"]), "daily_interest_at_loss": str(bh["daily"]), "ends_no_refund": {"date": str(bh["end_none"][0]), "payment_no": bh["end_none"][2], "final_payment": str(bh["end_none"][1])}, "ends_credited_at_cancellation": {"date": str(bh["end_cancel"][0]), "payment_no": bh["end_cancel"][2], "final_payment": str(bh["end_cancel"][1])}, "ends_credited_on_receipt": {"date": str(bh["end_receipt"][0]), "payment_no": bh["end_receipt"][2], "final_payment": str(bh["end_receipt"][1])}, }, }, }, indent=2) # ------------------------------------------------------------------------ spec # # The complete input for each example, written to site/*.json and linked from the # pages: the order, the terms with every convention named, the posting log, and the # expected outputs for each policy set the page exposes. The claim "you can reproduce # this" is only true if the inputs are all here, so they are. # Figures that are prose, not arithmetic: the spec publishes what has to be reproduced, # and a caption is not one of those things. Everything else goes into expected. PROSE = {"convLabel", "adjLabel", "adjAlt", "ruleWhy", "replayNote", "basisLabel", "refundNoun"} def spec_dental() -> dict: base = dental(verbose=False) states = [] for conv in ("30/360", "actual/365"): for adj in ("service", "received"): r = dental(verbose=False, conv=conv, adjudication=adj) f = dental_figures(conv=conv, adjudication=adj) states.append({ "policy": {"day_count": conv, "adjudication_effective": ("date of service (2026-03-01)" if adj == "service" else "on receipt (2026-04-23)"), "production_removed_effective": "POLICY FORK — both branches below"}, "log": [ {"on": "2026-03-01", "kind": "principal", "amount": str(r["financed"]), "note": "amount financed = patient share 4000.00 less down payment 400.00"}, {"on": "2026-03-01" if adj == "service" else "2026-04-23", "kind": "principal", "amount": str(r["eob_delta"]), "posted": "2026-04-23", "note": "adjudication: effective 'on', priced on 'posted'"}, {"on": "2026-04-01", "kind": "payment", "amount": str(r["pay0"]), "note": "installment 1"}, {"on": "2026-05-01", "kind": "payment", "amount": str(r["pay1"]), "note": "installment 2, repriced"}, {"on": "2026-05-14", "kind": "principal", "amount": str(r["add_delta"]), "note": "D4341 added, effective date performed"}, ] + [{"on": str(dt), "kind": "payment", "amount": str(r["pay2"]), "note": f"installment {i+3}"} for i, dt in enumerate(r["dues"][2:7])], "fork_on_2026-10-05": { "A_effective_today": {"effective": "2026-10-05", "amount": str(r["cancel_delta"]), "interest_charged": f["aInterest"], "credit_due_patient": f["aCredit"], "plan_closes": f["aClose"]}, "B_effective_at_origination": {"effective": "2026-03-01", "amount": str(r["cancel_delta"]), "interest_charged": f["bInterest"], "credit_due_patient": f["bCredit"], "plan_closes": f["bClose"]}, }, "expected": {k: v for k, v in f.items() if k not in PROSE}, }) return { "example": "dental — practice-financed treatment plan", "source": "https://amortance.com/dental", "note": ("Synthetic data, real mechanics. Generated from the same engine the page " "runs, not read by it: this file fixes the inputs and the expected outputs " "so the numbers can be reproduced independently. verify.py does exactly " "that and is published beside it."), "order": { "accepted": "2026-03-01", "lines": [{"code": c, "description": desc, "fee": str(fee), "estimated_benefit": str(ins), "patient_share": str(pat)} for c, desc, fee, ins, pat in base["items"]], "totals": {"fee": str(base["order_total"]), "estimated_benefit": str(base["est_ins"]), "patient_share": str(base["patient"])}, }, "terms": { "apr": "0.0990", "accrual": "simple interest on outstanding principal, no compounding", "rounding": "half up to the cent, computed per interval, at posting", "allocation": "accrued interest first, then principal", "credit_on_over_reduction": ("a reduction that takes the balance below zero settles " "any accrued interest first; what is left is a credit " "due back to the payer"), "down_payment": {"on": "2026-03-01", "amount": str(base["down"])}, "due_dates": [str(x) for x in base["dues"]], "installment_pricing": ("=PMT on the balance and accrued interest as at the date of the " "event, at the nominal periodic rate (APR x 30 / day-count basis), " "over the dates that remain; the part-period before the next " "installment is not discounted separately"), "on_change": "dates hold, installment moves", "final_installment": ("instAfterEobFinal: the last payment absorbs the residual — " "it is the principal and accrued interest still outstanding " "when it falls due, not the level installment"), "level_installment": ("instAfterEobLevel: the smallest whole cent that, paid on " "every remaining date, retires the balance without the final " "payment exceeding it"), "as_signed_schedule": ("asSignedInterest and as1..asLast are the projection made at " "origination: twelve level installments on the due dates, " "interest accrued on the day count in force"), "derivation": ("ruleBalance is the principal in force for the first interval, " "ruleDays/ruleBasis its day count, ruleExact the unrounded product " "to four places and ruleResult the same figure rounded"), "closed": "aClose/bClose: the date the balance first reaches zero", }, "states": states, } def spec_bhph() -> dict: base = bhph(verbose=False) states = [] for conv in ("actual/365", "actual/360"): for rb in ("days", "months"): r = bhph(verbose=False, conv=conv, refund_basis=rb) f = bhph_figures(conv=conv, refund_basis=rb) states.append({ "policy": {"day_count": conv, "refund_pro_rated_on": f["basisLabel"], "refund_effective": ("POLICY FORK — endNone/endCancel/endReceipt are the " "same contract with no refund, with it credited on " "the cancellation date, and with it credited when " "the money arrives. Every other figure here credits " "it on the cancellation date")}, "payments": {"first": str(r["first"]), "every_days": 14, "count": r["n"], "amount": str(r["pay0"]), "exceptions": [ {"on": str(r["deferred"]), "not_collected": True, "moved_to": str(r["after_end"]), "reason": "skip clause"}, {"after": str(r["loss_on"]), "not_collected": True, "reason": "assumption of this example: nothing collected after the loss"}, ]}, "events": [ {"on": str(r["deferred"]), "kind": "fee", "amount": "25.00", "note": "deferral fee, financed"}, {"on": str(r["cancel_on"]), "kind": "service_contract_canceled", "premium": "1795.00", "term": {"days": 730, "months": 24}, "cancellation_fee": str(r["cancel_fee"]), "received": str(r["refund_on"]), "note": f"service contract canceled, {r['used']} of {r['of']} " f"{f['refundNoun']} used, less the ${r['cancel_fee']} cancellation " f"fee; the refund is a principal reduction, " f"credited on the date the policy fork names"}, {"on": str(r["loss_on"]), "kind": "total_loss", "acv": "9850.00", "insurer_paid": str(r["settle_on"])}, ], "expected": {k: v for k, v in f.items() if k not in PROSE}, }) return { "example": "buy-here-pay-here — retail installment contract", "source": "https://amortance.com/bhph", "note": ("Synthetic data, real mechanics. Generated from the same engine the page " "runs, not read by it: this file fixes the inputs and the expected outputs " "so the numbers can be reproduced independently. verify.py does exactly " "that and is published beside it."), "deal": { "sold": "2026-01-16", "lines": [{"line": a, "detail": b, "amount": str(c)} for a, b, c in base["items"]], "cash_down": str(base["down"]), "amount_financed": str(base["financed"]), }, "terms": { "apr": "0.1990", "accrual": "simple interest on outstanding principal, no compounding", "rounding": "half up to the cent, computed per interval, at posting", "allocation": "accrued interest first, then principal", "payment_pricing": "=PMT at the nominal periodic rate (APR x 14 / day-count basis)", "on_change": "payment holds, term moves", "payoff_search": ("endNone/endCancel/endReceipt: the contract ends at the first " "scheduled date where the balance reaches zero. That last payment " "is the level payment less whatever it overpays, and if a residual " "survives the final scheduled date the schedule extends by one " "more period"), "refund_pricing": ("the gross refund is the premium times the unused fraction, " "rounded to the cent; the cancellation fee is subtracted from " "the rounded figure"), "float": ("float21 is the raw interest on the net refund over the days between " "cancellation and receipt, at the APR on the basis in force; floatLife is " "what the two credit dates do to the final payment; earlyBy is the " "difference in the number of payments"), "daily": ("daily: the principal outstanding at the loss times the APR over the " "day-count basis, rounded to the cent"), "already_collected": ("charged15/replayed15/diff15: payment 15, collected on " "2026-08-14, split as it was split that day with the refund " "not yet credited, and split again once the refund is " "credited as of the cancellation date. The contract, the " "date and the amount are the same in both"), "without_the_deferral": ("p13Plain: what installment 13 would have put to principal " "had payment 12 been collected on time and no fee financed"), "opening_schedule": ("op1..op3 are the projection made at origination; op11 is the " "eleventh payment as it actually posted"), "gap_waiver": ("waives the unpaid balance as of the date of loss, less two " "exclusions it names: any amount added to the balance after " "origination (waiverExcludedFee, the deferral fee) and any " "installment that fell due and was not collected before the loss " "(waiverExcludedSkipped, the deferred payment 12, whose new date " "falls after the loss). waiverExcludes is their sum. A waiver " "forgives debt; it does not pay"), }, "states": states, } def spec_selfcheck() -> dict: r = selfcheck(verbose=False) states = [] for credited, label in (("cancellation", "the date the contract says the refund takes effect"), ("receipt", "the day the money reached the lender")): states.append({ "policy": {"day_count": "30/360", "reading": label, "refund_credited_on": str(r["cancel_on"] if credited == "cancellation" else r["refund_on"]), "on_change": "payment holds, term moves"}, "expected": selfcheck_figures(credited=credited), }) return { "example": "self-check — one contract, one credit, two effective dates", "source": "https://amortance.com/self-check.txt", "note": ("Synthetic data, real mechanics. Short enough to key into another system by " "hand, with every date in the past so the events can be posted. The two states " "differ in one thing only: which date the refund is credited as of."), "contract": { "signed": str(r["sale"]), "amount_financed": str(r["financed"]), "apr": "0.1800", "day_count": "30/360", "payments": {"first": str(r["dues"][0]), "every": "one month, on the 15th", "count": r["n"], "amount": str(r["pay0"])}, }, "event": {"kind": "credit_effective_before_it_arrives", "refund": str(r["refund"]), "effective": str(r["cancel_on"]), "money_received": str(r["refund_on"]), "note": ("a principal reduction — a canceled service contract, an insurer " "paying above estimate — credited on the date the state names")}, "checked_payments": [str(dt) for dt in r["checked"]], "terms": { "accrual": "simple interest on outstanding principal, no compounding", "rounding": "half up to the cent, computed per interval, at posting", "allocation": "accrued interest first, then principal", "payment_pricing": "=PMT at APR / 12, which on 30/360 is also the monthly accrual", "on_change": "payment holds, term moves", "payoff_search": ("the contract ends at the first scheduled date where the balance " "reaches zero; that last payment is the level payment less " "whatever it overpays"), "checked": (f"firstInterest/firstPrincipal/firstBalance are the payment collected on " f"{r['checked'][0]}, secondInterest/secondBalance the one on " f"{r['checked'][1]}. Both fall between the two candidate dates"), }, "states": states, } SELFCHECK_TXT = """AMORTANCE — SELF-CHECK One contract, one credit, two readings of the date it takes effect. Synthetic data · every date is in the past · currency USD WHY THIS FILE Run this contract through your own module and compare eight figures. Whichever column you land in is the policy your system applies today. It takes one contract keyed in by hand — not an export — and nothing here has to be sent to anybody. The inputs and both sets of results are in self-check.json beside this file, and verify.py, a second implementation, re-derives them from it. THE CONTRACT Signed {sale}. Amount financed {financed}. APR 18.00%, simple interest on the outstanding principal, 30/360, no compounding. {n} monthly payments of {pay0} on the 15th, from {first} through {lastDue}. A payment settles accrued interest first, then principal. THE EVENT A credit of {refund} is agreed: a canceled service contract on a vehicle, an insurer paying above estimate on a treatment plan — the arithmetic is the same either way. It takes effect on {cancel_on} under the paper, and the money arrives on {refund_on}. Two payments are collected in between — {c1} and {c2} — and neither of them is reversed. The amount is not in dispute. The date it is credited as of is. THE TWO ANSWERS A — credited {cancel_on}, the date the contract names. B — credited {refund_on}, the day the money arrived. {table} Same in both: the scheduled payment, the number of payments ({aCount}), and the last one falling on {aLast} — the refund pulls the contract in by two payments either way, from {lastDue}. What differs is the split of the payments collected in the gap, and what the loan costs. HOW TO READ YOUR OWN RESULT Column A — your system credits an event on the date the paper gives it, and re-splits the payments already collected after that date. Column B — your system credits money on the day it arrives. That is the common answer and a defensible policy rather than a bug, but it should be the policy your contracts state rather than a side effect of when the check cleared. Neither — check the day count first (30/360: every month exactly 30 days) and the scheduled payment. If those two agree and the rest still does not, write to hello@amortance.com with your figures and I will say where the difference comes from. LIMITS A synthetic contract, one event, eight figures. This says which policy your system applies on this contract. It does not say how often the case arises on your book, what it costs you, or that anything you produce is an error — that is what a review of your own plans is for. Specification and both sets of results: https://amortance.com/self-check.json Independent verifier: https://amortance.com/verify.py The same figures as rows: https://amortance.com/self-check.csv """ def write_selfcheck(root: pathlib.Path) -> None: r = selfcheck(verbose=False) a, b = selfcheck_figures("cancellation"), selfcheck_figures("receipt") def line(label: str, left: str, right: str) -> str: return f"{label:<38}{left:>11}{right:>13}" table = "\n".join([ line("Check", "A", "B"), line("Scheduled payment", f'${a["pay0"]}', f'${b["pay0"]}'), line(f'Interest in the payment of {r["checked"][0]}', f'${a["firstInterest"]}', f'${b["firstInterest"]}'), line("Principal in that payment", f'${a["firstPrincipal"]}', f'${b["firstPrincipal"]}'), line("Balance after it", f'${a["firstBalance"]}', f'${b["firstBalance"]}'), line(f'Interest in the payment of {r["checked"][1]}', f'${a["secondInterest"]}', f'${b["secondInterest"]}'), line("Balance after that one", f'${a["secondBalance"]}', f'${b["secondBalance"]}'), line(f'Final payment, {a["lastDate"]}', f'${a["finalAmount"]}', f'${b["finalAmount"]}'), line("Interest over the life of the loan", f'${a["interestLife"]}', f'${b["interestLife"]}'), ]) body = SELFCHECK_TXT.format( table=table, sale=r["sale"], financed=f'${a["financed"]}', pay0=f'${a["pay0"]}', n=r["n"], first=r["dues"][0], lastDue=r["dues"][-1], refund=f'${a["refund"]}', cancel_on=r["cancel_on"], refund_on=r["refund_on"], c1=r["checked"][0], c2=r["checked"][1], aLast=a["lastDate"], aCount=a["payments"]) (root / "site2" / "self-check.txt").write_text(body) print(" site2/self-check.txt") rows = [("check", "unit", f'credited_{r["cancel_on"]}', f'credited_{r["refund_on"]}', "differs"), ("amount_financed", "USD", a["financed"], b["financed"], "no"), ("refund", "USD", a["refund"], b["refund"], "no"), ("scheduled_payment", "USD", a["pay0"], b["pay0"], "no"), (f'interest_in_payment_{r["checked"][0]}', "USD", a["firstInterest"], b["firstInterest"], "yes"), (f'principal_in_payment_{r["checked"][0]}', "USD", a["firstPrincipal"], b["firstPrincipal"], "yes"), (f'balance_after_payment_{r["checked"][0]}', "USD", a["firstBalance"], b["firstBalance"], "yes"), (f'interest_in_payment_{r["checked"][1]}', "USD", a["secondInterest"], b["secondInterest"], "yes"), (f'balance_after_payment_{r["checked"][1]}', "USD", a["secondBalance"], b["secondBalance"], "yes"), (f'final_payment_{a["lastDate"]}', "USD", a["finalAmount"], b["finalAmount"], "yes"), ("interest_over_the_life", "USD", a["interestLife"], b["interestLife"], "yes"), ("number_of_payments", "count", a["payments"], b["payments"], "no")] csv = "\n".join(",".join(str(c).replace(",", "") for c in row) for row in rows) + "\n" (root / "site2" / "self-check.csv").write_text(csv) print(" site2/self-check.csv") def write_specs() -> None: root = pathlib.Path(__file__).parent write_selfcheck(root) (root / "site2" / "self-check.json").write_text(json.dumps(spec_selfcheck(), indent=2) + "\n") print(" site2/self-check.json") for name, fn in (("dental", spec_dental), ("bhph", spec_bhph)): body = json.dumps(fn(), indent=2) + "\n" # both sites serve the same specification; writing one and copying the other by # hand is how they drift, and verify.py is only worth anything if they do not. for site in ("site", "site2"): (root / site / f"{name}.json").write_text(body) print(f" {site}/{name}.json") # The pages say the calculation core is public and runnable. It has to actually be # served, and it has to be this file rather than a copy that drifted away from it. (root / "site2" / "engine.py").write_text(pathlib.Path(__file__).read_text()) print(" site2/engine.py") # verify.py is written in site2 and served by both sites; copying it by hand is how the # two would disagree about what the published figures are. (root / "site" / "verify.py").write_text((root / "site2" / "verify.py").read_text()) print(" site/verify.py") if __name__ == "__main__": if "--spec" in sys.argv: write_specs() raise SystemExit quiet = "--json" in sys.argv dn = dental(verbose=not quiet) bh = bhph(verbose=not quiet) if quiet: print(vectors(dn, bh))