FA-60951 / Bond day-count conventions / Open access
Act/365L denominator selection: the end year is excluded from the leap-day search · case 01
An annual period ending after 29 February of a leap end year uses 365 days.
ROOT CAUSE
The search over years stops before the end year.
VERIFIED REPAIR
Search every year from the start year through the end year inclusive.
Unsuccessful approach: Starting the search one year later misses leap days in the start year.
Case contract
Inputs start, end ([y,m,d]) and coupon frequency. Days are actual days. For annual frequency the denominator is 366 if any 29 February lies in (start, end], else 365. For other frequencies the denominator is 366 if the end date year is a leap year, else 365. Return days/denominator rounded to 9 decimals.
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
from fractions import Fraction
N = 1
observations = []
def solve(a, b, freq):
A = datetime.date(*a)
B = datetime.date(*b)
def leap(y):
return (y % 4 == 0 and y % 100 != 0) or y % 400 == 0
days = (B - A).days
if freq == 1:
has29 = any(leap(y) and A < datetime.date(y, 2, 29) <= B for y in range(A.year, B.year))
den = 366 if has29 else 365
else:
den = 366 if leap(B.year) else 365
return round(days / den, 9)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression candidate year range 1', [[2023, 2, 28], [2024, 2, 29], 1], 1.0], ['regression candidate year range 2', [[1915, 8, 27], [1916, 9, 13], 1], 1.046448087], ['partial repair probe 1', [[2024, 1, 29], [2025, 1, 29], 1], 1.0], ['partial repair probe 2', [[1924, 1, 30], [1927, 1, 30], 1], 2.994535519], ['boundary control 1', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['boundary control 2', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['normal control 1', [[2059, 4, 30], [2059, 12, 6], 4], 0.602739726], ['normal control 2', [[2095, 2, 1], [2095, 8, 1], 2], 0.495890411]], [['regression candidate year range 1', [[2055, 5, 28], [2056, 5, 28], 1], 1.0], ['regression candidate year range 2', [[1907, 5, 8], [1908, 5, 8], 1], 1.0], ['partial repair probe 1', [[2104, 1, 1], [2106, 1, 1], 1], 1.99726776], ['partial repair probe 2', [[2004, 1, 1], [2005, 1, 1], 1], 1.0], ['boundary control 1', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['boundary control 2', [[2024, 11, 15], [2025, 2, 15], 4], 0.252054795], ['normal control 1', [[1902, 3, 28], [1902, 12, 28], 4], 0.753424658], ['normal control 2', [[2023, 2, 1], [2023, 8, 1], 2], 0.495890411]], [['regression candidate year range 1', [[2003, 1, 29], [2004, 3, 3], 1], 1.090163934], ['regression candidate year range 2', [[2091, 1, 30], [2092, 3, 29], 1], 1.158469945], ['partial repair probe 1', [[2024, 2, 15], [2025, 2, 15], 1], 1.0], ['partial repair probe 2', [[2096, 1, 15], [2098, 1, 15], 1], 1.99726776], ['boundary control 1', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['boundary control 2', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['normal control 1', [[1956, 5, 23], [1959, 5, 23], 1], 3.0], ['normal control 2', [[2050, 7, 28], [2051, 7, 28], 2], 1.0]], [['regression candidate year range 1', [[1983, 3, 1], [1984, 3, 1], 1], 1.0], ['regression candidate year range 2', [[1972, 1, 31], [1972, 10, 26], 1], 0.734972678], ['partial repair probe 1', [[2000, 1, 29], [2002, 1, 29], 1], 1.99726776], ['partial repair probe 2', [[2000, 1, 29], [2001, 1, 29], 1], 1.0], ['boundary control 1', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['boundary control 2', [[2024, 11, 15], [2025, 2, 15], 4], 0.252054795], ['normal control 1', [[2095, 2, 28], [2096, 2, 28], 1], 1.0], ['normal control 2', [[1947, 3, 30], [1948, 7, 15], 2], 1.292349727]], [['regression candidate year range 1', [[1995, 12, 1], [1996, 12, 1], 1], 1.0], ['regression candidate year range 2', [[1991, 4, 30], [1992, 4, 30], 1], 1.0], ['partial repair probe 1', [[2024, 2, 15], [2025, 2, 15], 1], 1.0], ['partial repair probe 2', [[2028, 2, 1], [2031, 2, 1], 1], 2.994535519], ['boundary control 1', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['boundary control 2', [[2024, 11, 15], [2025, 2, 15], 4], 0.252054795], ['normal control 1', [[2096, 1, 28], [2096, 4, 28], 4], 0.24863388], ['normal control 2', [[1943, 1, 22], [1943, 4, 22], 4], 0.246575342]]]
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 candidate year range 1 | 1.002739726 | 1.0 | Failed |
| regression candidate year range 2 | 1.049315068 | 1.046448087 | Failed |
| partial repair probe 1 | 1.0 | 1.0 | Passed |
| partial repair probe 2 | 2.994535519 | 2.994535519 | Passed |
| boundary control 1 | 1.0 | 1.0 | Passed |
| boundary control 2 | 0.24863388 | 0.24863388 | Passed |
| normal control 1 | 0.602739726 | 0.602739726 | Passed |
| normal control 2 | 0.495890411 | 0.495890411 | Passed |
SHA-256 / 5c3622434973bfcc2cda459b1460238b26ff18f6ca1981dd7eea96139aadf2c8
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import datetime
from fractions import Fraction
N = 1
observations = []
def solve(a, b, freq):
A = datetime.date(*a)
B = datetime.date(*b)
def leap(y):
return (y % 4 == 0 and y % 100 != 0) or y % 400 == 0
days = (B - A).days
if freq == 1:
has29 = any(leap(y) and A < datetime.date(y, 2, 29) <= B for y in range(A.year + 1, B.year + 1))
den = 366 if has29 else 365
else:
den = 366 if leap(B.year) else 365
return round(days / den, 9)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression candidate year range 1', [[2023, 2, 28], [2024, 2, 29], 1], 1.0], ['regression candidate year range 2', [[1915, 8, 27], [1916, 9, 13], 1], 1.046448087], ['partial repair probe 1', [[2024, 1, 29], [2025, 1, 29], 1], 1.0], ['partial repair probe 2', [[1924, 1, 30], [1927, 1, 30], 1], 2.994535519], ['boundary control 1', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['boundary control 2', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['normal control 1', [[2059, 4, 30], [2059, 12, 6], 4], 0.602739726], ['normal control 2', [[2095, 2, 1], [2095, 8, 1], 2], 0.495890411]], [['regression candidate year range 1', [[2055, 5, 28], [2056, 5, 28], 1], 1.0], ['regression candidate year range 2', [[1907, 5, 8], [1908, 5, 8], 1], 1.0], ['partial repair probe 1', [[2104, 1, 1], [2106, 1, 1], 1], 1.99726776], ['partial repair probe 2', [[2004, 1, 1], [2005, 1, 1], 1], 1.0], ['boundary control 1', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['boundary control 2', [[2024, 11, 15], [2025, 2, 15], 4], 0.252054795], ['normal control 1', [[1902, 3, 28], [1902, 12, 28], 4], 0.753424658], ['normal control 2', [[2023, 2, 1], [2023, 8, 1], 2], 0.495890411]], [['regression candidate year range 1', [[2003, 1, 29], [2004, 3, 3], 1], 1.090163934], ['regression candidate year range 2', [[2091, 1, 30], [2092, 3, 29], 1], 1.158469945], ['partial repair probe 1', [[2024, 2, 15], [2025, 2, 15], 1], 1.0], ['partial repair probe 2', [[2096, 1, 15], [2098, 1, 15], 1], 1.99726776], ['boundary control 1', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['boundary control 2', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['normal control 1', [[1956, 5, 23], [1959, 5, 23], 1], 3.0], ['normal control 2', [[2050, 7, 28], [2051, 7, 28], 2], 1.0]], [['regression candidate year range 1', [[1983, 3, 1], [1984, 3, 1], 1], 1.0], ['regression candidate year range 2', [[1972, 1, 31], [1972, 10, 26], 1], 0.734972678], ['partial repair probe 1', [[2000, 1, 29], [2002, 1, 29], 1], 1.99726776], ['partial repair probe 2', [[2000, 1, 29], [2001, 1, 29], 1], 1.0], ['boundary control 1', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['boundary control 2', [[2024, 11, 15], [2025, 2, 15], 4], 0.252054795], ['normal control 1', [[2095, 2, 28], [2096, 2, 28], 1], 1.0], ['normal control 2', [[1947, 3, 30], [1948, 7, 15], 2], 1.292349727]], [['regression candidate year range 1', [[1995, 12, 1], [1996, 12, 1], 1], 1.0], ['regression candidate year range 2', [[1991, 4, 30], [1992, 4, 30], 1], 1.0], ['partial repair probe 1', [[2024, 2, 15], [2025, 2, 15], 1], 1.0], ['partial repair probe 2', [[2028, 2, 1], [2031, 2, 1], 1], 2.994535519], ['boundary control 1', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['boundary control 2', [[2024, 11, 15], [2025, 2, 15], 4], 0.252054795], ['normal control 1', [[2096, 1, 28], [2096, 4, 28], 4], 0.24863388], ['normal control 2', [[1943, 1, 22], [1943, 4, 22], 4], 0.246575342]]]
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 candidate year range 1 | 1.0 | 1.0 | Passed |
| regression candidate year range 2 | 1.046448087 | 1.046448087 | Passed |
| partial repair probe 1 | 1.002739726 | 1.0 | Failed |
| partial repair probe 2 | 3.002739726 | 2.994535519 | Failed |
| boundary control 1 | 1.0 | 1.0 | Passed |
| boundary control 2 | 0.24863388 | 0.24863388 | Passed |
| normal control 1 | 0.602739726 | 0.602739726 | Passed |
| normal control 2 | 0.495890411 | 0.495890411 | Passed |
SHA-256 / 33cd45e419bb339e6fa589783bee7922a0909bebc714563767ea988a57bf0bc2
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import datetime
from fractions import Fraction
N = 1
observations = []
def solve(a, b, freq):
A = datetime.date(*a)
B = datetime.date(*b)
def leap(y):
return (y % 4 == 0 and y % 100 != 0) or y % 400 == 0
days = (B - A).days
if freq == 1:
has29 = any(leap(y) and A < datetime.date(y, 2, 29) <= B for y in range(A.year, B.year + 1))
den = 366 if has29 else 365
else:
den = 366 if leap(B.year) else 365
return round(days / den, 9)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression candidate year range 1', [[2023, 2, 28], [2024, 2, 29], 1], 1.0], ['regression candidate year range 2', [[1915, 8, 27], [1916, 9, 13], 1], 1.046448087], ['partial repair probe 1', [[2024, 1, 29], [2025, 1, 29], 1], 1.0], ['partial repair probe 2', [[1924, 1, 30], [1927, 1, 30], 1], 2.994535519], ['boundary control 1', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['boundary control 2', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['normal control 1', [[2059, 4, 30], [2059, 12, 6], 4], 0.602739726], ['normal control 2', [[2095, 2, 1], [2095, 8, 1], 2], 0.495890411]], [['regression candidate year range 1', [[2055, 5, 28], [2056, 5, 28], 1], 1.0], ['regression candidate year range 2', [[1907, 5, 8], [1908, 5, 8], 1], 1.0], ['partial repair probe 1', [[2104, 1, 1], [2106, 1, 1], 1], 1.99726776], ['partial repair probe 2', [[2004, 1, 1], [2005, 1, 1], 1], 1.0], ['boundary control 1', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['boundary control 2', [[2024, 11, 15], [2025, 2, 15], 4], 0.252054795], ['normal control 1', [[1902, 3, 28], [1902, 12, 28], 4], 0.753424658], ['normal control 2', [[2023, 2, 1], [2023, 8, 1], 2], 0.495890411]], [['regression candidate year range 1', [[2003, 1, 29], [2004, 3, 3], 1], 1.090163934], ['regression candidate year range 2', [[2091, 1, 30], [2092, 3, 29], 1], 1.158469945], ['partial repair probe 1', [[2024, 2, 15], [2025, 2, 15], 1], 1.0], ['partial repair probe 2', [[2096, 1, 15], [2098, 1, 15], 1], 1.99726776], ['boundary control 1', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['boundary control 2', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['normal control 1', [[1956, 5, 23], [1959, 5, 23], 1], 3.0], ['normal control 2', [[2050, 7, 28], [2051, 7, 28], 2], 1.0]], [['regression candidate year range 1', [[1983, 3, 1], [1984, 3, 1], 1], 1.0], ['regression candidate year range 2', [[1972, 1, 31], [1972, 10, 26], 1], 0.734972678], ['partial repair probe 1', [[2000, 1, 29], [2002, 1, 29], 1], 1.99726776], ['partial repair probe 2', [[2000, 1, 29], [2001, 1, 29], 1], 1.0], ['boundary control 1', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['boundary control 2', [[2024, 11, 15], [2025, 2, 15], 4], 0.252054795], ['normal control 1', [[2095, 2, 28], [2096, 2, 28], 1], 1.0], ['normal control 2', [[1947, 3, 30], [1948, 7, 15], 2], 1.292349727]], [['regression candidate year range 1', [[1995, 12, 1], [1996, 12, 1], 1], 1.0], ['regression candidate year range 2', [[1991, 4, 30], [1992, 4, 30], 1], 1.0], ['partial repair probe 1', [[2024, 2, 15], [2025, 2, 15], 1], 1.0], ['partial repair probe 2', [[2028, 2, 1], [2031, 2, 1], 1], 2.994535519], ['boundary control 1', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['boundary control 2', [[2024, 11, 15], [2025, 2, 15], 4], 0.252054795], ['normal control 1', [[2096, 1, 28], [2096, 4, 28], 4], 0.24863388], ['normal control 2', [[1943, 1, 22], [1943, 4, 22], 4], 0.246575342]]]
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 candidate year range 1 | 1.0 | 1.0 | Passed |
| regression candidate year range 2 | 1.046448087 | 1.046448087 | Passed |
| partial repair probe 1 | 1.0 | 1.0 | Passed |
| partial repair probe 2 | 2.994535519 | 2.994535519 | Passed |
| boundary control 1 | 1.0 | 1.0 | Passed |
| boundary control 2 | 0.24863388 | 0.24863388 | Passed |
| normal control 1 | 0.602739726 | 0.602739726 | Passed |
| normal control 2 | 0.495890411 | 0.495890411 | Passed |
SHA-256 / c0443261084dbcae7d6769b0648082c9aff1f2879028faa6bdfcf24d447a70bd
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:50.510902+00:00.
Case digest / 8f77aa6dfd3fe4b064cbc6513130d96c75d9291c595405e943c26029aec3a5cf