Amortance · worked example · buy-here-pay-here · the dental one is here
One deal, three events, and the dates nobody wrote down
A dealer sells a car on his own paper. Nine months in, a payment has been deferred, the service contract has been cancelled with a refund owing, and the vehicle is a total loss. Which of two dates the waiver names is worth $145.46.
Each of those is an event on the deal, not a hand adjustment to a loan. The obligation is replayed from the events, and every figure carries the rule and the inputs it came from. What the example is really about is dates: cancellation date against cheque date, loss date against settlement date. Each pair is a policy decision worth real money, and each one is usually decided by whichever line of code ran first. The data is synthetic; the mechanics are not, and the test vectors complete input — deal, terms, every posting — is published as a file, and the numbers here come from nothing else. Two of the rules are yours to switch as you read: the page recomputes in your browser, nothing is typed in and nothing leaves the page.
Terms of a contract, not properties of an engine. Switch either one and every figure on this page recomputes.
The deal
| Line | Detail | Amount |
|---|---|---|
| Vehicle | 2018 Chevrolet Equinox LT, 96,412 mi | 13,995.00 |
| Service contract | 24 months / 24,000 miles | 1,795.00 |
| GAP waiver | term of the contract | 495.00 |
| Documentary fee | 199.00 | |
| Sales tax | state and local | 874.69 |
| Title and registration | 215.00 | |
| Cash down | 16 January 2026 | −2,175.00 |
| Amount financed | 15,398.69 |
Tax and fee treatment varies by state; here they are simply lines on the order like any other. The note is sized on the $15,402 average amount financed reported for buy-here-pay-here paper (Federal Reserve, FEDS Notes, May 2026).
The terms
- 91 biweekly payments of $235.35 on Fridays, first 30 January 2026, last 13 July 2029
- 19.90% APR, simple interest on outstanding principal, no compounding
- Day count actual/365; interest is computed per interval and rounded half up to the cent before it posts
- A payment is applied to accrued interest first, then to principal
- When the balance changes: the payment holds and the term moves
Every line above is an input. The dental example runs the same engine on 30/360, monthly dates, and the opposite rule on change — there the dates hold and the instalment moves. Here the payment is the thing that has to keep fitting a paycheck, so the term absorbs everything instead.
| Due | Days | Payment | Interest | Principal | Balance |
|---|---|---|---|---|---|
| 2026-01-30 | 14 | 235.35 | 117.54 | 117.81 | 15,280.88 |
| 2026-02-13 | 14 | 235.35 | 116.64 | 118.71 | 15,162.17 |
| 2026-02-27 | 14 | 235.35 | 115.73 | 119.62 | 15,042.55 |
| … | … | … | … | … | … |
| 2026-06-19 | 14 | 235.35 | 108.23 | 127.12 | 14,052.15 |
What happened
- 3 July — payment 12 is deferred to the end of the term under the contract's skip clause. $25 fee, financed
- 7 August — the customer cancels the service contract, 203 days into 730. The administrator refunds the unearned premium to the dealer: $1,245.84, received 28 August
- 2 October — the vehicle is a total loss. The insurer pays actual cash value of $9,850.00 on 24 October; the GAP waiver covers the deficiency
Event 1 — the deferral
One payment moves to the back of the contract. The customer is not delinquent and the payment never changes — but a simple-interest note does not stop accruing because a payment did, and the engine says exactly where that lands:
| Date | Days | Posting | Amount | To interest | To principal | Balance |
|---|---|---|---|---|---|---|
| 2026-06-19 | 14 | payment 11 | 235.35 | 108.23 | 127.12 | 14,052.15 |
| 2026-07-03 | 14 | deferral fee, financed | 25.00 | — | — | 14,077.15 |
| 2026-07-17 | 14 | payment 13 | 235.35 | 214.71 | 20.64 | 14,056.51 |
| 2026-07-31 | 14 | payment 14 | 235.35 | 107.29 | 128.06 | 13,928.45 |
Rule: a payment settles accrued interest first; interest accrued on 3 July went unpaid because nothing was collected that day, so two periods are outstanding.
Inputs: $107.26 accrued 19 June → 3 July on $14,052.15, plus $107.45 accrued 3 July → 17 July on $14,077.15.
$107.26 + $107.45 = $214.71, leaving $20.64 of the payment for principal instead of the $129.07 it would have retired.
That is the honest price of the skip clause, and it is the number a collector should be able to read out loud on the phone.
Event 2 — the cancelled service contract, and the fork
The service contract comes off the deal after 203 of its 730 days. The administrator computes the unearned premium pro rata and sends it to the dealer, because on this deal the dealer is the lender:
Rule: pro rata unearned premium on elapsed days, less the administrator's cancellation fee.
Inputs: premium $1,795.00; 203 days used of 730; $50.00 cancellation fee.
$1,795.00 × (1 − 203 ÷ 730) = $1,295.84 − $50.00 = $1,245.84
The contract says refunds are applied to the account. It does not say as of when — and there are two candidate dates twenty-one days apart: the day the coverage stopped, and the day the cheque arrived.
| Not credited | Credited 7 Aug | Credited 28 Aug | |
|---|---|---|---|
| Contract ends | 2029-08-24 | 2029-04-06 | 2029-04-06 |
| Final payment number | 93 | 83 | 83 |
| Final payment | 8.59 | 169.47 | 193.45 |
| Interest over the life | 6,237.10 | 5,290.32 | 5,314.30 |
Twenty-one days of float on $1,245.84 is $14.26 of interest on the day it happens. By the end of the contract it is $23.98, because every payment after it splits differently — a knock-on the engine does not estimate, it replays. The customer's payment never changes in any column; what moves is when the paper stops earning, and that is 10 payments of difference against not crediting it at all.
Event 3 — the total loss, and which balance the waiver covers
The car is destroyed on 2 October. The last payment collected was 25 September, and this example assumes none is collected after the loss. That is an assumption of this example and nothing more: a contract that keeps collecting produces a different balance from the same log, which is the point. The insurer pays actual cash value of $9,850.00 twenty-two days later, on 24 October.
What the waiver covers has to be written down before any of this means anything, so here it is, synthetic and explicit: the unpaid balance as of the date of loss, less any amount added to the balance after origination, and less any instalment due but unpaid when the loss occurred. Published waivers say more — the Northwest Federal Credit Union addendum also carves out refunds of cancelled ancillary products and caps the benefit. Which set of exclusions is right is not the question; every one of them names a date and a base, and the ledger has to be able to produce both on demand. (NWFCU GAP waiver addendum, as a real example of the wording.)
| Principal | Accrued | Payoff | Deficiency | |
|---|---|---|---|---|
| At the date of loss, 2 Oct | 12,126.91 | 46.28 | 12,173.19 | 2,323.19 |
| At the date of payment, 24 Oct | 12,126.91 | 191.74 | 12,318.65 | 2,468.65 |
| Difference — 22 days at $6.61 a day | — | 145.46 | 145.46 | 145.46 |
Both numbers are right; they answer different questions. The waiver written above names the first, so it relieves the account of the deficiency as at the date of loss, less the $25 deferral fee that its own exclusion carves out as an amount added after origination: $2,298.19 waived. A waiver forgives debt rather than paying it — the only payment here is the insurer's $9,850.00.
Which leaves the account at $170.46:
| Owed on 24 October, when the insurer pays | 12,318.65 |
| Less actual cash value, paid by the insurer | 9,850.00 |
| Less the deficiency waived as at 2 October | 2,298.19 |
| Left standing — 145.46 of interest that accrued while the claim was in the post, and the $25 the waiver excludes | 170.46 |
Under the assumptions of this example, $170.46 remains on the borrower's account. Any further waiver or adjustment is a separate event and has to be recorded as one — which is the whole discipline. The engine's job is not to invent it: it is to produce the balance on either date, name the rule that produced it, and still be able to show that eighteen months later, to somebody who was not there.
What this example is actually about
Not the arithmetic. Interest on a declining balance is a solved problem, and any DMS that has been in this business for a decade computes it correctly.
It is about the fact that a deal keeps changing after it is signed, that every change carries two dates and at least two defensible readings, and that whichever reading ran has to still be legible when somebody asks eighteen months later. That is what an event log plus a deterministic replay buys: the answer, plus the rule that produced it, plus the ability to run the other reading and see the difference in dollars before choosing.
Check it yourself
The engine is a pure function of the terms and the event log: same inputs, same
numbers, on any machine, including for periods already past. The block below is a
summary of the state you are looking at. bhph.json is the
whole of it — the deal line by line, every convention named, the posting log, and the expected
outputs for all four policy sets these controls select. That file is generated
from the same engine this page runs; the page does not read it back, so it is a
published input, not a source of truth about itself. What makes it worth anything
is verify.py: a second implementation written from the
specification rather than shared with the engine. Save it next to the file and run
python3 verify.py; it checks whichever of the two specifications it
finds beside it, and either one on its own is enough.
{
"terms": {
"apr": "0.1990",
"day_count": "actual/365",
"compounding": "none",
"payments": 91,
"every_days": 14,
"first_due": "2026-01-30",
"amount_financed": "15,398.69",
"payment": "235.35",
"on_change": "payment holds, term moves",
"allocation": "accrued interest, then principal"
},
"events": [
{ "on": "2026-07-03", "type": "payment_deferred",
"fee": "25.00", "fee_financed": true, "moved_to": "2029-07-27" },
{ "on": "2026-08-07", "type": "service_contract_cancelled",
"pro_rata_on": "elapsed days", "used": "203", "of": "730",
"refund": "1,245.84", "received": "2026-08-28", "effective": "POLICY FORK" },
{ "on": "2026-10-02", "type": "total_loss",
"acv": "9850.00", "insurer_paid": "2026-10-24" }
],
"expected": {
"payoff_at_date_of_loss": "12,173.19",
"payoff_at_date_of_insurer_payment": "12,318.65",
"deficiency_at_date_of_loss": "2,323.19",
"deficiency_at_date_of_payment": "2,468.65",
"daily_interest_at_loss": "6.61",
"ends_not_credited": { "date": "2029-08-24", "payment_no": 93, "final": "8.59" },
"ends_credited_at_cancellation": { "date": "2029-04-06", "payment_no": 83, "final": "169.47" },
"ends_credited_on_receipt": { "date": "2029-04-06", "payment_no": 83, "final": "193.45" }
}
}
If your numbers come out differently, the disagreement is in a named rule — the day count, the allocation order, the effective date, the rounding step — and that is a conversation worth having before anyone integrates anything.
Amortance computes obligations for platforms whose merchants finance their own sales. It does not move money, hold borrower identity data, or make credit decisions. What it is · the same engine on a practice-financed treatment plan.
If you build the ledger your dealers run on: when a service contract is cancelled mid-term, which date does the credit take effect, and can the system still show that decision to a dealer eighteen months later? I would rather have the answer in writing than on a call — hello@amortance.com.