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.
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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