FAILURE MAP
← Case archive

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.

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

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 fixtureActualExpectedOutcome
regression candidate year range 11.0027397261.0Failed
regression candidate year range 21.0493150681.046448087Failed
partial repair probe 11.01.0Passed
partial repair probe 22.9945355192.994535519Passed
boundary control 11.01.0Passed
boundary control 20.248633880.24863388Passed
normal control 10.6027397260.602739726Passed
normal control 20.4958904110.495890411Passed

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 fixtureActualExpectedOutcome
regression candidate year range 11.01.0Passed
regression candidate year range 21.0464480871.046448087Passed
partial repair probe 11.0027397261.0Failed
partial repair probe 23.0027397262.994535519Failed
boundary control 11.01.0Passed
boundary control 20.248633880.24863388Passed
normal control 10.6027397260.602739726Passed
normal control 20.4958904110.495890411Passed

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 fixtureActualExpectedOutcome
regression candidate year range 11.01.0Passed
regression candidate year range 21.0464480871.046448087Passed
partial repair probe 11.01.0Passed
partial repair probe 22.9945355192.994535519Passed
boundary control 11.01.0Passed
boundary control 20.248633880.24863388Passed
normal control 10.6027397260.602739726Passed
normal control 20.4958904110.495890411Passed

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