FAILURE MAP
← Case archive

FA-61266 / Bond day-count conventions / Open access

Adjusted versus unadjusted accrual periods: payments are made on unadjusted dates · case 01

Payments fall on weekends and holidays.

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

ROOT CAUSE

The payment date is the raw schedule date.

VERIFIED REPAIR

Pay on the modified-following adjusted end date.

Unsuccessful approach: Plain following adjustment pushes month-end payments into the next month.

Case contract

Inputs an unadjusted schedule (first element is the accrual start), holidays and a flag. Business days are weekdays not in holidays; adjustment is modified following. For each period the payment date is the adjusted end date; accrual days use adjusted start and end if the flag is set, otherwise the unadjusted dates. Return [[payment date, accrual days], ...].

Why this case matters

Bond accrual and pricing systems depend on exact day-count arithmetic; a single-day error changes settlement cash.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import datetime
N = 1
observations = []
def solve(dates, holidays, adjust_accrual):
    H = {datetime.date(*h) for h in holidays}
    def biz(x):
        return x.weekday() < 5 and x not in H
    def fwd(x):
        while not biz(x):
            x += datetime.timedelta(days=1)
        return x
    def bwd(x):
        while not biz(x):
            x -= datetime.timedelta(days=1)
        return x
    def mf(x):
        f = fwd(x)
        return f if f.month == x.month else bwd(x)
    out = []
    for i in range(1, len(dates)):
        s = datetime.date(*dates[i - 1])
        e = datetime.date(*dates[i])
        pay = e
        if adjust_accrual:
            s, e = mf(s), mf(e)
        out.append([[pay.year, pay.month, pay.day], (e - s).days])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression payment date convention 1', [[[2025, 10, 31], [2026, 4, 30], [2026, 10, 31]], [], True], [[[2026, 4, 30], 181], [[2026, 10, 30], 183]]], ['regression payment date convention 2', [[[2026, 2, 26], [2026, 5, 26]], [[2026, 5, 26]], False], [[[2026, 5, 27], 89]]], ['partial repair probe 1', [[[2024, 8, 31], [2025, 2, 28], [2025, 8, 31], [2026, 2, 28]], [[2026, 2, 28]], True], [[[2025, 2, 28], 182], [[2025, 8, 29], 182], [[2026, 2, 27], 182]]], ['partial repair probe 2', [[[2030, 8, 31], [2030, 9, 30], [2030, 10, 31], [2030, 11, 30], [2030, 12, 31]], [], False], [[[2030, 9, 30], 30], [[2030, 10, 31], 31], [[2030, 11, 29], 30], [[2030, 12, 31], 31]]], ['normal control 1', [[[2025, 12, 30], [2026, 6, 30], [2026, 12, 30], [2027, 6, 30], [2027, 12, 30]], [[2026, 7, 2], [2027, 12, 31]], True], [[[2026, 6, 30], 182], [[2026, 12, 30], 183], [[2027, 6, 30], 182], [[2027, 12, 30], 183]]], ['normal control 2', [[[2029, 7, 31], [2029, 10, 31], [2030, 1, 31]], [[2029, 11, 2]], True], [[[2029, 10, 31], 92], [[2030, 1, 31], 92]]], ['normal control 3', [[[2023, 5, 8], [2023, 8, 8], [2023, 11, 8]], [], True], [[[2023, 8, 8], 92], [[2023, 11, 8], 92]]], ['normal control 4', [[[2027, 11, 4], [2028, 2, 4]], [[2027, 11, 6], [2028, 2, 5]], False], [[[2028, 2, 4], 92]]]], [['regression payment date convention 1', [[[2025, 4, 19], [2025, 5, 19], [2025, 6, 19], [2025, 7, 19], [2025, 8, 19]], [[2025, 8, 20]], False], [[[2025, 5, 19], 30], [[2025, 6, 19], 31], [[2025, 7, 21], 30], [[2025, 8, 19], 31]]], ['regression payment date convention 2', [[[2025, 7, 31], [2025, 8, 31], [2025, 9, 30], [2025, 10, 31], [2025, 11, 30]], [[2025, 12, 2]], False], [[[2025, 8, 29], 31], [[2025, 9, 30], 30], [[2025, 10, 31], 31], [[2025, 11, 28], 30]]], ['partial repair probe 1', [[[2020, 11, 30], [2021, 2, 28], [2021, 5, 30], [2021, 8, 30]], [], False], [[[2021, 2, 26], 90], [[2021, 5, 31], 91], [[2021, 8, 30], 92]]], ['partial repair probe 2', [[[2021, 12, 30], [2022, 6, 30], [2022, 12, 30], [2023, 6, 30], [2023, 12, 30]], [[2022, 12, 31]], False], [[[2022, 6, 30], 182], [[2022, 12, 30], 183], [[2023, 6, 30], 182], [[2023, 12, 29], 183]]], ['normal control 1', [[[2025, 9, 30], [2026, 3, 30], [2026, 9, 30]], [[2026, 4, 1]], True], [[[2026, 3, 30], 181], [[2026, 9, 30], 184]]], ['normal control 2', [[[2024, 8, 20], [2024, 11, 20], [2025, 2, 20]], [], False], [[[2024, 11, 20], 92], [[2025, 2, 20], 92]]], ['normal control 3', [[[2019, 4, 9], [2019, 5, 9]], [], False], [[[2019, 5, 9], 30]]], ['normal control 4', [[[2030, 11, 30], [2030, 12, 30], [2031, 1, 30], [2031, 2, 28]], [], True], [[[2030, 12, 30], 31], [[2031, 1, 30], 31], [[2031, 2, 28], 29]]]], [['regression payment date convention 1', [[[2030, 1, 30], [2030, 2, 28], [2030, 3, 30], [2030, 4, 30]], [[2030, 1, 30], [2030, 3, 30]], False], [[[2030, 2, 28], 29], [[2030, 3, 29], 30], [[2030, 4, 30], 31]]], ['regression payment date convention 2', [[[2029, 6, 30], [2029, 9, 30], [2029, 12, 30]], [], True], [[[2029, 9, 28], 91], [[2029, 12, 31], 94]]], ['partial repair probe 1', [[[2021, 9, 30], [2021, 10, 30], [2021, 11, 30]], [[2021, 10, 31]], False], [[[2021, 10, 29], 30], [[2021, 11, 30], 31]]], ['partial repair probe 2', [[[2019, 3, 31], [2019, 6, 30]], [[2019, 7, 2]], True], [[[2019, 6, 28], 91]]], ['normal control 1', [[[2019, 10, 13], [2020, 4, 13]], [], False], [[[2020, 4, 13], 183]]], ['normal control 2', [[[2030, 4, 30], [2030, 10, 30], [2031, 4, 30], [2031, 10, 30]], [], True], [[[2030, 10, 30], 183], [[2031, 4, 30], 182], [[2031, 10, 30], 183]]], ['normal control 3', [[[2024, 4, 15], [2024, 10, 15]], [[2024, 4, 17]], False], [[[2024, 10, 15], 183]]], ['normal control 4', [[[2027, 11, 30], [2027, 12, 30]], [], True], [[[2027, 12, 30], 30]]]], [['regression payment date convention 1', [[[2019, 3, 28], [2019, 6, 28], [2019, 9, 28], [2019, 12, 28], [2020, 3, 28]], [[2019, 3, 29]], False], [[[2019, 6, 28], 92], [[2019, 9, 30], 92], [[2019, 12, 30], 91], [[2020, 3, 30], 91]]], ['regression payment date convention 2', [[[2027, 12, 31], [2028, 6, 30], [2028, 12, 31], [2029, 6, 30], [2029, 12, 31]], [], False], [[[2028, 6, 30], 182], [[2028, 12, 29], 184], [[2029, 6, 29], 181], [[2029, 12, 31], 184]]], ['partial repair probe 1', [[[2026, 10, 30], [2027, 1, 30], [2027, 4, 30], [2027, 7, 30]], [[2027, 5, 1]], False], [[[2027, 1, 29], 92], [[2027, 4, 30], 90], [[2027, 7, 30], 91]]], ['partial repair probe 2', [[[2023, 11, 30], [2024, 5, 30], [2024, 11, 30]], [[2023, 12, 2]], False], [[[2024, 5, 30], 182], [[2024, 11, 29], 184]]], ['normal control 1', [[[2025, 2, 28], [2025, 8, 28]], [[2025, 8, 30]], True], [[[2025, 8, 28], 181]]], ['normal control 2', [[[2025, 10, 6], [2026, 1, 6], [2026, 4, 6], [2026, 7, 6], [2026, 10, 6]], [[2026, 1, 8]], False], [[[2026, 1, 6], 92], [[2026, 4, 6], 90], [[2026, 7, 6], 91], [[2026, 10, 6], 92]]], ['normal control 3', [[[2024, 6, 30], [2024, 9, 30]], [], False], [[[2024, 9, 30], 92]]], ['normal control 4', [[[2022, 6, 6], [2022, 9, 6]], [[2022, 6, 6]], True], [[[2022, 9, 6], 91]]]], [['regression payment date convention 1', [[[2022, 9, 30], [2023, 3, 30], [2023, 9, 30]], [[2023, 10, 1]], True], [[[2023, 3, 30], 181], [[2023, 9, 29], 183]]], ['regression payment date convention 2', [[[2023, 3, 31], [2023, 6, 30], [2023, 9, 30]], [], False], [[[2023, 6, 30], 91], [[2023, 9, 29], 92]]], ['partial repair probe 1', [[[2024, 3, 31], [2024, 6, 30], [2024, 9, 30], [2024, 12, 31], [2025, 3, 31]], [], False], [[[2024, 6, 28], 91], [[2024, 9, 30], 92], [[2024, 12, 31], 92], [[2025, 3, 31], 90]]], ['partial repair probe 2', [[[2030, 8, 31], [2030, 9, 30], [2030, 10, 31], [2030, 11, 30]], [[2030, 11, 1]], True], [[[2030, 9, 30], 31], [[2030, 10, 31], 31], [[2030, 11, 29], 29]]], ['normal control 1', [[[2026, 8, 2], [2026, 9, 2], [2026, 10, 2], [2026, 11, 2], [2026, 12, 2]], [[2026, 8, 3], [2026, 11, 3]], True], [[[2026, 9, 2], 29], [[2026, 10, 2], 30], [[2026, 11, 2], 31], [[2026, 12, 2], 30]]], ['normal control 2', [[[2030, 7, 31], [2030, 10, 31]], [], False], [[[2030, 10, 31], 92]]], ['normal control 3', [[[2029, 7, 30], [2029, 10, 30], [2030, 1, 30], [2030, 4, 30]], [[2029, 7, 30]], False], [[[2029, 10, 30], 92], [[2030, 1, 30], 92], [[2030, 4, 30], 90]]], ['normal control 4', [[[2022, 8, 28], [2022, 9, 28], [2022, 10, 28], [2022, 11, 28], [2022, 12, 28]], [[2022, 8, 28]], True], [[[2022, 9, 28], 30], [[2022, 10, 28], 30], [[2022, 11, 28], 31], [[2022, 12, 28], 30]]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), 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 payment date convention 1[[[2026, 4, 30], 181], [[2026, 10, 31], 183]][[[2026, 4, 30], 181], [[2026, 10, 30], 183]]Failed
regression payment date convention 2[[[2026, 5, 26], 89]][[[2026, 5, 27], 89]]Failed
partial repair probe 1[[[2025, 2, 28], 182], [[2025, 8, 31], 182], [[2026, 2, 28], 182]][[[2025, 2, 28], 182], [[2025, 8, 29], 182], [[2026, 2, 27], 182]]Failed
partial repair probe 2[[[2030, 9, 30], 30], [[2030, 10, 31], 31], [[2030, 11, 30], 30], [[2030, 12, 31], 31]][[[2030, 9, 30], 30], [[2030, 10, 31], 31], [[2030, 11, 29], 30], [[2030, 12, 31], 31]]Failed
normal control 1[[[2026, 6, 30], 182], [[2026, 12, 30], 183], [[2027, 6, 30], 182], [[2027, 12, 30], 183]][[[2026, 6, 30], 182], [[2026, 12, 30], 183], [[2027, 6, 30], 182], [[2027, 12, 30], 183]]Passed
normal control 2[[[2029, 10, 31], 92], [[2030, 1, 31], 92]][[[2029, 10, 31], 92], [[2030, 1, 31], 92]]Passed
normal control 3[[[2023, 8, 8], 92], [[2023, 11, 8], 92]][[[2023, 8, 8], 92], [[2023, 11, 8], 92]]Passed
normal control 4[[[2028, 2, 4], 92]][[[2028, 2, 4], 92]]Passed

SHA-256 / 17c5ecb9611b7f890e247e04a78af15e565cb8361689e7872b6a1302e27fa4d8

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import datetime
N = 1
observations = []
def solve(dates, holidays, adjust_accrual):
    H = {datetime.date(*h) for h in holidays}
    def biz(x):
        return x.weekday() < 5 and x not in H
    def fwd(x):
        while not biz(x):
            x += datetime.timedelta(days=1)
        return x
    def bwd(x):
        while not biz(x):
            x -= datetime.timedelta(days=1)
        return x
    def mf(x):
        f = fwd(x)
        return f if f.month == x.month else bwd(x)
    out = []
    for i in range(1, len(dates)):
        s = datetime.date(*dates[i - 1])
        e = datetime.date(*dates[i])
        pay = fwd(e)
        if adjust_accrual:
            s, e = mf(s), mf(e)
        out.append([[pay.year, pay.month, pay.day], (e - s).days])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression payment date convention 1', [[[2025, 10, 31], [2026, 4, 30], [2026, 10, 31]], [], True], [[[2026, 4, 30], 181], [[2026, 10, 30], 183]]], ['regression payment date convention 2', [[[2026, 2, 26], [2026, 5, 26]], [[2026, 5, 26]], False], [[[2026, 5, 27], 89]]], ['partial repair probe 1', [[[2024, 8, 31], [2025, 2, 28], [2025, 8, 31], [2026, 2, 28]], [[2026, 2, 28]], True], [[[2025, 2, 28], 182], [[2025, 8, 29], 182], [[2026, 2, 27], 182]]], ['partial repair probe 2', [[[2030, 8, 31], [2030, 9, 30], [2030, 10, 31], [2030, 11, 30], [2030, 12, 31]], [], False], [[[2030, 9, 30], 30], [[2030, 10, 31], 31], [[2030, 11, 29], 30], [[2030, 12, 31], 31]]], ['normal control 1', [[[2025, 12, 30], [2026, 6, 30], [2026, 12, 30], [2027, 6, 30], [2027, 12, 30]], [[2026, 7, 2], [2027, 12, 31]], True], [[[2026, 6, 30], 182], [[2026, 12, 30], 183], [[2027, 6, 30], 182], [[2027, 12, 30], 183]]], ['normal control 2', [[[2029, 7, 31], [2029, 10, 31], [2030, 1, 31]], [[2029, 11, 2]], True], [[[2029, 10, 31], 92], [[2030, 1, 31], 92]]], ['normal control 3', [[[2023, 5, 8], [2023, 8, 8], [2023, 11, 8]], [], True], [[[2023, 8, 8], 92], [[2023, 11, 8], 92]]], ['normal control 4', [[[2027, 11, 4], [2028, 2, 4]], [[2027, 11, 6], [2028, 2, 5]], False], [[[2028, 2, 4], 92]]]], [['regression payment date convention 1', [[[2025, 4, 19], [2025, 5, 19], [2025, 6, 19], [2025, 7, 19], [2025, 8, 19]], [[2025, 8, 20]], False], [[[2025, 5, 19], 30], [[2025, 6, 19], 31], [[2025, 7, 21], 30], [[2025, 8, 19], 31]]], ['regression payment date convention 2', [[[2025, 7, 31], [2025, 8, 31], [2025, 9, 30], [2025, 10, 31], [2025, 11, 30]], [[2025, 12, 2]], False], [[[2025, 8, 29], 31], [[2025, 9, 30], 30], [[2025, 10, 31], 31], [[2025, 11, 28], 30]]], ['partial repair probe 1', [[[2020, 11, 30], [2021, 2, 28], [2021, 5, 30], [2021, 8, 30]], [], False], [[[2021, 2, 26], 90], [[2021, 5, 31], 91], [[2021, 8, 30], 92]]], ['partial repair probe 2', [[[2021, 12, 30], [2022, 6, 30], [2022, 12, 30], [2023, 6, 30], [2023, 12, 30]], [[2022, 12, 31]], False], [[[2022, 6, 30], 182], [[2022, 12, 30], 183], [[2023, 6, 30], 182], [[2023, 12, 29], 183]]], ['normal control 1', [[[2025, 9, 30], [2026, 3, 30], [2026, 9, 30]], [[2026, 4, 1]], True], [[[2026, 3, 30], 181], [[2026, 9, 30], 184]]], ['normal control 2', [[[2024, 8, 20], [2024, 11, 20], [2025, 2, 20]], [], False], [[[2024, 11, 20], 92], [[2025, 2, 20], 92]]], ['normal control 3', [[[2019, 4, 9], [2019, 5, 9]], [], False], [[[2019, 5, 9], 30]]], ['normal control 4', [[[2030, 11, 30], [2030, 12, 30], [2031, 1, 30], [2031, 2, 28]], [], True], [[[2030, 12, 30], 31], [[2031, 1, 30], 31], [[2031, 2, 28], 29]]]], [['regression payment date convention 1', [[[2030, 1, 30], [2030, 2, 28], [2030, 3, 30], [2030, 4, 30]], [[2030, 1, 30], [2030, 3, 30]], False], [[[2030, 2, 28], 29], [[2030, 3, 29], 30], [[2030, 4, 30], 31]]], ['regression payment date convention 2', [[[2029, 6, 30], [2029, 9, 30], [2029, 12, 30]], [], True], [[[2029, 9, 28], 91], [[2029, 12, 31], 94]]], ['partial repair probe 1', [[[2021, 9, 30], [2021, 10, 30], [2021, 11, 30]], [[2021, 10, 31]], False], [[[2021, 10, 29], 30], [[2021, 11, 30], 31]]], ['partial repair probe 2', [[[2019, 3, 31], [2019, 6, 30]], [[2019, 7, 2]], True], [[[2019, 6, 28], 91]]], ['normal control 1', [[[2019, 10, 13], [2020, 4, 13]], [], False], [[[2020, 4, 13], 183]]], ['normal control 2', [[[2030, 4, 30], [2030, 10, 30], [2031, 4, 30], [2031, 10, 30]], [], True], [[[2030, 10, 30], 183], [[2031, 4, 30], 182], [[2031, 10, 30], 183]]], ['normal control 3', [[[2024, 4, 15], [2024, 10, 15]], [[2024, 4, 17]], False], [[[2024, 10, 15], 183]]], ['normal control 4', [[[2027, 11, 30], [2027, 12, 30]], [], True], [[[2027, 12, 30], 30]]]], [['regression payment date convention 1', [[[2019, 3, 28], [2019, 6, 28], [2019, 9, 28], [2019, 12, 28], [2020, 3, 28]], [[2019, 3, 29]], False], [[[2019, 6, 28], 92], [[2019, 9, 30], 92], [[2019, 12, 30], 91], [[2020, 3, 30], 91]]], ['regression payment date convention 2', [[[2027, 12, 31], [2028, 6, 30], [2028, 12, 31], [2029, 6, 30], [2029, 12, 31]], [], False], [[[2028, 6, 30], 182], [[2028, 12, 29], 184], [[2029, 6, 29], 181], [[2029, 12, 31], 184]]], ['partial repair probe 1', [[[2026, 10, 30], [2027, 1, 30], [2027, 4, 30], [2027, 7, 30]], [[2027, 5, 1]], False], [[[2027, 1, 29], 92], [[2027, 4, 30], 90], [[2027, 7, 30], 91]]], ['partial repair probe 2', [[[2023, 11, 30], [2024, 5, 30], [2024, 11, 30]], [[2023, 12, 2]], False], [[[2024, 5, 30], 182], [[2024, 11, 29], 184]]], ['normal control 1', [[[2025, 2, 28], [2025, 8, 28]], [[2025, 8, 30]], True], [[[2025, 8, 28], 181]]], ['normal control 2', [[[2025, 10, 6], [2026, 1, 6], [2026, 4, 6], [2026, 7, 6], [2026, 10, 6]], [[2026, 1, 8]], False], [[[2026, 1, 6], 92], [[2026, 4, 6], 90], [[2026, 7, 6], 91], [[2026, 10, 6], 92]]], ['normal control 3', [[[2024, 6, 30], [2024, 9, 30]], [], False], [[[2024, 9, 30], 92]]], ['normal control 4', [[[2022, 6, 6], [2022, 9, 6]], [[2022, 6, 6]], True], [[[2022, 9, 6], 91]]]], [['regression payment date convention 1', [[[2022, 9, 30], [2023, 3, 30], [2023, 9, 30]], [[2023, 10, 1]], True], [[[2023, 3, 30], 181], [[2023, 9, 29], 183]]], ['regression payment date convention 2', [[[2023, 3, 31], [2023, 6, 30], [2023, 9, 30]], [], False], [[[2023, 6, 30], 91], [[2023, 9, 29], 92]]], ['partial repair probe 1', [[[2024, 3, 31], [2024, 6, 30], [2024, 9, 30], [2024, 12, 31], [2025, 3, 31]], [], False], [[[2024, 6, 28], 91], [[2024, 9, 30], 92], [[2024, 12, 31], 92], [[2025, 3, 31], 90]]], ['partial repair probe 2', [[[2030, 8, 31], [2030, 9, 30], [2030, 10, 31], [2030, 11, 30]], [[2030, 11, 1]], True], [[[2030, 9, 30], 31], [[2030, 10, 31], 31], [[2030, 11, 29], 29]]], ['normal control 1', [[[2026, 8, 2], [2026, 9, 2], [2026, 10, 2], [2026, 11, 2], [2026, 12, 2]], [[2026, 8, 3], [2026, 11, 3]], True], [[[2026, 9, 2], 29], [[2026, 10, 2], 30], [[2026, 11, 2], 31], [[2026, 12, 2], 30]]], ['normal control 2', [[[2030, 7, 31], [2030, 10, 31]], [], False], [[[2030, 10, 31], 92]]], ['normal control 3', [[[2029, 7, 30], [2029, 10, 30], [2030, 1, 30], [2030, 4, 30]], [[2029, 7, 30]], False], [[[2029, 10, 30], 92], [[2030, 1, 30], 92], [[2030, 4, 30], 90]]], ['normal control 4', [[[2022, 8, 28], [2022, 9, 28], [2022, 10, 28], [2022, 11, 28], [2022, 12, 28]], [[2022, 8, 28]], True], [[[2022, 9, 28], 30], [[2022, 10, 28], 30], [[2022, 11, 28], 31], [[2022, 12, 28], 30]]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), 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 payment date convention 1[[[2026, 4, 30], 181], [[2026, 11, 2], 183]][[[2026, 4, 30], 181], [[2026, 10, 30], 183]]Failed
regression payment date convention 2[[[2026, 5, 27], 89]][[[2026, 5, 27], 89]]Passed
partial repair probe 1[[[2025, 2, 28], 182], [[2025, 9, 1], 182], [[2026, 3, 2], 182]][[[2025, 2, 28], 182], [[2025, 8, 29], 182], [[2026, 2, 27], 182]]Failed
partial repair probe 2[[[2030, 9, 30], 30], [[2030, 10, 31], 31], [[2030, 12, 2], 30], [[2030, 12, 31], 31]][[[2030, 9, 30], 30], [[2030, 10, 31], 31], [[2030, 11, 29], 30], [[2030, 12, 31], 31]]Failed
normal control 1[[[2026, 6, 30], 182], [[2026, 12, 30], 183], [[2027, 6, 30], 182], [[2027, 12, 30], 183]][[[2026, 6, 30], 182], [[2026, 12, 30], 183], [[2027, 6, 30], 182], [[2027, 12, 30], 183]]Passed
normal control 2[[[2029, 10, 31], 92], [[2030, 1, 31], 92]][[[2029, 10, 31], 92], [[2030, 1, 31], 92]]Passed
normal control 3[[[2023, 8, 8], 92], [[2023, 11, 8], 92]][[[2023, 8, 8], 92], [[2023, 11, 8], 92]]Passed
normal control 4[[[2028, 2, 4], 92]][[[2028, 2, 4], 92]]Passed

SHA-256 / fe415fa51f84f28012a8266713419172a24e32e6eb4f50917f87c9cadf499186

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import datetime
N = 1
observations = []
def solve(dates, holidays, adjust_accrual):
    H = {datetime.date(*h) for h in holidays}
    def biz(x):
        return x.weekday() < 5 and x not in H
    def fwd(x):
        while not biz(x):
            x += datetime.timedelta(days=1)
        return x
    def bwd(x):
        while not biz(x):
            x -= datetime.timedelta(days=1)
        return x
    def mf(x):
        f = fwd(x)
        return f if f.month == x.month else bwd(x)
    out = []
    for i in range(1, len(dates)):
        s = datetime.date(*dates[i - 1])
        e = datetime.date(*dates[i])
        pay = mf(e)
        if adjust_accrual:
            s, e = mf(s), mf(e)
        out.append([[pay.year, pay.month, pay.day], (e - s).days])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression payment date convention 1', [[[2025, 10, 31], [2026, 4, 30], [2026, 10, 31]], [], True], [[[2026, 4, 30], 181], [[2026, 10, 30], 183]]], ['regression payment date convention 2', [[[2026, 2, 26], [2026, 5, 26]], [[2026, 5, 26]], False], [[[2026, 5, 27], 89]]], ['partial repair probe 1', [[[2024, 8, 31], [2025, 2, 28], [2025, 8, 31], [2026, 2, 28]], [[2026, 2, 28]], True], [[[2025, 2, 28], 182], [[2025, 8, 29], 182], [[2026, 2, 27], 182]]], ['partial repair probe 2', [[[2030, 8, 31], [2030, 9, 30], [2030, 10, 31], [2030, 11, 30], [2030, 12, 31]], [], False], [[[2030, 9, 30], 30], [[2030, 10, 31], 31], [[2030, 11, 29], 30], [[2030, 12, 31], 31]]], ['normal control 1', [[[2025, 12, 30], [2026, 6, 30], [2026, 12, 30], [2027, 6, 30], [2027, 12, 30]], [[2026, 7, 2], [2027, 12, 31]], True], [[[2026, 6, 30], 182], [[2026, 12, 30], 183], [[2027, 6, 30], 182], [[2027, 12, 30], 183]]], ['normal control 2', [[[2029, 7, 31], [2029, 10, 31], [2030, 1, 31]], [[2029, 11, 2]], True], [[[2029, 10, 31], 92], [[2030, 1, 31], 92]]], ['normal control 3', [[[2023, 5, 8], [2023, 8, 8], [2023, 11, 8]], [], True], [[[2023, 8, 8], 92], [[2023, 11, 8], 92]]], ['normal control 4', [[[2027, 11, 4], [2028, 2, 4]], [[2027, 11, 6], [2028, 2, 5]], False], [[[2028, 2, 4], 92]]]], [['regression payment date convention 1', [[[2025, 4, 19], [2025, 5, 19], [2025, 6, 19], [2025, 7, 19], [2025, 8, 19]], [[2025, 8, 20]], False], [[[2025, 5, 19], 30], [[2025, 6, 19], 31], [[2025, 7, 21], 30], [[2025, 8, 19], 31]]], ['regression payment date convention 2', [[[2025, 7, 31], [2025, 8, 31], [2025, 9, 30], [2025, 10, 31], [2025, 11, 30]], [[2025, 12, 2]], False], [[[2025, 8, 29], 31], [[2025, 9, 30], 30], [[2025, 10, 31], 31], [[2025, 11, 28], 30]]], ['partial repair probe 1', [[[2020, 11, 30], [2021, 2, 28], [2021, 5, 30], [2021, 8, 30]], [], False], [[[2021, 2, 26], 90], [[2021, 5, 31], 91], [[2021, 8, 30], 92]]], ['partial repair probe 2', [[[2021, 12, 30], [2022, 6, 30], [2022, 12, 30], [2023, 6, 30], [2023, 12, 30]], [[2022, 12, 31]], False], [[[2022, 6, 30], 182], [[2022, 12, 30], 183], [[2023, 6, 30], 182], [[2023, 12, 29], 183]]], ['normal control 1', [[[2025, 9, 30], [2026, 3, 30], [2026, 9, 30]], [[2026, 4, 1]], True], [[[2026, 3, 30], 181], [[2026, 9, 30], 184]]], ['normal control 2', [[[2024, 8, 20], [2024, 11, 20], [2025, 2, 20]], [], False], [[[2024, 11, 20], 92], [[2025, 2, 20], 92]]], ['normal control 3', [[[2019, 4, 9], [2019, 5, 9]], [], False], [[[2019, 5, 9], 30]]], ['normal control 4', [[[2030, 11, 30], [2030, 12, 30], [2031, 1, 30], [2031, 2, 28]], [], True], [[[2030, 12, 30], 31], [[2031, 1, 30], 31], [[2031, 2, 28], 29]]]], [['regression payment date convention 1', [[[2030, 1, 30], [2030, 2, 28], [2030, 3, 30], [2030, 4, 30]], [[2030, 1, 30], [2030, 3, 30]], False], [[[2030, 2, 28], 29], [[2030, 3, 29], 30], [[2030, 4, 30], 31]]], ['regression payment date convention 2', [[[2029, 6, 30], [2029, 9, 30], [2029, 12, 30]], [], True], [[[2029, 9, 28], 91], [[2029, 12, 31], 94]]], ['partial repair probe 1', [[[2021, 9, 30], [2021, 10, 30], [2021, 11, 30]], [[2021, 10, 31]], False], [[[2021, 10, 29], 30], [[2021, 11, 30], 31]]], ['partial repair probe 2', [[[2019, 3, 31], [2019, 6, 30]], [[2019, 7, 2]], True], [[[2019, 6, 28], 91]]], ['normal control 1', [[[2019, 10, 13], [2020, 4, 13]], [], False], [[[2020, 4, 13], 183]]], ['normal control 2', [[[2030, 4, 30], [2030, 10, 30], [2031, 4, 30], [2031, 10, 30]], [], True], [[[2030, 10, 30], 183], [[2031, 4, 30], 182], [[2031, 10, 30], 183]]], ['normal control 3', [[[2024, 4, 15], [2024, 10, 15]], [[2024, 4, 17]], False], [[[2024, 10, 15], 183]]], ['normal control 4', [[[2027, 11, 30], [2027, 12, 30]], [], True], [[[2027, 12, 30], 30]]]], [['regression payment date convention 1', [[[2019, 3, 28], [2019, 6, 28], [2019, 9, 28], [2019, 12, 28], [2020, 3, 28]], [[2019, 3, 29]], False], [[[2019, 6, 28], 92], [[2019, 9, 30], 92], [[2019, 12, 30], 91], [[2020, 3, 30], 91]]], ['regression payment date convention 2', [[[2027, 12, 31], [2028, 6, 30], [2028, 12, 31], [2029, 6, 30], [2029, 12, 31]], [], False], [[[2028, 6, 30], 182], [[2028, 12, 29], 184], [[2029, 6, 29], 181], [[2029, 12, 31], 184]]], ['partial repair probe 1', [[[2026, 10, 30], [2027, 1, 30], [2027, 4, 30], [2027, 7, 30]], [[2027, 5, 1]], False], [[[2027, 1, 29], 92], [[2027, 4, 30], 90], [[2027, 7, 30], 91]]], ['partial repair probe 2', [[[2023, 11, 30], [2024, 5, 30], [2024, 11, 30]], [[2023, 12, 2]], False], [[[2024, 5, 30], 182], [[2024, 11, 29], 184]]], ['normal control 1', [[[2025, 2, 28], [2025, 8, 28]], [[2025, 8, 30]], True], [[[2025, 8, 28], 181]]], ['normal control 2', [[[2025, 10, 6], [2026, 1, 6], [2026, 4, 6], [2026, 7, 6], [2026, 10, 6]], [[2026, 1, 8]], False], [[[2026, 1, 6], 92], [[2026, 4, 6], 90], [[2026, 7, 6], 91], [[2026, 10, 6], 92]]], ['normal control 3', [[[2024, 6, 30], [2024, 9, 30]], [], False], [[[2024, 9, 30], 92]]], ['normal control 4', [[[2022, 6, 6], [2022, 9, 6]], [[2022, 6, 6]], True], [[[2022, 9, 6], 91]]]], [['regression payment date convention 1', [[[2022, 9, 30], [2023, 3, 30], [2023, 9, 30]], [[2023, 10, 1]], True], [[[2023, 3, 30], 181], [[2023, 9, 29], 183]]], ['regression payment date convention 2', [[[2023, 3, 31], [2023, 6, 30], [2023, 9, 30]], [], False], [[[2023, 6, 30], 91], [[2023, 9, 29], 92]]], ['partial repair probe 1', [[[2024, 3, 31], [2024, 6, 30], [2024, 9, 30], [2024, 12, 31], [2025, 3, 31]], [], False], [[[2024, 6, 28], 91], [[2024, 9, 30], 92], [[2024, 12, 31], 92], [[2025, 3, 31], 90]]], ['partial repair probe 2', [[[2030, 8, 31], [2030, 9, 30], [2030, 10, 31], [2030, 11, 30]], [[2030, 11, 1]], True], [[[2030, 9, 30], 31], [[2030, 10, 31], 31], [[2030, 11, 29], 29]]], ['normal control 1', [[[2026, 8, 2], [2026, 9, 2], [2026, 10, 2], [2026, 11, 2], [2026, 12, 2]], [[2026, 8, 3], [2026, 11, 3]], True], [[[2026, 9, 2], 29], [[2026, 10, 2], 30], [[2026, 11, 2], 31], [[2026, 12, 2], 30]]], ['normal control 2', [[[2030, 7, 31], [2030, 10, 31]], [], False], [[[2030, 10, 31], 92]]], ['normal control 3', [[[2029, 7, 30], [2029, 10, 30], [2030, 1, 30], [2030, 4, 30]], [[2029, 7, 30]], False], [[[2029, 10, 30], 92], [[2030, 1, 30], 92], [[2030, 4, 30], 90]]], ['normal control 4', [[[2022, 8, 28], [2022, 9, 28], [2022, 10, 28], [2022, 11, 28], [2022, 12, 28]], [[2022, 8, 28]], True], [[[2022, 9, 28], 30], [[2022, 10, 28], 30], [[2022, 11, 28], 31], [[2022, 12, 28], 30]]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), 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 payment date convention 1[[[2026, 4, 30], 181], [[2026, 10, 30], 183]][[[2026, 4, 30], 181], [[2026, 10, 30], 183]]Passed
regression payment date convention 2[[[2026, 5, 27], 89]][[[2026, 5, 27], 89]]Passed
partial repair probe 1[[[2025, 2, 28], 182], [[2025, 8, 29], 182], [[2026, 2, 27], 182]][[[2025, 2, 28], 182], [[2025, 8, 29], 182], [[2026, 2, 27], 182]]Passed
partial repair probe 2[[[2030, 9, 30], 30], [[2030, 10, 31], 31], [[2030, 11, 29], 30], [[2030, 12, 31], 31]][[[2030, 9, 30], 30], [[2030, 10, 31], 31], [[2030, 11, 29], 30], [[2030, 12, 31], 31]]Passed
normal control 1[[[2026, 6, 30], 182], [[2026, 12, 30], 183], [[2027, 6, 30], 182], [[2027, 12, 30], 183]][[[2026, 6, 30], 182], [[2026, 12, 30], 183], [[2027, 6, 30], 182], [[2027, 12, 30], 183]]Passed
normal control 2[[[2029, 10, 31], 92], [[2030, 1, 31], 92]][[[2029, 10, 31], 92], [[2030, 1, 31], 92]]Passed
normal control 3[[[2023, 8, 8], 92], [[2023, 11, 8], 92]][[[2023, 8, 8], 92], [[2023, 11, 8], 92]]Passed
normal control 4[[[2028, 2, 4], 92]][[[2028, 2, 4], 92]]Passed

SHA-256 / 81f21379a75e38ebd753e4f2a05fb5fc8f3692112cf564e74900eb66c60b9ba3

Verification & scope

A deterministic toy contract stated explicitly in the contract field; no claim of conformance to any published convention text. 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:53.574117+00:00.

Case digest / b99685a3e7bcf5f461c487b3afc84e47b5e57f7edf96b394992671b09bfa461c