{"abstract":"The recast is detected a month after the balance crosses the cap.","category":"Loan amortization schedules","checks":7,"contract":"x = {'principal', 'rate_bp', 'min_payment', 'cap_pct_bp' (e.g. 11000 = 110% of principal), 'months'}. Each month interest = round_half_up(balance*bp/120000); the shortfall interest - payment (if positive) is deferred; balance += interest - payment. The first time balance*10000 exceeds principal*cap_pct_bp the loan recasts once: payment = level(balance, months - k) (exact annuity, half-up). Return {'balance', 'recast_month' or None, 'deferred', 'payment'}.","evaluation_group":"w2-loan-amortization-schedules-negative-amortization-recast","failed_approach":"Testing the projected balance but switching payment in the same month applies the new payment one month early.","family":"w2-loan-amortization-schedules-negative-amortization-recast-cap-check-timing","id":"FA-58606","implementations":{"attempt":{"sha256":"853decd0532111960a340758e14034564bb3fba4b79c7c06fa9942ff0ed23aa8","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nfrom fractions import Fraction\nN = 1\nobservations = []\ndef solve(x):\n    def rnd(n, d):\n        q, r = divmod(n, d)\n        return q + (1 if 2 * r >= d else 0)\n    def level(P, n):\n        if n <= 0 or P <= 0:\n            return 0\n        if bp == 0:\n            exact = Fraction(P, n)\n        else:\n            r = Fraction(bp, 120000)\n            exact = P * r / (1 - (1 + r) ** -n)\n        return math.floor(exact + Fraction(1, 2))\n    bp = x['rate_bp']\n    P = x['principal']\n    n = x['months']\n    bal = P\n    pay = x['min_payment']\n    deferred = 0\n    recast = None\n    limit = P * x['cap_pct_bp']\n    for k in range(1, n + 1):\n        interest = rnd(bal * bp, 120000)\n        if pay < interest:\n            deferred += interest - pay\n        if recast is None and (bal + interest - pay) * 10000 > limit:\n            recast = k\n            pay = level(bal + interest - pay, n - k)\n        bal += interest - pay\n    return {'balance': bal, 'recast_month': recast, 'deferred': deferred, 'payment': pay}\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['regression: cap check timing', {'principal': 1000000, 'rate_bp': 1200, 'min_payment': 5000, 'cap_pct_bp': 10500, 'months': 12}, {'balance': 1, 'recast_month': 10, 'deferred': 52312, 'payment': 534061}], ['control 1', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 10000, 'cap_pct_bp': 11000, 'months': 6}, {'balance': 1063081, 'recast_month': None, 'deferred': 63081, 'payment': 10000}], ['control 2', {'principal': 1000000, 'rate_bp': 1200, 'min_payment': 10000, 'cap_pct_bp': 10200, 'months': 12}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 10000}], ['control 3', {'principal': 200000, 'rate_bp': 2400, 'min_payment': 4000, 'cap_pct_bp': 10100, 'months': 36}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 4', {'principal': 1000000, 'rate_bp': 600, 'min_payment': 5000, 'cap_pct_bp': 10500, 'months': 12}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 5000}], ['control 5', {'principal': 200000, 'rate_bp': 1200, 'min_payment': 4000, 'cap_pct_bp': 11000, 'months': 36}, {'balance': 113849, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 6', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 20000, 'cap_pct_bp': 10100, 'months': 36}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 20000}]], [['regression: cap check timing', {'principal': 200000, 'rate_bp': 2400, 'min_payment': 2000, 'cap_pct_bp': 10100, 'months': 12}, {'balance': 0, 'recast_month': 2, 'deferred': 4040, 'payment': 22715}], ['control 1', {'principal': 100000, 'rate_bp': 600, 'min_payment': 500, 'cap_pct_bp': 10100, 'months': 36}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 500}], ['control 2', {'principal': 200000, 'rate_bp': 600, 'min_payment': 1000, 'cap_pct_bp': 11000, 'months': 12}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 1000}], ['control 3', {'principal': 100000, 'rate_bp': 2400, 'min_payment': 2000, 'cap_pct_bp': 11000, 'months': 36}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 2000}], ['control 4', {'principal': 200000, 'rate_bp': 600, 'min_payment': 1000, 'cap_pct_bp': 10200, 'months': 36}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 1000}], ['control 5', {'principal': 100000, 'rate_bp': 2400, 'min_payment': 2000, 'cap_pct_bp': 10100, 'months': 6}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 2000}], ['control 6', {'principal': 100000, 'rate_bp': 600, 'min_payment': 1000, 'cap_pct_bp': 11000, 'months': 6}, {'balance': 96962, 'recast_month': None, 'deferred': 0, 'payment': 1000}]], [['regression: cap check timing', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 10000, 'cap_pct_bp': 10100, 'months': 12}, {'balance': 4, 'recast_month': 2, 'deferred': 20200, 'payment': 113575}], ['control 1', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 20000, 'cap_pct_bp': 11000, 'months': 36}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 20000}], ['control 2', {'principal': 200000, 'rate_bp': 600, 'min_payment': 500, 'cap_pct_bp': 10200, 'months': 6}, {'balance': 203039, 'recast_month': None, 'deferred': 3039, 'payment': 500}], ['control 3', {'principal': 1000000, 'rate_bp': 600, 'min_payment': 2500, 'cap_pct_bp': 11000, 'months': 6}, {'balance': 1015189, 'recast_month': None, 'deferred': 15189, 'payment': 2500}], ['control 4', {'principal': 1000000, 'rate_bp': 600, 'min_payment': 20000, 'cap_pct_bp': 10200, 'months': 24}, {'balance': 618521, 'recast_month': None, 'deferred': 0, 'payment': 20000}], ['control 5', {'principal': 100000, 'rate_bp': 600, 'min_payment': 2000, 'cap_pct_bp': 11000, 'months': 6}, {'balance': 90887, 'recast_month': None, 'deferred': 0, 'payment': 2000}], ['control 6', {'principal': 200000, 'rate_bp': 1200, 'min_payment': 4000, 'cap_pct_bp': 11000, 'months': 12}, {'balance': 174636, 'recast_month': None, 'deferred': 0, 'payment': 4000}]], [['regression: cap check timing', {'principal': 200000, 'rate_bp': 2400, 'min_payment': 500, 'cap_pct_bp': 11000, 'months': 6}, {'balance': 222078, 'recast_month': 6, 'deferred': 22078, 'payment': 0}], ['control 1', {'principal': 200000, 'rate_bp': 1200, 'min_payment': 4000, 'cap_pct_bp': 10100, 'months': 6}, {'balance': 187696, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 2', {'principal': 200000, 'rate_bp': 2400, 'min_payment': 4000, 'cap_pct_bp': 10200, 'months': 12}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 3', {'principal': 100000, 'rate_bp': 2400, 'min_payment': 2000, 'cap_pct_bp': 10100, 'months': 12}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 2000}], ['control 4', {'principal': 1000000, 'rate_bp': 1200, 'min_payment': 10000, 'cap_pct_bp': 10200, 'months': 6}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 10000}], ['control 5', {'principal': 200000, 'rate_bp': 1200, 'min_payment': 4000, 'cap_pct_bp': 10100, 'months': 36}, {'balance': 113849, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 6', {'principal': 200000, 'rate_bp': 600, 'min_payment': 4000, 'cap_pct_bp': 10200, 'months': 24}, {'balance': 123705, 'recast_month': None, 'deferred': 0, 'payment': 4000}]], [['regression: cap check timing', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 10000, 'cap_pct_bp': 11000, 'months': 12}, {'balance': 1, 'recast_month': 10, 'deferred': 109498, 'payment': 571446}], ['control 1', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 20000, 'cap_pct_bp': 11000, 'months': 36}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 20000}], ['control 2', {'principal': 100000, 'rate_bp': 2400, 'min_payment': 2000, 'cap_pct_bp': 10100, 'months': 24}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 2000}], ['control 3', {'principal': 200000, 'rate_bp': 600, 'min_payment': 500, 'cap_pct_bp': 10200, 'months': 6}, {'balance': 203039, 'recast_month': None, 'deferred': 3039, 'payment': 500}], ['control 4', {'principal': 200000, 'rate_bp': 2400, 'min_payment': 4000, 'cap_pct_bp': 10200, 'months': 24}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 5', {'principal': 100000, 'rate_bp': 1200, 'min_payment': 1000, 'cap_pct_bp': 10500, 'months': 6}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 1000}], ['control 6', {'principal': 200000, 'rate_bp': 600, 'min_payment': 1000, 'cap_pct_bp': 11000, 'months': 24}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 1000}]]]\nfor label, args, expected in fixtures[N-1]:\n    try:\n        actual = solve(args)\n    except Exception as exc:\n        actual = 'raised ' + type(exc).__name__\n    check(label, actual, expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"153df6052026e904b7f09b8517a03babf8a3a3d3818398c961fbcfca90297e76","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nfrom fractions import Fraction\nN = 1\nobservations = []\ndef solve(x):\n    def rnd(n, d):\n        q, r = divmod(n, d)\n        return q + (1 if 2 * r >= d else 0)\n    def level(P, n):\n        if n <= 0 or P <= 0:\n            return 0\n        if bp == 0:\n            exact = Fraction(P, n)\n        else:\n            r = Fraction(bp, 120000)\n            exact = P * r / (1 - (1 + r) ** -n)\n        return math.floor(exact + Fraction(1, 2))\n    bp = x['rate_bp']\n    P = x['principal']\n    n = x['months']\n    bal = P\n    pay = x['min_payment']\n    deferred = 0\n    recast = None\n    limit = P * x['cap_pct_bp']\n    for k in range(1, n + 1):\n        interest = rnd(bal * bp, 120000)\n        if pay < interest:\n            deferred += interest - pay\n        if recast is None and bal * 10000 > limit:\n            recast = k\n            pay = level(bal, n - k)\n        bal += interest - pay\n    return {'balance': bal, 'recast_month': recast, 'deferred': deferred, 'payment': pay}\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['regression: cap check timing', {'principal': 1000000, 'rate_bp': 1200, 'min_payment': 5000, 'cap_pct_bp': 10500, 'months': 12}, {'balance': 1, 'recast_month': 10, 'deferred': 52312, 'payment': 534061}], ['control 1', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 10000, 'cap_pct_bp': 11000, 'months': 6}, {'balance': 1063081, 'recast_month': None, 'deferred': 63081, 'payment': 10000}], ['control 2', {'principal': 1000000, 'rate_bp': 1200, 'min_payment': 10000, 'cap_pct_bp': 10200, 'months': 12}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 10000}], ['control 3', {'principal': 200000, 'rate_bp': 2400, 'min_payment': 4000, 'cap_pct_bp': 10100, 'months': 36}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 4', {'principal': 1000000, 'rate_bp': 600, 'min_payment': 5000, 'cap_pct_bp': 10500, 'months': 12}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 5000}], ['control 5', {'principal': 200000, 'rate_bp': 1200, 'min_payment': 4000, 'cap_pct_bp': 11000, 'months': 36}, {'balance': 113849, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 6', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 20000, 'cap_pct_bp': 10100, 'months': 36}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 20000}]], [['regression: cap check timing', {'principal': 200000, 'rate_bp': 2400, 'min_payment': 2000, 'cap_pct_bp': 10100, 'months': 12}, {'balance': 0, 'recast_month': 2, 'deferred': 4040, 'payment': 22715}], ['control 1', {'principal': 100000, 'rate_bp': 600, 'min_payment': 500, 'cap_pct_bp': 10100, 'months': 36}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 500}], ['control 2', {'principal': 200000, 'rate_bp': 600, 'min_payment': 1000, 'cap_pct_bp': 11000, 'months': 12}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 1000}], ['control 3', {'principal': 100000, 'rate_bp': 2400, 'min_payment': 2000, 'cap_pct_bp': 11000, 'months': 36}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 2000}], ['control 4', {'principal': 200000, 'rate_bp': 600, 'min_payment': 1000, 'cap_pct_bp': 10200, 'months': 36}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 1000}], ['control 5', {'principal': 100000, 'rate_bp': 2400, 'min_payment': 2000, 'cap_pct_bp': 10100, 'months': 6}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 2000}], ['control 6', {'principal': 100000, 'rate_bp': 600, 'min_payment': 1000, 'cap_pct_bp': 11000, 'months': 6}, {'balance': 96962, 'recast_month': None, 'deferred': 0, 'payment': 1000}]], [['regression: cap check timing', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 10000, 'cap_pct_bp': 10100, 'months': 12}, {'balance': 4, 'recast_month': 2, 'deferred': 20200, 'payment': 113575}], ['control 1', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 20000, 'cap_pct_bp': 11000, 'months': 36}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 20000}], ['control 2', {'principal': 200000, 'rate_bp': 600, 'min_payment': 500, 'cap_pct_bp': 10200, 'months': 6}, {'balance': 203039, 'recast_month': None, 'deferred': 3039, 'payment': 500}], ['control 3', {'principal': 1000000, 'rate_bp': 600, 'min_payment': 2500, 'cap_pct_bp': 11000, 'months': 6}, {'balance': 1015189, 'recast_month': None, 'deferred': 15189, 'payment': 2500}], ['control 4', {'principal': 1000000, 'rate_bp': 600, 'min_payment': 20000, 'cap_pct_bp': 10200, 'months': 24}, {'balance': 618521, 'recast_month': None, 'deferred': 0, 'payment': 20000}], ['control 5', {'principal': 100000, 'rate_bp': 600, 'min_payment': 2000, 'cap_pct_bp': 11000, 'months': 6}, {'balance': 90887, 'recast_month': None, 'deferred': 0, 'payment': 2000}], ['control 6', {'principal': 200000, 'rate_bp': 1200, 'min_payment': 4000, 'cap_pct_bp': 11000, 'months': 12}, {'balance': 174636, 'recast_month': None, 'deferred': 0, 'payment': 4000}]], [['regression: cap check timing', {'principal': 200000, 'rate_bp': 2400, 'min_payment': 500, 'cap_pct_bp': 11000, 'months': 6}, {'balance': 222078, 'recast_month': 6, 'deferred': 22078, 'payment': 0}], ['control 1', {'principal': 200000, 'rate_bp': 1200, 'min_payment': 4000, 'cap_pct_bp': 10100, 'months': 6}, {'balance': 187696, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 2', {'principal': 200000, 'rate_bp': 2400, 'min_payment': 4000, 'cap_pct_bp': 10200, 'months': 12}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 3', {'principal': 100000, 'rate_bp': 2400, 'min_payment': 2000, 'cap_pct_bp': 10100, 'months': 12}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 2000}], ['control 4', {'principal': 1000000, 'rate_bp': 1200, 'min_payment': 10000, 'cap_pct_bp': 10200, 'months': 6}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 10000}], ['control 5', {'principal': 200000, 'rate_bp': 1200, 'min_payment': 4000, 'cap_pct_bp': 10100, 'months': 36}, {'balance': 113849, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 6', {'principal': 200000, 'rate_bp': 600, 'min_payment': 4000, 'cap_pct_bp': 10200, 'months': 24}, {'balance': 123705, 'recast_month': None, 'deferred': 0, 'payment': 4000}]], [['regression: cap check timing', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 10000, 'cap_pct_bp': 11000, 'months': 12}, {'balance': 1, 'recast_month': 10, 'deferred': 109498, 'payment': 571446}], ['control 1', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 20000, 'cap_pct_bp': 11000, 'months': 36}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 20000}], ['control 2', {'principal': 100000, 'rate_bp': 2400, 'min_payment': 2000, 'cap_pct_bp': 10100, 'months': 24}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 2000}], ['control 3', {'principal': 200000, 'rate_bp': 600, 'min_payment': 500, 'cap_pct_bp': 10200, 'months': 6}, {'balance': 203039, 'recast_month': None, 'deferred': 3039, 'payment': 500}], ['control 4', {'principal': 200000, 'rate_bp': 2400, 'min_payment': 4000, 'cap_pct_bp': 10200, 'months': 24}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 5', {'principal': 100000, 'rate_bp': 1200, 'min_payment': 1000, 'cap_pct_bp': 10500, 'months': 6}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 1000}], ['control 6', {'principal': 200000, 'rate_bp': 600, 'min_payment': 1000, 'cap_pct_bp': 11000, 'months': 24}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 1000}]]]\nfor label, args, expected in fixtures[N-1]:\n    try:\n        actual = solve(args)\n    except Exception as exc:\n        actual = 'raised ' + type(exc).__name__\n    check(label, actual, expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"511ea368434d767ed96b7520aca3d83ab970bf2df782b870fa58d953a0fb9fe2","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nfrom fractions import Fraction\nN = 1\nobservations = []\ndef solve(x):\n    def rnd(n, d):\n        q, r = divmod(n, d)\n        return q + (1 if 2 * r >= d else 0)\n    def level(P, n):\n        if n <= 0 or P <= 0:\n            return 0\n        if bp == 0:\n            exact = Fraction(P, n)\n        else:\n            r = Fraction(bp, 120000)\n            exact = P * r / (1 - (1 + r) ** -n)\n        return math.floor(exact + Fraction(1, 2))\n    bp = x['rate_bp']\n    P = x['principal']\n    n = x['months']\n    bal = P\n    pay = x['min_payment']\n    deferred = 0\n    recast = None\n    limit = P * x['cap_pct_bp']\n    for k in range(1, n + 1):\n        interest = rnd(bal * bp, 120000)\n        if pay < interest:\n            deferred += interest - pay\n        bal += interest - pay\n        if recast is None and bal * 10000 > limit:\n            recast = k\n            pay = level(bal, n - k)\n    return {'balance': bal, 'recast_month': recast, 'deferred': deferred, 'payment': pay}\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['regression: cap check timing', {'principal': 1000000, 'rate_bp': 1200, 'min_payment': 5000, 'cap_pct_bp': 10500, 'months': 12}, {'balance': 1, 'recast_month': 10, 'deferred': 52312, 'payment': 534061}], ['control 1', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 10000, 'cap_pct_bp': 11000, 'months': 6}, {'balance': 1063081, 'recast_month': None, 'deferred': 63081, 'payment': 10000}], ['control 2', {'principal': 1000000, 'rate_bp': 1200, 'min_payment': 10000, 'cap_pct_bp': 10200, 'months': 12}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 10000}], ['control 3', {'principal': 200000, 'rate_bp': 2400, 'min_payment': 4000, 'cap_pct_bp': 10100, 'months': 36}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 4', {'principal': 1000000, 'rate_bp': 600, 'min_payment': 5000, 'cap_pct_bp': 10500, 'months': 12}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 5000}], ['control 5', {'principal': 200000, 'rate_bp': 1200, 'min_payment': 4000, 'cap_pct_bp': 11000, 'months': 36}, {'balance': 113849, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 6', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 20000, 'cap_pct_bp': 10100, 'months': 36}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 20000}]], [['regression: cap check timing', {'principal': 200000, 'rate_bp': 2400, 'min_payment': 2000, 'cap_pct_bp': 10100, 'months': 12}, {'balance': 0, 'recast_month': 2, 'deferred': 4040, 'payment': 22715}], ['control 1', {'principal': 100000, 'rate_bp': 600, 'min_payment': 500, 'cap_pct_bp': 10100, 'months': 36}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 500}], ['control 2', {'principal': 200000, 'rate_bp': 600, 'min_payment': 1000, 'cap_pct_bp': 11000, 'months': 12}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 1000}], ['control 3', {'principal': 100000, 'rate_bp': 2400, 'min_payment': 2000, 'cap_pct_bp': 11000, 'months': 36}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 2000}], ['control 4', {'principal': 200000, 'rate_bp': 600, 'min_payment': 1000, 'cap_pct_bp': 10200, 'months': 36}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 1000}], ['control 5', {'principal': 100000, 'rate_bp': 2400, 'min_payment': 2000, 'cap_pct_bp': 10100, 'months': 6}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 2000}], ['control 6', {'principal': 100000, 'rate_bp': 600, 'min_payment': 1000, 'cap_pct_bp': 11000, 'months': 6}, {'balance': 96962, 'recast_month': None, 'deferred': 0, 'payment': 1000}]], [['regression: cap check timing', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 10000, 'cap_pct_bp': 10100, 'months': 12}, {'balance': 4, 'recast_month': 2, 'deferred': 20200, 'payment': 113575}], ['control 1', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 20000, 'cap_pct_bp': 11000, 'months': 36}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 20000}], ['control 2', {'principal': 200000, 'rate_bp': 600, 'min_payment': 500, 'cap_pct_bp': 10200, 'months': 6}, {'balance': 203039, 'recast_month': None, 'deferred': 3039, 'payment': 500}], ['control 3', {'principal': 1000000, 'rate_bp': 600, 'min_payment': 2500, 'cap_pct_bp': 11000, 'months': 6}, {'balance': 1015189, 'recast_month': None, 'deferred': 15189, 'payment': 2500}], ['control 4', {'principal': 1000000, 'rate_bp': 600, 'min_payment': 20000, 'cap_pct_bp': 10200, 'months': 24}, {'balance': 618521, 'recast_month': None, 'deferred': 0, 'payment': 20000}], ['control 5', {'principal': 100000, 'rate_bp': 600, 'min_payment': 2000, 'cap_pct_bp': 11000, 'months': 6}, {'balance': 90887, 'recast_month': None, 'deferred': 0, 'payment': 2000}], ['control 6', {'principal': 200000, 'rate_bp': 1200, 'min_payment': 4000, 'cap_pct_bp': 11000, 'months': 12}, {'balance': 174636, 'recast_month': None, 'deferred': 0, 'payment': 4000}]], [['regression: cap check timing', {'principal': 200000, 'rate_bp': 2400, 'min_payment': 500, 'cap_pct_bp': 11000, 'months': 6}, {'balance': 222078, 'recast_month': 6, 'deferred': 22078, 'payment': 0}], ['control 1', {'principal': 200000, 'rate_bp': 1200, 'min_payment': 4000, 'cap_pct_bp': 10100, 'months': 6}, {'balance': 187696, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 2', {'principal': 200000, 'rate_bp': 2400, 'min_payment': 4000, 'cap_pct_bp': 10200, 'months': 12}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 3', {'principal': 100000, 'rate_bp': 2400, 'min_payment': 2000, 'cap_pct_bp': 10100, 'months': 12}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 2000}], ['control 4', {'principal': 1000000, 'rate_bp': 1200, 'min_payment': 10000, 'cap_pct_bp': 10200, 'months': 6}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 10000}], ['control 5', {'principal': 200000, 'rate_bp': 1200, 'min_payment': 4000, 'cap_pct_bp': 10100, 'months': 36}, {'balance': 113849, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 6', {'principal': 200000, 'rate_bp': 600, 'min_payment': 4000, 'cap_pct_bp': 10200, 'months': 24}, {'balance': 123705, 'recast_month': None, 'deferred': 0, 'payment': 4000}]], [['regression: cap check timing', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 10000, 'cap_pct_bp': 11000, 'months': 12}, {'balance': 1, 'recast_month': 10, 'deferred': 109498, 'payment': 571446}], ['control 1', {'principal': 1000000, 'rate_bp': 2400, 'min_payment': 20000, 'cap_pct_bp': 11000, 'months': 36}, {'balance': 1000000, 'recast_month': None, 'deferred': 0, 'payment': 20000}], ['control 2', {'principal': 100000, 'rate_bp': 2400, 'min_payment': 2000, 'cap_pct_bp': 10100, 'months': 24}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 2000}], ['control 3', {'principal': 200000, 'rate_bp': 600, 'min_payment': 500, 'cap_pct_bp': 10200, 'months': 6}, {'balance': 203039, 'recast_month': None, 'deferred': 3039, 'payment': 500}], ['control 4', {'principal': 200000, 'rate_bp': 2400, 'min_payment': 4000, 'cap_pct_bp': 10200, 'months': 24}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 4000}], ['control 5', {'principal': 100000, 'rate_bp': 1200, 'min_payment': 1000, 'cap_pct_bp': 10500, 'months': 6}, {'balance': 100000, 'recast_month': None, 'deferred': 0, 'payment': 1000}], ['control 6', {'principal': 200000, 'rate_bp': 600, 'min_payment': 1000, 'cap_pct_bp': 11000, 'months': 24}, {'balance': 200000, 'recast_month': None, 'deferred': 0, 'payment': 1000}]]]\nfor label, args, expected in fixtures[N-1]:\n    try:\n        actual = solve(args)\n    except Exception as exc:\n        actual = 'raised ' + type(exc).__name__\n    check(label, actual, expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"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.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-loan-amortization-schedules-negative-amortization-recast-cap-check-timing","generated_at":"2026-09-29T14:46:28.205339+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Amortization engines drive borrower statements, payoff quotes and investor remittances; a misplaced rounding step, boundary or ordering rule compounds across hundreds of periods.","repair":"Capitalize the month first, then test the cap and recast for the following months.","root_cause":"The cap test runs before the month interest is capitalized.","sha256":"791558b5185b2af0bcfd3c59ebddbd0dd9305fb8424935085af94e5ec2f53705","title":"Negative amortization cap recast: cap check timing · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":43.414,"exit_code":1,"observations":[{"actual":{"balance":-539694,"deferred":52312,"payment":534061,"recast_month":10},"check":"regression: cap check timing","expected":{"balance":1,"deferred":52312,"payment":534061,"recast_month":10},"passed":false},{"actual":{"balance":1063081,"deferred":63081,"payment":10000,"recast_month":null},"check":"control 1","expected":{"balance":1063081,"deferred":63081,"payment":10000,"recast_month":null},"passed":true},{"actual":{"balance":1000000,"deferred":0,"payment":10000,"recast_month":null},"check":"control 2","expected":{"balance":1000000,"deferred":0,"payment":10000,"recast_month":null},"passed":true},{"actual":{"balance":200000,"deferred":0,"payment":4000,"recast_month":null},"check":"control 3","expected":{"balance":200000,"deferred":0,"payment":4000,"recast_month":null},"passed":true},{"actual":{"balance":1000000,"deferred":0,"payment":5000,"recast_month":null},"check":"control 4","expected":{"balance":1000000,"deferred":0,"payment":5000,"recast_month":null},"passed":true},{"actual":{"balance":113849,"deferred":0,"payment":4000,"recast_month":null},"check":"control 5","expected":{"balance":113849,"deferred":0,"payment":4000,"recast_month":null},"passed":true},{"actual":{"balance":1000000,"deferred":0,"payment":20000,"recast_month":null},"check":"control 6","expected":{"balance":1000000,"deferred":0,"payment":20000,"recast_month":null},"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: cap check timing\", \"actual\": {\"balance\": -539694, \"recast_month\": 10, \"deferred\": 52312, \"payment\": 534061}, \"expected\": {\"balance\": 1, \"recast_month\": 10, \"deferred\": 52312, \"payment\": 534061}, \"passed\": false}, {\"check\": \"control 1\", \"actual\": {\"balance\": 1063081, \"recast_month\": null, \"deferred\": 63081, \"payment\": 10000}, \"expected\": {\"balance\": 1063081, \"recast_month\": null, \"deferred\": 63081, \"payment\": 10000}, \"passed\": true}, {\"check\": \"control 2\", \"actual\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 10000}, \"expected\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 10000}, \"passed\": true}, {\"check\": \"control 3\", \"actual\": {\"balance\": 200000, \"recast_month\": null, \"deferred\": 0, \"payment\": 4000}, \"expected\": {\"balance\": 200000, \"recast_month\": null, \"deferred\": 0, \"payment\": 4000}, \"passed\": true}, {\"check\": \"control 4\", \"actual\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 5000}, \"expected\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 5000}, \"passed\": true}, {\"check\": \"control 5\", \"actual\": {\"balance\": 113849, \"recast_month\": null, \"deferred\": 0, \"payment\": 4000}, \"expected\": {\"balance\": 113849, \"recast_month\": null, \"deferred\": 0, \"payment\": 4000}, \"passed\": true}, {\"check\": \"control 6\", \"actual\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 20000}, \"expected\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 20000}, \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":42.447,"exit_code":1,"observations":[{"actual":{"balance":-1062835,"deferred":57835,"payment":1062835,"recast_month":11},"check":"regression: cap check timing","expected":{"balance":1,"deferred":52312,"payment":534061,"recast_month":10},"passed":false},{"actual":{"balance":1063081,"deferred":63081,"payment":10000,"recast_month":null},"check":"control 1","expected":{"balance":1063081,"deferred":63081,"payment":10000,"recast_month":null},"passed":true},{"actual":{"balance":1000000,"deferred":0,"payment":10000,"recast_month":null},"check":"control 2","expected":{"balance":1000000,"deferred":0,"payment":10000,"recast_month":null},"passed":true},{"actual":{"balance":200000,"deferred":0,"payment":4000,"recast_month":null},"check":"control 3","expected":{"balance":200000,"deferred":0,"payment":4000,"recast_month":null},"passed":true},{"actual":{"balance":1000000,"deferred":0,"payment":5000,"recast_month":null},"check":"control 4","expected":{"balance":1000000,"deferred":0,"payment":5000,"recast_month":null},"passed":true},{"actual":{"balance":113849,"deferred":0,"payment":4000,"recast_month":null},"check":"control 5","expected":{"balance":113849,"deferred":0,"payment":4000,"recast_month":null},"passed":true},{"actual":{"balance":1000000,"deferred":0,"payment":20000,"recast_month":null},"check":"control 6","expected":{"balance":1000000,"deferred":0,"payment":20000,"recast_month":null},"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: cap check timing\", \"actual\": {\"balance\": -1062835, \"recast_month\": 11, \"deferred\": 57835, \"payment\": 1062835}, \"expected\": {\"balance\": 1, \"recast_month\": 10, \"deferred\": 52312, \"payment\": 534061}, \"passed\": false}, {\"check\": \"control 1\", \"actual\": {\"balance\": 1063081, \"recast_month\": null, \"deferred\": 63081, \"payment\": 10000}, \"expected\": {\"balance\": 1063081, \"recast_month\": null, \"deferred\": 63081, \"payment\": 10000}, \"passed\": true}, {\"check\": \"control 2\", \"actual\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 10000}, \"expected\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 10000}, \"passed\": true}, {\"check\": \"control 3\", \"actual\": {\"balance\": 200000, \"recast_month\": null, \"deferred\": 0, \"payment\": 4000}, \"expected\": {\"balance\": 200000, \"recast_month\": null, \"deferred\": 0, \"payment\": 4000}, \"passed\": true}, {\"check\": \"control 4\", \"actual\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 5000}, \"expected\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 5000}, \"passed\": true}, {\"check\": \"control 5\", \"actual\": {\"balance\": 113849, \"recast_month\": null, \"deferred\": 0, \"payment\": 4000}, \"expected\": {\"balance\": 113849, \"recast_month\": null, \"deferred\": 0, \"payment\": 4000}, \"passed\": true}, {\"check\": \"control 6\", \"actual\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 20000}, \"expected\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 20000}, \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":44.966,"exit_code":0,"observations":[{"actual":{"balance":1,"deferred":52312,"payment":534061,"recast_month":10},"check":"regression: cap check timing","expected":{"balance":1,"deferred":52312,"payment":534061,"recast_month":10},"passed":true},{"actual":{"balance":1063081,"deferred":63081,"payment":10000,"recast_month":null},"check":"control 1","expected":{"balance":1063081,"deferred":63081,"payment":10000,"recast_month":null},"passed":true},{"actual":{"balance":1000000,"deferred":0,"payment":10000,"recast_month":null},"check":"control 2","expected":{"balance":1000000,"deferred":0,"payment":10000,"recast_month":null},"passed":true},{"actual":{"balance":200000,"deferred":0,"payment":4000,"recast_month":null},"check":"control 3","expected":{"balance":200000,"deferred":0,"payment":4000,"recast_month":null},"passed":true},{"actual":{"balance":1000000,"deferred":0,"payment":5000,"recast_month":null},"check":"control 4","expected":{"balance":1000000,"deferred":0,"payment":5000,"recast_month":null},"passed":true},{"actual":{"balance":113849,"deferred":0,"payment":4000,"recast_month":null},"check":"control 5","expected":{"balance":113849,"deferred":0,"payment":4000,"recast_month":null},"passed":true},{"actual":{"balance":1000000,"deferred":0,"payment":20000,"recast_month":null},"check":"control 6","expected":{"balance":1000000,"deferred":0,"payment":20000,"recast_month":null},"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: cap check timing\", \"actual\": {\"balance\": 1, \"recast_month\": 10, \"deferred\": 52312, \"payment\": 534061}, \"expected\": {\"balance\": 1, \"recast_month\": 10, \"deferred\": 52312, \"payment\": 534061}, \"passed\": true}, {\"check\": \"control 1\", \"actual\": {\"balance\": 1063081, \"recast_month\": null, \"deferred\": 63081, \"payment\": 10000}, \"expected\": {\"balance\": 1063081, \"recast_month\": null, \"deferred\": 63081, \"payment\": 10000}, \"passed\": true}, {\"check\": \"control 2\", \"actual\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 10000}, \"expected\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 10000}, \"passed\": true}, {\"check\": \"control 3\", \"actual\": {\"balance\": 200000, \"recast_month\": null, \"deferred\": 0, \"payment\": 4000}, \"expected\": {\"balance\": 200000, \"recast_month\": null, \"deferred\": 0, \"payment\": 4000}, \"passed\": true}, {\"check\": \"control 4\", \"actual\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 5000}, \"expected\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 5000}, \"passed\": true}, {\"check\": \"control 5\", \"actual\": {\"balance\": 113849, \"recast_month\": null, \"deferred\": 0, \"payment\": 4000}, \"expected\": {\"balance\": 113849, \"recast_month\": null, \"deferred\": 0, \"payment\": 4000}, \"passed\": true}, {\"check\": \"control 6\", \"actual\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 20000}, \"expected\": {\"balance\": 1000000, \"recast_month\": null, \"deferred\": 0, \"payment\": 20000}, \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}