FA-58383 / Loan amortization schedules / Member archive
Schedule rows from a fixed payment: final principal clamp · case 03
The last schedule row drives the balance negative.
Case contract
x = {'principal', 'rate_bp', 'payment', 'max_months'}. For months 1..max_months while the balance is positive: interest = round_half_up(balance*bp/120000); if payment <= interest return {'error': 'negative_amortization', 'month': k}; principal paid = min(payment - interest, balance); append [k, interest, principal, balance after]. Return {'rows', 'balloon': remaining principal}.
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.
One recorded failure
Sample boundary fixtureThis sample comes from the broken implementation of a controlled reproducer.
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: final principal clamp | {"balloon": -71383, "rows": [[1, 500, 4500, 45500], [2, 455, 4545, 40955], [3, 410, 4590, 36365], [4, 364, 4636, 31729], [5, 317, 4683, 27046], [6, 270, 4730, 22316], [7, 223, 4777, 17539], [8, 175, 4825, 12714], [9, 127, 4873, 7841], [10, 78, 4922, 2919], [11, 29, 4971, -2052], [12, -21, 5021, -7073], [13, -71, 5071, -12144], [14, -121, 5121, -17265], [15, -173, 5173, -22438], [16, -224, 5224, -27662], [17, -277, 5277, -32939], [18, -329, 5329, -38268], [19, -383, 5383, -43651], [20, -437, 5437, -49088], [21, -491, 5491, -54579], [22, -546, 5546, -60125], [23, -601, 5601, -65726], [24, -657, 5657, -71383]]} | {"balloon": 0, "rows": [[1, 500, 4500, 45500], [2, 455, 4545, 40955], [3, 410, 4590, 36365], [4, 364, 4636, 31729], [5, 317, 4683, 27046], [6, 270, 4730, 22316], [7, 223, 4777, 17539], [8, 175, 4825, 12714], [9, 127, 4873, 7841], [10, 78, 4922, 2919], [11, 29, 2919, 0]]} | Failed |
MEMBER ARCHIVE
The complete case is available to members.
This record includes three runnable implementations, regression fixtures, execution results, and source hashes.
Member access is invitation-based. Sign in with your invited account to inspect the sources.
Sign in to the archive ↗