FA-60936 / Bond day-count conventions / Open access
Act/365L denominator selection: a period starting on 29 February uses a 366-day year · case 01
Annual periods beginning on a leap day and periods ending on one are classified the wrong way round.
ROOT CAUSE
The leap-day membership test uses [start, end) instead of (start, end].
VERIFIED REPAIR
Count 29 February only when start < 29 Feb <= end.
Unsuccessful approach: Closing both ends still counts a 29 February start date.
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 + 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 february 29 interval ends 1', [[2023, 2, 28], [2024, 2, 29], 1], 1.0], ['regression february 29 interval ends 2', [[2028, 2, 29], [2029, 2, 28], 1], 1.0], ['partial repair probe 1', [[2104, 2, 29], [2106, 2, 28], 1], 2.0], ['partial repair probe 2', [[1996, 2, 29], [1997, 6, 27], 1], 1.326027397], ['boundary control 1', [[2024, 11, 15], [2025, 2, 15], 4], 0.252054795], ['boundary control 2', [[2023, 3, 1], [2024, 3, 1], 1], 1.0], ['normal control 1', [[2071, 8, 3], [2072, 12, 10], 1], 1.352459016], ['normal control 2', [[2027, 12, 29], [2030, 12, 29], 1], 2.994535519]], [['regression february 29 interval ends 1', [[2096, 2, 29], [2099, 2, 28], 1], 3.0], ['regression february 29 interval ends 2', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['partial repair probe 1', [[2000, 2, 29], [2001, 6, 25], 1], 1.320547945], ['boundary control 1', [[2023, 3, 1], [2024, 3, 1], 1], 1.0], ['boundary control 2', [[2024, 11, 15], [2025, 2, 15], 4], 0.252054795], ['normal control 1', [[2028, 12, 15], [2029, 3, 15], 4], 0.246575342], ['normal control 2', [[2077, 12, 6], [2078, 9, 23], 1], 0.797260274], ['normal control 3', [[2025, 4, 30], [2026, 4, 30], 1], 1.0]], [['regression february 29 interval ends 1', [[2096, 2, 29], [2097, 2, 28], 1], 1.0], ['regression february 29 interval ends 2', [[2096, 2, 29], [2096, 6, 30], 1], 0.334246575], ['partial repair probe 1', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['partial repair probe 2', [[2104, 2, 29], [2105, 2, 28], 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', [[1935, 3, 4], [1936, 3, 12], 4], 1.021857923], ['normal control 2', [[2024, 3, 29], [2024, 9, 29], 4], 0.50273224]], [['regression february 29 interval ends 1', [[2024, 2, 29], [2027, 2, 28], 1], 3.0], ['regression february 29 interval ends 2', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['partial repair probe 1', [[1996, 2, 29], [1996, 4, 30], 1], 0.167123288], ['partial repair probe 2', [[2024, 2, 29], [2025, 4, 23], 1], 1.147945205], ['boundary control 1', [[2023, 3, 1], [2024, 3, 1], 1], 1.0], ['boundary control 2', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['normal control 1', [[2103, 12, 29], [2104, 3, 29], 4], 0.24863388], ['normal control 2', [[2076, 11, 19], [2077, 11, 19], 1], 1.0]], [['regression february 29 interval ends 1', [[2048, 2, 29], [2049, 2, 28], 1], 1.0], ['regression february 29 interval ends 2', [[2023, 2, 28], [2024, 2, 29], 1], 1.0], ['partial repair probe 1', [[1980, 2, 29], [1981, 2, 28], 1], 1.0], ['partial repair probe 2', [[2028, 2, 29], [2030, 2, 28], 1], 2.0], ['boundary control 1', [[2023, 3, 1], [2024, 3, 1], 1], 1.0], ['boundary control 2', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['normal control 1', [[1896, 1, 30], [1896, 4, 30], 4], 0.24863388], ['normal control 2', [[2015, 3, 17], [2016, 3, 17], 1], 1.0]]]
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 february 29 interval ends 1 | 1.002739726 | 1.0 | Failed |
| regression february 29 interval ends 2 | 0.99726776 | 1.0 | Failed |
| partial repair probe 1 | 1.994535519 | 2.0 | Failed |
| partial repair probe 2 | 1.322404372 | 1.326027397 | Failed |
| boundary control 1 | 0.252054795 | 0.252054795 | Passed |
| boundary control 2 | 1.0 | 1.0 | Passed |
| normal control 1 | 1.352459016 | 1.352459016 | Passed |
| normal control 2 | 2.994535519 | 2.994535519 | Passed |
SHA-256 / b947b526f2540242fc9ef05c64872810ab5a1383d65215153677ac397b008be4
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, 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 february 29 interval ends 1', [[2023, 2, 28], [2024, 2, 29], 1], 1.0], ['regression february 29 interval ends 2', [[2028, 2, 29], [2029, 2, 28], 1], 1.0], ['partial repair probe 1', [[2104, 2, 29], [2106, 2, 28], 1], 2.0], ['partial repair probe 2', [[1996, 2, 29], [1997, 6, 27], 1], 1.326027397], ['boundary control 1', [[2024, 11, 15], [2025, 2, 15], 4], 0.252054795], ['boundary control 2', [[2023, 3, 1], [2024, 3, 1], 1], 1.0], ['normal control 1', [[2071, 8, 3], [2072, 12, 10], 1], 1.352459016], ['normal control 2', [[2027, 12, 29], [2030, 12, 29], 1], 2.994535519]], [['regression february 29 interval ends 1', [[2096, 2, 29], [2099, 2, 28], 1], 3.0], ['regression february 29 interval ends 2', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['partial repair probe 1', [[2000, 2, 29], [2001, 6, 25], 1], 1.320547945], ['boundary control 1', [[2023, 3, 1], [2024, 3, 1], 1], 1.0], ['boundary control 2', [[2024, 11, 15], [2025, 2, 15], 4], 0.252054795], ['normal control 1', [[2028, 12, 15], [2029, 3, 15], 4], 0.246575342], ['normal control 2', [[2077, 12, 6], [2078, 9, 23], 1], 0.797260274], ['normal control 3', [[2025, 4, 30], [2026, 4, 30], 1], 1.0]], [['regression february 29 interval ends 1', [[2096, 2, 29], [2097, 2, 28], 1], 1.0], ['regression february 29 interval ends 2', [[2096, 2, 29], [2096, 6, 30], 1], 0.334246575], ['partial repair probe 1', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['partial repair probe 2', [[2104, 2, 29], [2105, 2, 28], 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', [[1935, 3, 4], [1936, 3, 12], 4], 1.021857923], ['normal control 2', [[2024, 3, 29], [2024, 9, 29], 4], 0.50273224]], [['regression february 29 interval ends 1', [[2024, 2, 29], [2027, 2, 28], 1], 3.0], ['regression february 29 interval ends 2', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['partial repair probe 1', [[1996, 2, 29], [1996, 4, 30], 1], 0.167123288], ['partial repair probe 2', [[2024, 2, 29], [2025, 4, 23], 1], 1.147945205], ['boundary control 1', [[2023, 3, 1], [2024, 3, 1], 1], 1.0], ['boundary control 2', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['normal control 1', [[2103, 12, 29], [2104, 3, 29], 4], 0.24863388], ['normal control 2', [[2076, 11, 19], [2077, 11, 19], 1], 1.0]], [['regression february 29 interval ends 1', [[2048, 2, 29], [2049, 2, 28], 1], 1.0], ['regression february 29 interval ends 2', [[2023, 2, 28], [2024, 2, 29], 1], 1.0], ['partial repair probe 1', [[1980, 2, 29], [1981, 2, 28], 1], 1.0], ['partial repair probe 2', [[2028, 2, 29], [2030, 2, 28], 1], 2.0], ['boundary control 1', [[2023, 3, 1], [2024, 3, 1], 1], 1.0], ['boundary control 2', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['normal control 1', [[1896, 1, 30], [1896, 4, 30], 4], 0.24863388], ['normal control 2', [[2015, 3, 17], [2016, 3, 17], 1], 1.0]]]
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 february 29 interval ends 1 | 1.0 | 1.0 | Passed |
| regression february 29 interval ends 2 | 0.99726776 | 1.0 | Failed |
| partial repair probe 1 | 1.994535519 | 2.0 | Failed |
| partial repair probe 2 | 1.322404372 | 1.326027397 | Failed |
| boundary control 1 | 0.252054795 | 0.252054795 | Passed |
| boundary control 2 | 1.0 | 1.0 | Passed |
| normal control 1 | 1.352459016 | 1.352459016 | Passed |
| normal control 2 | 2.994535519 | 2.994535519 | Passed |
SHA-256 / e1165ed204b96415d72ae2824ac08cd20422c3f11b7a5197ac9fe530d6f21b0d
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 february 29 interval ends 1', [[2023, 2, 28], [2024, 2, 29], 1], 1.0], ['regression february 29 interval ends 2', [[2028, 2, 29], [2029, 2, 28], 1], 1.0], ['partial repair probe 1', [[2104, 2, 29], [2106, 2, 28], 1], 2.0], ['partial repair probe 2', [[1996, 2, 29], [1997, 6, 27], 1], 1.326027397], ['boundary control 1', [[2024, 11, 15], [2025, 2, 15], 4], 0.252054795], ['boundary control 2', [[2023, 3, 1], [2024, 3, 1], 1], 1.0], ['normal control 1', [[2071, 8, 3], [2072, 12, 10], 1], 1.352459016], ['normal control 2', [[2027, 12, 29], [2030, 12, 29], 1], 2.994535519]], [['regression february 29 interval ends 1', [[2096, 2, 29], [2099, 2, 28], 1], 3.0], ['regression february 29 interval ends 2', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['partial repair probe 1', [[2000, 2, 29], [2001, 6, 25], 1], 1.320547945], ['boundary control 1', [[2023, 3, 1], [2024, 3, 1], 1], 1.0], ['boundary control 2', [[2024, 11, 15], [2025, 2, 15], 4], 0.252054795], ['normal control 1', [[2028, 12, 15], [2029, 3, 15], 4], 0.246575342], ['normal control 2', [[2077, 12, 6], [2078, 9, 23], 1], 0.797260274], ['normal control 3', [[2025, 4, 30], [2026, 4, 30], 1], 1.0]], [['regression february 29 interval ends 1', [[2096, 2, 29], [2097, 2, 28], 1], 1.0], ['regression february 29 interval ends 2', [[2096, 2, 29], [2096, 6, 30], 1], 0.334246575], ['partial repair probe 1', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['partial repair probe 2', [[2104, 2, 29], [2105, 2, 28], 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', [[1935, 3, 4], [1936, 3, 12], 4], 1.021857923], ['normal control 2', [[2024, 3, 29], [2024, 9, 29], 4], 0.50273224]], [['regression february 29 interval ends 1', [[2024, 2, 29], [2027, 2, 28], 1], 3.0], ['regression february 29 interval ends 2', [[2024, 2, 29], [2025, 2, 28], 1], 1.0], ['partial repair probe 1', [[1996, 2, 29], [1996, 4, 30], 1], 0.167123288], ['partial repair probe 2', [[2024, 2, 29], [2025, 4, 23], 1], 1.147945205], ['boundary control 1', [[2023, 3, 1], [2024, 3, 1], 1], 1.0], ['boundary control 2', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['normal control 1', [[2103, 12, 29], [2104, 3, 29], 4], 0.24863388], ['normal control 2', [[2076, 11, 19], [2077, 11, 19], 1], 1.0]], [['regression february 29 interval ends 1', [[2048, 2, 29], [2049, 2, 28], 1], 1.0], ['regression february 29 interval ends 2', [[2023, 2, 28], [2024, 2, 29], 1], 1.0], ['partial repair probe 1', [[1980, 2, 29], [1981, 2, 28], 1], 1.0], ['partial repair probe 2', [[2028, 2, 29], [2030, 2, 28], 1], 2.0], ['boundary control 1', [[2023, 3, 1], [2024, 3, 1], 1], 1.0], ['boundary control 2', [[2023, 12, 15], [2024, 3, 15], 4], 0.24863388], ['normal control 1', [[1896, 1, 30], [1896, 4, 30], 4], 0.24863388], ['normal control 2', [[2015, 3, 17], [2016, 3, 17], 1], 1.0]]]
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 february 29 interval ends 1 | 1.0 | 1.0 | Passed |
| regression february 29 interval ends 2 | 1.0 | 1.0 | Passed |
| partial repair probe 1 | 2.0 | 2.0 | Passed |
| partial repair probe 2 | 1.326027397 | 1.326027397 | Passed |
| boundary control 1 | 0.252054795 | 0.252054795 | Passed |
| boundary control 2 | 1.0 | 1.0 | Passed |
| normal control 1 | 1.352459016 | 1.352459016 | Passed |
| normal control 2 | 2.994535519 | 2.994535519 | Passed |
SHA-256 / bdae5fd37ea6c661b981e68b3bbc0f317e3aaa4d6c8afe5bb7b443322ca44645
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.292701+00:00.
Case digest / de254554e39c018b705e59a20ed67cad1850e8a3072bd0b5715bf21d8ef72fc2