FAILURE MAP
← Case archive

FA-58656 / Loan amortization schedules / Open access

Payoff quote with per diem: penalty window · case 01

Payoffs on the last day of the penalty window escape the prepayment penalty.

Verified by executionVariant 1 · 7 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The penalty window end is exclusive.

VERIFIED REPAIR

Apply the penalty through penalty_until inclusive.

Unsuccessful approach: Testing the last paid day applies the penalty to payoffs after the window.

Case contract

x = {'balance', 'rate_bp', 'last_paid_day', 'payoff_day', 'basis', 'fees_due', 'escrow' (credit, may be negative), 'penalty_bp', 'penalty_until'}. Per diem = round_half_up(balance*bp/(10000*basis)); interest = per diem * (payoff_day - last_paid_day). Penalty = round_half_up(balance*penalty_bp/10000) when payoff_day <= penalty_until, else 0. Payoff = balance + interest + fees + penalty - escrow. Return {'per_diem', 'interest', 'penalty', 'payoff'}.

Why this case matters

Amortization engines drive borrower statements, payoff quotes and investor remittances; a misplaced rounding step, boundary or ordering rule compounds across hundreds of periods.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    def rnd(n, d):
        q, r = divmod(n, d)
        return q + (1 if 2 * r >= d else 0)
    per_diem = rnd(x['balance'] * x['rate_bp'], 10000 * x['basis'])
    days = x['payoff_day'] - x['last_paid_day']
    interest = per_diem * days
    penalty = rnd(x['balance'] * x['penalty_bp'], 10000) if x['payoff_day'] < x['penalty_until'] else 0
    payoff = x['balance'] + interest + x['fees_due'] + penalty - x['escrow']
    return {'per_diem': per_diem, 'interest': interest, 'penalty': penalty, 'payoff': payoff}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: penalty window', {'balance': 999999, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 115, 'basis': 360, 'fees_due': 0, 'escrow': -4000, 'penalty_bp': 200, 'penalty_until': 115}, {'per_diem': 347, 'interest': 5205, 'penalty': 20000, 'payoff': 1029204}], ['regression: penalty window, partial-repair probe', {'balance': 999999, 'rate_bp': 600, 'last_paid_day': 10, 'payoff_day': 11, 'basis': 365, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 100, 'penalty_until': 10}, {'per_diem': 164, 'interest': 164, 'penalty': 0, 'payoff': 1000163}], ['control 1', {'balance': 100000, 'rate_bp': 600, 'last_paid_day': 100, 'payoff_day': 145, 'basis': 360, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 0, 'penalty_until': 115}, {'per_diem': 17, 'interest': 765, 'penalty': 0, 'payoff': 108265}], ['control 2', {'balance': 100000, 'rate_bp': 1250, 'last_paid_day': 1, 'payoff_day': 16, 'basis': 360, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 31}, {'per_diem': 35, 'interest': 525, 'penalty': 1000, 'payoff': 93025}], ['control 3', {'balance': 12345678, 'rate_bp': 600, 'last_paid_day': 10, 'payoff_day': 41, 'basis': 360, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 200, 'penalty_until': 40}, {'per_diem': 2058, 'interest': 63798, 'penalty': 0, 'payoff': 12400976}], ['control 4', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 10, 'payoff_day': 55, 'basis': 360, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 100, 'penalty_until': 25}, {'per_diem': 1543, 'interest': 69435, 'penalty': 0, 'payoff': 12415113}], ['control 5', {'balance': 5000, 'rate_bp': 1250, 'last_paid_day': 10, 'payoff_day': 41, 'basis': 360, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 0, 'penalty_until': 25}, {'per_diem': 2, 'interest': 62, 'penalty': 0, 'payoff': -6938}]], [['regression: penalty window', {'balance': 12345678, 'rate_bp': 600, 'last_paid_day': 100, 'payoff_day': 130, 'basis': 360, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 200, 'penalty_until': 130}, {'per_diem': 2058, 'interest': 61740, 'penalty': 246914, 'payoff': 12661832}], ['regression: penalty window, partial-repair probe', {'balance': 999999, 'rate_bp': 1250, 'last_paid_day': 1, 'payoff_day': 46, 'basis': 365, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 100, 'penalty_until': 1}, {'per_diem': 342, 'interest': 15390, 'penalty': 0, 'payoff': 1022889}], ['control 1', {'balance': 100000, 'rate_bp': 450, 'last_paid_day': 1, 'payoff_day': 2, 'basis': 360, 'fees_due': 3500, 'escrow': 0, 'penalty_bp': 200, 'penalty_until': 61}, {'per_diem': 13, 'interest': 13, 'penalty': 2000, 'payoff': 105513}], ['control 2', {'balance': 100000, 'rate_bp': 1250, 'last_paid_day': 10, 'payoff_day': 25, 'basis': 365, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 100, 'penalty_until': 10}, {'per_diem': 34, 'interest': 510, 'penalty': 0, 'payoff': 100510}], ['control 3', {'balance': 999999, 'rate_bp': 450, 'last_paid_day': 1, 'payoff_day': 31, 'basis': 360, 'fees_due': 3500, 'escrow': 0, 'penalty_bp': 0, 'penalty_until': 61}, {'per_diem': 125, 'interest': 3750, 'penalty': 0, 'payoff': 1007249}], ['control 4', {'balance': 12345678, 'rate_bp': 1250, 'last_paid_day': 10, 'payoff_day': 11, 'basis': 365, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 0, 'penalty_until': 40}, {'per_diem': 4228, 'interest': 4228, 'penalty': 0, 'payoff': 12337906}], ['control 5', {'balance': 100000, 'rate_bp': 450, 'last_paid_day': 100, 'payoff_day': 101, 'basis': 365, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 200, 'penalty_until': 130}, {'per_diem': 12, 'interest': 12, 'penalty': 2000, 'payoff': 90012}]], [['regression: penalty window', {'balance': 12345678, 'rate_bp': 600, 'last_paid_day': 1, 'payoff_day': 31, 'basis': 360, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 200, 'penalty_until': 31}, {'per_diem': 2058, 'interest': 61740, 'penalty': 246914, 'payoff': 12654332}], ['regression: penalty window, partial-repair probe', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 1, 'payoff_day': 31, 'basis': 360, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 16}, {'per_diem': 1543, 'interest': 46290, 'penalty': 0, 'payoff': 12383468}], ['control 1', {'balance': 5000, 'rate_bp': 450, 'last_paid_day': 10, 'payoff_day': 55, 'basis': 365, 'fees_due': 0, 'escrow': -4000, 'penalty_bp': 0, 'penalty_until': 40}, {'per_diem': 1, 'interest': 45, 'penalty': 0, 'payoff': 9045}], ['control 2', {'balance': 100000, 'rate_bp': 1250, 'last_paid_day': 1, 'payoff_day': 46, 'basis': 360, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 0, 'penalty_until': 31}, {'per_diem': 35, 'interest': 1575, 'penalty': 0, 'payoff': 89575}], ['control 3', {'balance': 999999, 'rate_bp': 1250, 'last_paid_day': 10, 'payoff_day': 25, 'basis': 365, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 0, 'penalty_until': 40}, {'per_diem': 342, 'interest': 5130, 'penalty': 0, 'payoff': 1005129}], ['control 4', {'balance': 100000, 'rate_bp': 1250, 'last_paid_day': 1, 'payoff_day': 2, 'basis': 365, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 1}, {'per_diem': 34, 'interest': 34, 'penalty': 0, 'payoff': 91534}], ['control 5', {'balance': 100000, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 130, 'basis': 360, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 100, 'penalty_until': 115}, {'per_diem': 35, 'interest': 1050, 'penalty': 0, 'payoff': 108550}]], [['regression: penalty window', {'balance': 5000, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 130, 'basis': 360, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 200, 'penalty_until': 130}, {'per_diem': 2, 'interest': 60, 'penalty': 100, 'payoff': 5160}], ['regression: penalty window, partial-repair probe', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 1, 'payoff_day': 32, 'basis': 365, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 100, 'penalty_until': 1}, {'per_diem': 1522, 'interest': 47182, 'penalty': 0, 'payoff': 12400360}], ['control 1', {'balance': 5000, 'rate_bp': 600, 'last_paid_day': 10, 'payoff_day': 40, 'basis': 365, 'fees_due': 3500, 'escrow': 0, 'penalty_bp': 200, 'penalty_until': 70}, {'per_diem': 1, 'interest': 30, 'penalty': 100, 'payoff': 8630}], ['control 2', {'balance': 5000, 'rate_bp': 1250, 'last_paid_day': 1, 'payoff_day': 46, 'basis': 360, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 16}, {'per_diem': 2, 'interest': 90, 'penalty': 0, 'payoff': -6910}], ['control 3', {'balance': 5000, 'rate_bp': 600, 'last_paid_day': 100, 'payoff_day': 130, 'basis': 365, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 200, 'penalty_until': 100}, {'per_diem': 1, 'interest': 30, 'penalty': 0, 'payoff': 12530}], ['control 4', {'balance': 999999, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 115, 'basis': 360, 'fees_due': 0, 'escrow': -4000, 'penalty_bp': 200, 'penalty_until': 130}, {'per_diem': 347, 'interest': 5205, 'penalty': 20000, 'payoff': 1029204}], ['control 5', {'balance': 5000, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 115, 'basis': 365, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 160}, {'per_diem': 2, 'interest': 30, 'penalty': 50, 'payoff': -3420}]], [['regression: penalty window', {'balance': 12345678, 'rate_bp': 1250, 'last_paid_day': 10, 'payoff_day': 40, 'basis': 365, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 40}, {'per_diem': 4228, 'interest': 126840, 'penalty': 123457, 'payoff': 12587475}], ['regression: penalty window, partial-repair probe', {'balance': 999999, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 131, 'basis': 360, 'fees_due': 3500, 'escrow': 0, 'penalty_bp': 100, 'penalty_until': 115}, {'per_diem': 347, 'interest': 10757, 'penalty': 0, 'payoff': 1014256}], ['control 1', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 100, 'payoff_day': 115, 'basis': 360, 'fees_due': 3500, 'escrow': 0, 'penalty_bp': 100, 'penalty_until': 160}, {'per_diem': 1543, 'interest': 23145, 'penalty': 123457, 'payoff': 12495780}], ['control 2', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 100, 'payoff_day': 101, 'basis': 365, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 100, 'penalty_until': 130}, {'per_diem': 1522, 'interest': 1522, 'penalty': 123457, 'payoff': 12478157}], ['control 3', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 100, 'payoff_day': 130, 'basis': 365, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 0, 'penalty_until': 130}, {'per_diem': 1522, 'interest': 45660, 'penalty': 0, 'payoff': 12379338}], ['control 4', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 1, 'payoff_day': 31, 'basis': 360, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 200, 'penalty_until': 1}, {'per_diem': 1543, 'interest': 46290, 'penalty': 0, 'payoff': 12399468}], ['control 5', {'balance': 999999, 'rate_bp': 600, 'last_paid_day': 10, 'payoff_day': 40, 'basis': 360, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 0, 'penalty_until': 70}, {'per_diem': 167, 'interest': 5010, 'penalty': 0, 'payoff': 1005009}]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: penalty window{'interest': 5205, 'payoff': 1009204, 'penalty': 0, 'per_diem': 347}{'interest': 5205, 'payoff': 1029204, 'penalty': 20000, 'per_diem': 347}Failed
regression: penalty window, partial-repair probe{'interest': 164, 'payoff': 1000163, 'penalty': 0, 'per_diem': 164}{'interest': 164, 'payoff': 1000163, 'penalty': 0, 'per_diem': 164}Passed
control 1{'interest': 765, 'payoff': 108265, 'penalty': 0, 'per_diem': 17}{'interest': 765, 'payoff': 108265, 'penalty': 0, 'per_diem': 17}Passed
control 2{'interest': 525, 'payoff': 93025, 'penalty': 1000, 'per_diem': 35}{'interest': 525, 'payoff': 93025, 'penalty': 1000, 'per_diem': 35}Passed
control 3{'interest': 63798, 'payoff': 12400976, 'penalty': 0, 'per_diem': 2058}{'interest': 63798, 'payoff': 12400976, 'penalty': 0, 'per_diem': 2058}Passed
control 4{'interest': 69435, 'payoff': 12415113, 'penalty': 0, 'per_diem': 1543}{'interest': 69435, 'payoff': 12415113, 'penalty': 0, 'per_diem': 1543}Passed
control 5{'interest': 62, 'payoff': -6938, 'penalty': 0, 'per_diem': 2}{'interest': 62, 'payoff': -6938, 'penalty': 0, 'per_diem': 2}Passed

SHA-256 / 6c4be0235374e3e218a4d0d722442ea10ac636a11c9fb327a96e03f2f448d70b

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    def rnd(n, d):
        q, r = divmod(n, d)
        return q + (1 if 2 * r >= d else 0)
    per_diem = rnd(x['balance'] * x['rate_bp'], 10000 * x['basis'])
    days = x['payoff_day'] - x['last_paid_day']
    interest = per_diem * days
    penalty = rnd(x['balance'] * x['penalty_bp'], 10000) if x['last_paid_day'] <= x['penalty_until'] else 0
    payoff = x['balance'] + interest + x['fees_due'] + penalty - x['escrow']
    return {'per_diem': per_diem, 'interest': interest, 'penalty': penalty, 'payoff': payoff}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: penalty window', {'balance': 999999, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 115, 'basis': 360, 'fees_due': 0, 'escrow': -4000, 'penalty_bp': 200, 'penalty_until': 115}, {'per_diem': 347, 'interest': 5205, 'penalty': 20000, 'payoff': 1029204}], ['regression: penalty window, partial-repair probe', {'balance': 999999, 'rate_bp': 600, 'last_paid_day': 10, 'payoff_day': 11, 'basis': 365, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 100, 'penalty_until': 10}, {'per_diem': 164, 'interest': 164, 'penalty': 0, 'payoff': 1000163}], ['control 1', {'balance': 100000, 'rate_bp': 600, 'last_paid_day': 100, 'payoff_day': 145, 'basis': 360, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 0, 'penalty_until': 115}, {'per_diem': 17, 'interest': 765, 'penalty': 0, 'payoff': 108265}], ['control 2', {'balance': 100000, 'rate_bp': 1250, 'last_paid_day': 1, 'payoff_day': 16, 'basis': 360, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 31}, {'per_diem': 35, 'interest': 525, 'penalty': 1000, 'payoff': 93025}], ['control 3', {'balance': 12345678, 'rate_bp': 600, 'last_paid_day': 10, 'payoff_day': 41, 'basis': 360, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 200, 'penalty_until': 40}, {'per_diem': 2058, 'interest': 63798, 'penalty': 0, 'payoff': 12400976}], ['control 4', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 10, 'payoff_day': 55, 'basis': 360, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 100, 'penalty_until': 25}, {'per_diem': 1543, 'interest': 69435, 'penalty': 0, 'payoff': 12415113}], ['control 5', {'balance': 5000, 'rate_bp': 1250, 'last_paid_day': 10, 'payoff_day': 41, 'basis': 360, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 0, 'penalty_until': 25}, {'per_diem': 2, 'interest': 62, 'penalty': 0, 'payoff': -6938}]], [['regression: penalty window', {'balance': 12345678, 'rate_bp': 600, 'last_paid_day': 100, 'payoff_day': 130, 'basis': 360, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 200, 'penalty_until': 130}, {'per_diem': 2058, 'interest': 61740, 'penalty': 246914, 'payoff': 12661832}], ['regression: penalty window, partial-repair probe', {'balance': 999999, 'rate_bp': 1250, 'last_paid_day': 1, 'payoff_day': 46, 'basis': 365, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 100, 'penalty_until': 1}, {'per_diem': 342, 'interest': 15390, 'penalty': 0, 'payoff': 1022889}], ['control 1', {'balance': 100000, 'rate_bp': 450, 'last_paid_day': 1, 'payoff_day': 2, 'basis': 360, 'fees_due': 3500, 'escrow': 0, 'penalty_bp': 200, 'penalty_until': 61}, {'per_diem': 13, 'interest': 13, 'penalty': 2000, 'payoff': 105513}], ['control 2', {'balance': 100000, 'rate_bp': 1250, 'last_paid_day': 10, 'payoff_day': 25, 'basis': 365, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 100, 'penalty_until': 10}, {'per_diem': 34, 'interest': 510, 'penalty': 0, 'payoff': 100510}], ['control 3', {'balance': 999999, 'rate_bp': 450, 'last_paid_day': 1, 'payoff_day': 31, 'basis': 360, 'fees_due': 3500, 'escrow': 0, 'penalty_bp': 0, 'penalty_until': 61}, {'per_diem': 125, 'interest': 3750, 'penalty': 0, 'payoff': 1007249}], ['control 4', {'balance': 12345678, 'rate_bp': 1250, 'last_paid_day': 10, 'payoff_day': 11, 'basis': 365, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 0, 'penalty_until': 40}, {'per_diem': 4228, 'interest': 4228, 'penalty': 0, 'payoff': 12337906}], ['control 5', {'balance': 100000, 'rate_bp': 450, 'last_paid_day': 100, 'payoff_day': 101, 'basis': 365, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 200, 'penalty_until': 130}, {'per_diem': 12, 'interest': 12, 'penalty': 2000, 'payoff': 90012}]], [['regression: penalty window', {'balance': 12345678, 'rate_bp': 600, 'last_paid_day': 1, 'payoff_day': 31, 'basis': 360, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 200, 'penalty_until': 31}, {'per_diem': 2058, 'interest': 61740, 'penalty': 246914, 'payoff': 12654332}], ['regression: penalty window, partial-repair probe', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 1, 'payoff_day': 31, 'basis': 360, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 16}, {'per_diem': 1543, 'interest': 46290, 'penalty': 0, 'payoff': 12383468}], ['control 1', {'balance': 5000, 'rate_bp': 450, 'last_paid_day': 10, 'payoff_day': 55, 'basis': 365, 'fees_due': 0, 'escrow': -4000, 'penalty_bp': 0, 'penalty_until': 40}, {'per_diem': 1, 'interest': 45, 'penalty': 0, 'payoff': 9045}], ['control 2', {'balance': 100000, 'rate_bp': 1250, 'last_paid_day': 1, 'payoff_day': 46, 'basis': 360, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 0, 'penalty_until': 31}, {'per_diem': 35, 'interest': 1575, 'penalty': 0, 'payoff': 89575}], ['control 3', {'balance': 999999, 'rate_bp': 1250, 'last_paid_day': 10, 'payoff_day': 25, 'basis': 365, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 0, 'penalty_until': 40}, {'per_diem': 342, 'interest': 5130, 'penalty': 0, 'payoff': 1005129}], ['control 4', {'balance': 100000, 'rate_bp': 1250, 'last_paid_day': 1, 'payoff_day': 2, 'basis': 365, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 1}, {'per_diem': 34, 'interest': 34, 'penalty': 0, 'payoff': 91534}], ['control 5', {'balance': 100000, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 130, 'basis': 360, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 100, 'penalty_until': 115}, {'per_diem': 35, 'interest': 1050, 'penalty': 0, 'payoff': 108550}]], [['regression: penalty window', {'balance': 5000, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 130, 'basis': 360, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 200, 'penalty_until': 130}, {'per_diem': 2, 'interest': 60, 'penalty': 100, 'payoff': 5160}], ['regression: penalty window, partial-repair probe', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 1, 'payoff_day': 32, 'basis': 365, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 100, 'penalty_until': 1}, {'per_diem': 1522, 'interest': 47182, 'penalty': 0, 'payoff': 12400360}], ['control 1', {'balance': 5000, 'rate_bp': 600, 'last_paid_day': 10, 'payoff_day': 40, 'basis': 365, 'fees_due': 3500, 'escrow': 0, 'penalty_bp': 200, 'penalty_until': 70}, {'per_diem': 1, 'interest': 30, 'penalty': 100, 'payoff': 8630}], ['control 2', {'balance': 5000, 'rate_bp': 1250, 'last_paid_day': 1, 'payoff_day': 46, 'basis': 360, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 16}, {'per_diem': 2, 'interest': 90, 'penalty': 0, 'payoff': -6910}], ['control 3', {'balance': 5000, 'rate_bp': 600, 'last_paid_day': 100, 'payoff_day': 130, 'basis': 365, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 200, 'penalty_until': 100}, {'per_diem': 1, 'interest': 30, 'penalty': 0, 'payoff': 12530}], ['control 4', {'balance': 999999, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 115, 'basis': 360, 'fees_due': 0, 'escrow': -4000, 'penalty_bp': 200, 'penalty_until': 130}, {'per_diem': 347, 'interest': 5205, 'penalty': 20000, 'payoff': 1029204}], ['control 5', {'balance': 5000, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 115, 'basis': 365, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 160}, {'per_diem': 2, 'interest': 30, 'penalty': 50, 'payoff': -3420}]], [['regression: penalty window', {'balance': 12345678, 'rate_bp': 1250, 'last_paid_day': 10, 'payoff_day': 40, 'basis': 365, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 40}, {'per_diem': 4228, 'interest': 126840, 'penalty': 123457, 'payoff': 12587475}], ['regression: penalty window, partial-repair probe', {'balance': 999999, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 131, 'basis': 360, 'fees_due': 3500, 'escrow': 0, 'penalty_bp': 100, 'penalty_until': 115}, {'per_diem': 347, 'interest': 10757, 'penalty': 0, 'payoff': 1014256}], ['control 1', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 100, 'payoff_day': 115, 'basis': 360, 'fees_due': 3500, 'escrow': 0, 'penalty_bp': 100, 'penalty_until': 160}, {'per_diem': 1543, 'interest': 23145, 'penalty': 123457, 'payoff': 12495780}], ['control 2', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 100, 'payoff_day': 101, 'basis': 365, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 100, 'penalty_until': 130}, {'per_diem': 1522, 'interest': 1522, 'penalty': 123457, 'payoff': 12478157}], ['control 3', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 100, 'payoff_day': 130, 'basis': 365, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 0, 'penalty_until': 130}, {'per_diem': 1522, 'interest': 45660, 'penalty': 0, 'payoff': 12379338}], ['control 4', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 1, 'payoff_day': 31, 'basis': 360, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 200, 'penalty_until': 1}, {'per_diem': 1543, 'interest': 46290, 'penalty': 0, 'payoff': 12399468}], ['control 5', {'balance': 999999, 'rate_bp': 600, 'last_paid_day': 10, 'payoff_day': 40, 'basis': 360, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 0, 'penalty_until': 70}, {'per_diem': 167, 'interest': 5010, 'penalty': 0, 'payoff': 1005009}]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: penalty window{'interest': 5205, 'payoff': 1029204, 'penalty': 20000, 'per_diem': 347}{'interest': 5205, 'payoff': 1029204, 'penalty': 20000, 'per_diem': 347}Passed
regression: penalty window, partial-repair probe{'interest': 164, 'payoff': 1010163, 'penalty': 10000, 'per_diem': 164}{'interest': 164, 'payoff': 1000163, 'penalty': 0, 'per_diem': 164}Failed
control 1{'interest': 765, 'payoff': 108265, 'penalty': 0, 'per_diem': 17}{'interest': 765, 'payoff': 108265, 'penalty': 0, 'per_diem': 17}Passed
control 2{'interest': 525, 'payoff': 93025, 'penalty': 1000, 'per_diem': 35}{'interest': 525, 'payoff': 93025, 'penalty': 1000, 'per_diem': 35}Passed
control 3{'interest': 63798, 'payoff': 12647890, 'penalty': 246914, 'per_diem': 2058}{'interest': 63798, 'payoff': 12400976, 'penalty': 0, 'per_diem': 2058}Failed
control 4{'interest': 69435, 'payoff': 12538570, 'penalty': 123457, 'per_diem': 1543}{'interest': 69435, 'payoff': 12415113, 'penalty': 0, 'per_diem': 1543}Failed
control 5{'interest': 62, 'payoff': -6938, 'penalty': 0, 'per_diem': 2}{'interest': 62, 'payoff': -6938, 'penalty': 0, 'per_diem': 2}Passed

SHA-256 / 784c89f4b754a50438111bfeeb117b6688b800a976b6033df756c02abea03c8c

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    def rnd(n, d):
        q, r = divmod(n, d)
        return q + (1 if 2 * r >= d else 0)
    per_diem = rnd(x['balance'] * x['rate_bp'], 10000 * x['basis'])
    days = x['payoff_day'] - x['last_paid_day']
    interest = per_diem * days
    penalty = rnd(x['balance'] * x['penalty_bp'], 10000) if x['payoff_day'] <= x['penalty_until'] else 0
    payoff = x['balance'] + interest + x['fees_due'] + penalty - x['escrow']
    return {'per_diem': per_diem, 'interest': interest, 'penalty': penalty, 'payoff': payoff}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: penalty window', {'balance': 999999, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 115, 'basis': 360, 'fees_due': 0, 'escrow': -4000, 'penalty_bp': 200, 'penalty_until': 115}, {'per_diem': 347, 'interest': 5205, 'penalty': 20000, 'payoff': 1029204}], ['regression: penalty window, partial-repair probe', {'balance': 999999, 'rate_bp': 600, 'last_paid_day': 10, 'payoff_day': 11, 'basis': 365, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 100, 'penalty_until': 10}, {'per_diem': 164, 'interest': 164, 'penalty': 0, 'payoff': 1000163}], ['control 1', {'balance': 100000, 'rate_bp': 600, 'last_paid_day': 100, 'payoff_day': 145, 'basis': 360, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 0, 'penalty_until': 115}, {'per_diem': 17, 'interest': 765, 'penalty': 0, 'payoff': 108265}], ['control 2', {'balance': 100000, 'rate_bp': 1250, 'last_paid_day': 1, 'payoff_day': 16, 'basis': 360, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 31}, {'per_diem': 35, 'interest': 525, 'penalty': 1000, 'payoff': 93025}], ['control 3', {'balance': 12345678, 'rate_bp': 600, 'last_paid_day': 10, 'payoff_day': 41, 'basis': 360, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 200, 'penalty_until': 40}, {'per_diem': 2058, 'interest': 63798, 'penalty': 0, 'payoff': 12400976}], ['control 4', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 10, 'payoff_day': 55, 'basis': 360, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 100, 'penalty_until': 25}, {'per_diem': 1543, 'interest': 69435, 'penalty': 0, 'payoff': 12415113}], ['control 5', {'balance': 5000, 'rate_bp': 1250, 'last_paid_day': 10, 'payoff_day': 41, 'basis': 360, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 0, 'penalty_until': 25}, {'per_diem': 2, 'interest': 62, 'penalty': 0, 'payoff': -6938}]], [['regression: penalty window', {'balance': 12345678, 'rate_bp': 600, 'last_paid_day': 100, 'payoff_day': 130, 'basis': 360, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 200, 'penalty_until': 130}, {'per_diem': 2058, 'interest': 61740, 'penalty': 246914, 'payoff': 12661832}], ['regression: penalty window, partial-repair probe', {'balance': 999999, 'rate_bp': 1250, 'last_paid_day': 1, 'payoff_day': 46, 'basis': 365, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 100, 'penalty_until': 1}, {'per_diem': 342, 'interest': 15390, 'penalty': 0, 'payoff': 1022889}], ['control 1', {'balance': 100000, 'rate_bp': 450, 'last_paid_day': 1, 'payoff_day': 2, 'basis': 360, 'fees_due': 3500, 'escrow': 0, 'penalty_bp': 200, 'penalty_until': 61}, {'per_diem': 13, 'interest': 13, 'penalty': 2000, 'payoff': 105513}], ['control 2', {'balance': 100000, 'rate_bp': 1250, 'last_paid_day': 10, 'payoff_day': 25, 'basis': 365, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 100, 'penalty_until': 10}, {'per_diem': 34, 'interest': 510, 'penalty': 0, 'payoff': 100510}], ['control 3', {'balance': 999999, 'rate_bp': 450, 'last_paid_day': 1, 'payoff_day': 31, 'basis': 360, 'fees_due': 3500, 'escrow': 0, 'penalty_bp': 0, 'penalty_until': 61}, {'per_diem': 125, 'interest': 3750, 'penalty': 0, 'payoff': 1007249}], ['control 4', {'balance': 12345678, 'rate_bp': 1250, 'last_paid_day': 10, 'payoff_day': 11, 'basis': 365, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 0, 'penalty_until': 40}, {'per_diem': 4228, 'interest': 4228, 'penalty': 0, 'payoff': 12337906}], ['control 5', {'balance': 100000, 'rate_bp': 450, 'last_paid_day': 100, 'payoff_day': 101, 'basis': 365, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 200, 'penalty_until': 130}, {'per_diem': 12, 'interest': 12, 'penalty': 2000, 'payoff': 90012}]], [['regression: penalty window', {'balance': 12345678, 'rate_bp': 600, 'last_paid_day': 1, 'payoff_day': 31, 'basis': 360, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 200, 'penalty_until': 31}, {'per_diem': 2058, 'interest': 61740, 'penalty': 246914, 'payoff': 12654332}], ['regression: penalty window, partial-repair probe', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 1, 'payoff_day': 31, 'basis': 360, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 16}, {'per_diem': 1543, 'interest': 46290, 'penalty': 0, 'payoff': 12383468}], ['control 1', {'balance': 5000, 'rate_bp': 450, 'last_paid_day': 10, 'payoff_day': 55, 'basis': 365, 'fees_due': 0, 'escrow': -4000, 'penalty_bp': 0, 'penalty_until': 40}, {'per_diem': 1, 'interest': 45, 'penalty': 0, 'payoff': 9045}], ['control 2', {'balance': 100000, 'rate_bp': 1250, 'last_paid_day': 1, 'payoff_day': 46, 'basis': 360, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 0, 'penalty_until': 31}, {'per_diem': 35, 'interest': 1575, 'penalty': 0, 'payoff': 89575}], ['control 3', {'balance': 999999, 'rate_bp': 1250, 'last_paid_day': 10, 'payoff_day': 25, 'basis': 365, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 0, 'penalty_until': 40}, {'per_diem': 342, 'interest': 5130, 'penalty': 0, 'payoff': 1005129}], ['control 4', {'balance': 100000, 'rate_bp': 1250, 'last_paid_day': 1, 'payoff_day': 2, 'basis': 365, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 1}, {'per_diem': 34, 'interest': 34, 'penalty': 0, 'payoff': 91534}], ['control 5', {'balance': 100000, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 130, 'basis': 360, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 100, 'penalty_until': 115}, {'per_diem': 35, 'interest': 1050, 'penalty': 0, 'payoff': 108550}]], [['regression: penalty window', {'balance': 5000, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 130, 'basis': 360, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 200, 'penalty_until': 130}, {'per_diem': 2, 'interest': 60, 'penalty': 100, 'payoff': 5160}], ['regression: penalty window, partial-repair probe', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 1, 'payoff_day': 32, 'basis': 365, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 100, 'penalty_until': 1}, {'per_diem': 1522, 'interest': 47182, 'penalty': 0, 'payoff': 12400360}], ['control 1', {'balance': 5000, 'rate_bp': 600, 'last_paid_day': 10, 'payoff_day': 40, 'basis': 365, 'fees_due': 3500, 'escrow': 0, 'penalty_bp': 200, 'penalty_until': 70}, {'per_diem': 1, 'interest': 30, 'penalty': 100, 'payoff': 8630}], ['control 2', {'balance': 5000, 'rate_bp': 1250, 'last_paid_day': 1, 'payoff_day': 46, 'basis': 360, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 16}, {'per_diem': 2, 'interest': 90, 'penalty': 0, 'payoff': -6910}], ['control 3', {'balance': 5000, 'rate_bp': 600, 'last_paid_day': 100, 'payoff_day': 130, 'basis': 365, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 200, 'penalty_until': 100}, {'per_diem': 1, 'interest': 30, 'penalty': 0, 'payoff': 12530}], ['control 4', {'balance': 999999, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 115, 'basis': 360, 'fees_due': 0, 'escrow': -4000, 'penalty_bp': 200, 'penalty_until': 130}, {'per_diem': 347, 'interest': 5205, 'penalty': 20000, 'payoff': 1029204}], ['control 5', {'balance': 5000, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 115, 'basis': 365, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 160}, {'per_diem': 2, 'interest': 30, 'penalty': 50, 'payoff': -3420}]], [['regression: penalty window', {'balance': 12345678, 'rate_bp': 1250, 'last_paid_day': 10, 'payoff_day': 40, 'basis': 365, 'fees_due': 3500, 'escrow': 12000, 'penalty_bp': 100, 'penalty_until': 40}, {'per_diem': 4228, 'interest': 126840, 'penalty': 123457, 'payoff': 12587475}], ['regression: penalty window, partial-repair probe', {'balance': 999999, 'rate_bp': 1250, 'last_paid_day': 100, 'payoff_day': 131, 'basis': 360, 'fees_due': 3500, 'escrow': 0, 'penalty_bp': 100, 'penalty_until': 115}, {'per_diem': 347, 'interest': 10757, 'penalty': 0, 'payoff': 1014256}], ['control 1', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 100, 'payoff_day': 115, 'basis': 360, 'fees_due': 3500, 'escrow': 0, 'penalty_bp': 100, 'penalty_until': 160}, {'per_diem': 1543, 'interest': 23145, 'penalty': 123457, 'payoff': 12495780}], ['control 2', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 100, 'payoff_day': 101, 'basis': 365, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 100, 'penalty_until': 130}, {'per_diem': 1522, 'interest': 1522, 'penalty': 123457, 'payoff': 12478157}], ['control 3', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 100, 'payoff_day': 130, 'basis': 365, 'fees_due': 0, 'escrow': 12000, 'penalty_bp': 0, 'penalty_until': 130}, {'per_diem': 1522, 'interest': 45660, 'penalty': 0, 'payoff': 12379338}], ['control 4', {'balance': 12345678, 'rate_bp': 450, 'last_paid_day': 1, 'payoff_day': 31, 'basis': 360, 'fees_due': 3500, 'escrow': -4000, 'penalty_bp': 200, 'penalty_until': 1}, {'per_diem': 1543, 'interest': 46290, 'penalty': 0, 'payoff': 12399468}], ['control 5', {'balance': 999999, 'rate_bp': 600, 'last_paid_day': 10, 'payoff_day': 40, 'basis': 360, 'fees_due': 0, 'escrow': 0, 'penalty_bp': 0, 'penalty_until': 70}, {'per_diem': 167, 'interest': 5010, 'penalty': 0, 'payoff': 1005009}]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: penalty window{'interest': 5205, 'payoff': 1029204, 'penalty': 20000, 'per_diem': 347}{'interest': 5205, 'payoff': 1029204, 'penalty': 20000, 'per_diem': 347}Passed
regression: penalty window, partial-repair probe{'interest': 164, 'payoff': 1000163, 'penalty': 0, 'per_diem': 164}{'interest': 164, 'payoff': 1000163, 'penalty': 0, 'per_diem': 164}Passed
control 1{'interest': 765, 'payoff': 108265, 'penalty': 0, 'per_diem': 17}{'interest': 765, 'payoff': 108265, 'penalty': 0, 'per_diem': 17}Passed
control 2{'interest': 525, 'payoff': 93025, 'penalty': 1000, 'per_diem': 35}{'interest': 525, 'payoff': 93025, 'penalty': 1000, 'per_diem': 35}Passed
control 3{'interest': 63798, 'payoff': 12400976, 'penalty': 0, 'per_diem': 2058}{'interest': 63798, 'payoff': 12400976, 'penalty': 0, 'per_diem': 2058}Passed
control 4{'interest': 69435, 'payoff': 12415113, 'penalty': 0, 'per_diem': 1543}{'interest': 69435, 'payoff': 12415113, 'penalty': 0, 'per_diem': 1543}Passed
control 5{'interest': 62, 'payoff': -6938, 'penalty': 0, 'per_diem': 2}{'interest': 62, 'payoff': -6938, 'penalty': 0, 'per_diem': 2}Passed

SHA-256 / 2dcaff10c8f6c17b0fc9ad6e52d3deb9440d7c5d836273d6b7633cd8779ded9d

Verification & scope

A deterministic bounded teaching model with stipulated toy lending rules stated in the contract; money is integer cents and rates are basis points; it makes no claim of conformance to any regulation, servicing standard or product. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:46:28.827855+00:00.

Case digest / f53182e958999cd004ef2db4f386072b82fb21d58ae3ca92ad6c59409c4ee8a8