FAILURE MAP
← Case archive

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

Rate conversion across day-count basis and compounding: the basis ratio is inverted · case 01

Converting an Act/360 rate to Act/365 lowers it instead of raising it.

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

ROOT CAUSE

The rescaling multiplies by from_basis/to_basis.

VERIFIED REPAIR

Multiply by to_basis/from_basis so interest per day is preserved.

Unsuccessful approach: Hard-coding the 360-to-365 case ignores conversions in the other direction.

Case contract

Inputs a nominal rate, from/to day-count year basis (360 or 365), from/to compounding frequency (0 = continuous). First rescale the nominal rate by to_basis/from_basis, then convert compounding through the effective annual rate: EAR = (1+r/m)^m - 1 or e^r - 1; target nominal = m*((1+EAR)^(1/m)-1) or ln(1+EAR). Return rounded to 10 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 math
N = 1
observations = []
def solve(rate, from_basis, to_basis, from_comp, to_comp):
    def ear(r, m):
        return math.exp(r) - 1 if m == 0 else (1 + r / m) ** m - 1
    def nominal(e, m):
        return math.log(1 + e) if m == 0 else m * ((1 + e) ** (1 / m) - 1)
    scaled = rate * from_basis / to_basis
    return round(nominal(ear(scaled, from_comp), to_comp), 10)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression basis ratio direction 1', [0.0475, 365, 360, 4, 12], 0.0466675911], ['regression basis ratio direction 2', [0.0475, 365, 360, 12, 1], 0.047868499], ['partial repair probe 1', [0.0125, 360, 360, 0, 0], 0.0125], ['partial repair probe 2', [0.0125, 360, 360, 2, 1], 0.0125390625], ['boundary control 1', [0.05, 365, 365, 0, 0], 0.05], ['normal control 1', [0.0125, 365, 365, 12, 12], 0.0125], ['normal control 2', [0.08, 365, 365, 0, 4], 0.0808053601], ['normal control 3', [0.03, 365, 365, 12, 4], 0.0300750625]], [['regression basis ratio direction 1', [0.03, 360, 365, 12, 12], 0.0304166667], ['regression basis ratio direction 2', [0.001, 365, 360, 1, 12], 0.0009858558], ['partial repair probe 1', [0.08, 360, 360, 1, 4], 0.0777061876], ['partial repair probe 2', [0.15, 360, 360, 4, 2], 0.1528125], ['boundary control 1', [0.05, 365, 365, 0, 0], 0.05], ['normal control 1', [0.08, 365, 365, 1, 4], 0.0777061876], ['normal control 2', [0.0125, 365, 365, 4, 0], 0.0124805093], ['normal control 3', [0.15, 365, 365, 2, 12], 0.1455165491]], [['regression basis ratio direction 1', [0.001, 365, 360, 12, 12], 0.0009863014], ['regression basis ratio direction 2', [0.03, 365, 360, 4, 1], 0.0299189799], ['partial repair probe 1', [0.0125, 360, 360, 4, 0], 0.0124805093], ['partial repair probe 2', [0.0125, 360, 360, 4, 2], 0.0125195313], ['boundary control 1', [0.05, 365, 365, 0, 0], 0.05], ['normal control 1', [0.0475, 365, 365, 2, 0], 0.0469447124], ['normal control 2', [0.03, 365, 365, 2, 4], 0.0298883359], ['normal control 3', [0.001, 365, 365, 2, 12], 0.0009997917]], [['regression basis ratio direction 1', [0.0475, 365, 360, 1, 12], 0.0458724565], ['regression basis ratio direction 2', [0.03, 365, 360, 4, 4], 0.0295890411], ['partial repair probe 1', [0.0475, 360, 360, 2, 2], 0.0475], ['partial repair probe 2', [0.001, 360, 360, 0, 1], 0.0010005002], ['boundary control 1', [0.05, 365, 365, 0, 0], 0.05], ['normal control 1', [0.03, 365, 365, 4, 12], 0.0299253109], ['normal control 2', [0.0125, 365, 365, 12, 1], 0.0125718638], ['normal control 3', [0.15, 365, 365, 1, 1], 0.15]], [['regression basis ratio direction 1', [0.0475, 360, 365, 2, 2], 0.0481597222], ['regression basis ratio direction 2', [0.001, 365, 360, 1, 0], 0.0009858153], ['partial repair probe 1', [0.03, 360, 360, 12, 4], 0.0300750625], ['partial repair probe 2', [0.0125, 360, 360, 4, 2], 0.0125195313], ['boundary control 1', [0.05, 365, 365, 0, 0], 0.05], ['normal control 1', [0.15, 365, 365, 0, 4], 0.1528479883], ['normal control 2', [0.001, 365, 365, 1, 4], 0.0009996252], ['normal control 3', [0.15, 365, 365, 4, 4], 0.15]]]
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 basis ratio direction 10.04796772490.0466675911Failed
regression basis ratio direction 20.0492371120.047868499Failed
partial repair probe 10.01250.0125Passed
partial repair probe 20.01253906250.0125390625Passed
boundary control 10.050.05Passed
normal control 10.01250.0125Passed
normal control 20.08080536010.0808053601Passed
normal control 30.03007506250.0300750625Passed

SHA-256 / 714f5842fd932730e35cbc8d831e28eac24d446d124be612358fd1380a9835b4

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(rate, from_basis, to_basis, from_comp, to_comp):
    def ear(r, m):
        return math.exp(r) - 1 if m == 0 else (1 + r / m) ** m - 1
    def nominal(e, m):
        return math.log(1 + e) if m == 0 else m * ((1 + e) ** (1 / m) - 1)
    scaled = rate * 365 / 360 if from_basis == 360 else rate
    return round(nominal(ear(scaled, from_comp), to_comp), 10)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression basis ratio direction 1', [0.0475, 365, 360, 4, 12], 0.0466675911], ['regression basis ratio direction 2', [0.0475, 365, 360, 12, 1], 0.047868499], ['partial repair probe 1', [0.0125, 360, 360, 0, 0], 0.0125], ['partial repair probe 2', [0.0125, 360, 360, 2, 1], 0.0125390625], ['boundary control 1', [0.05, 365, 365, 0, 0], 0.05], ['normal control 1', [0.0125, 365, 365, 12, 12], 0.0125], ['normal control 2', [0.08, 365, 365, 0, 4], 0.0808053601], ['normal control 3', [0.03, 365, 365, 12, 4], 0.0300750625]], [['regression basis ratio direction 1', [0.03, 360, 365, 12, 12], 0.0304166667], ['regression basis ratio direction 2', [0.001, 365, 360, 1, 12], 0.0009858558], ['partial repair probe 1', [0.08, 360, 360, 1, 4], 0.0777061876], ['partial repair probe 2', [0.15, 360, 360, 4, 2], 0.1528125], ['boundary control 1', [0.05, 365, 365, 0, 0], 0.05], ['normal control 1', [0.08, 365, 365, 1, 4], 0.0777061876], ['normal control 2', [0.0125, 365, 365, 4, 0], 0.0124805093], ['normal control 3', [0.15, 365, 365, 2, 12], 0.1455165491]], [['regression basis ratio direction 1', [0.001, 365, 360, 12, 12], 0.0009863014], ['regression basis ratio direction 2', [0.03, 365, 360, 4, 1], 0.0299189799], ['partial repair probe 1', [0.0125, 360, 360, 4, 0], 0.0124805093], ['partial repair probe 2', [0.0125, 360, 360, 4, 2], 0.0125195313], ['boundary control 1', [0.05, 365, 365, 0, 0], 0.05], ['normal control 1', [0.0475, 365, 365, 2, 0], 0.0469447124], ['normal control 2', [0.03, 365, 365, 2, 4], 0.0298883359], ['normal control 3', [0.001, 365, 365, 2, 12], 0.0009997917]], [['regression basis ratio direction 1', [0.0475, 365, 360, 1, 12], 0.0458724565], ['regression basis ratio direction 2', [0.03, 365, 360, 4, 4], 0.0295890411], ['partial repair probe 1', [0.0475, 360, 360, 2, 2], 0.0475], ['partial repair probe 2', [0.001, 360, 360, 0, 1], 0.0010005002], ['boundary control 1', [0.05, 365, 365, 0, 0], 0.05], ['normal control 1', [0.03, 365, 365, 4, 12], 0.0299253109], ['normal control 2', [0.0125, 365, 365, 12, 1], 0.0125718638], ['normal control 3', [0.15, 365, 365, 1, 1], 0.15]], [['regression basis ratio direction 1', [0.0475, 360, 365, 2, 2], 0.0481597222], ['regression basis ratio direction 2', [0.001, 365, 360, 1, 0], 0.0009858153], ['partial repair probe 1', [0.03, 360, 360, 12, 4], 0.0300750625], ['partial repair probe 2', [0.0125, 360, 360, 4, 2], 0.0125195313], ['boundary control 1', [0.05, 365, 365, 0, 0], 0.05], ['normal control 1', [0.15, 365, 365, 0, 4], 0.1528479883], ['normal control 2', [0.001, 365, 365, 1, 4], 0.0009996252], ['normal control 3', [0.15, 365, 365, 4, 4], 0.15]]]
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 basis ratio direction 10.04731320980.0466675911Failed
regression basis ratio direction 20.04854788140.047868499Failed
partial repair probe 10.01267361110.0125Failed
partial repair probe 20.01271376620.0125390625Failed
boundary control 10.050.05Passed
normal control 10.01250.0125Passed
normal control 20.08080536010.0808053601Passed
normal control 30.03007506250.0300750625Passed

SHA-256 / 7b9348638930ce4abe622b42228d6c19f05cc27966766766bd309473271cb49d

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(rate, from_basis, to_basis, from_comp, to_comp):
    def ear(r, m):
        return math.exp(r) - 1 if m == 0 else (1 + r / m) ** m - 1
    def nominal(e, m):
        return math.log(1 + e) if m == 0 else m * ((1 + e) ** (1 / m) - 1)
    scaled = rate * to_basis / from_basis
    return round(nominal(ear(scaled, from_comp), to_comp), 10)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression basis ratio direction 1', [0.0475, 365, 360, 4, 12], 0.0466675911], ['regression basis ratio direction 2', [0.0475, 365, 360, 12, 1], 0.047868499], ['partial repair probe 1', [0.0125, 360, 360, 0, 0], 0.0125], ['partial repair probe 2', [0.0125, 360, 360, 2, 1], 0.0125390625], ['boundary control 1', [0.05, 365, 365, 0, 0], 0.05], ['normal control 1', [0.0125, 365, 365, 12, 12], 0.0125], ['normal control 2', [0.08, 365, 365, 0, 4], 0.0808053601], ['normal control 3', [0.03, 365, 365, 12, 4], 0.0300750625]], [['regression basis ratio direction 1', [0.03, 360, 365, 12, 12], 0.0304166667], ['regression basis ratio direction 2', [0.001, 365, 360, 1, 12], 0.0009858558], ['partial repair probe 1', [0.08, 360, 360, 1, 4], 0.0777061876], ['partial repair probe 2', [0.15, 360, 360, 4, 2], 0.1528125], ['boundary control 1', [0.05, 365, 365, 0, 0], 0.05], ['normal control 1', [0.08, 365, 365, 1, 4], 0.0777061876], ['normal control 2', [0.0125, 365, 365, 4, 0], 0.0124805093], ['normal control 3', [0.15, 365, 365, 2, 12], 0.1455165491]], [['regression basis ratio direction 1', [0.001, 365, 360, 12, 12], 0.0009863014], ['regression basis ratio direction 2', [0.03, 365, 360, 4, 1], 0.0299189799], ['partial repair probe 1', [0.0125, 360, 360, 4, 0], 0.0124805093], ['partial repair probe 2', [0.0125, 360, 360, 4, 2], 0.0125195313], ['boundary control 1', [0.05, 365, 365, 0, 0], 0.05], ['normal control 1', [0.0475, 365, 365, 2, 0], 0.0469447124], ['normal control 2', [0.03, 365, 365, 2, 4], 0.0298883359], ['normal control 3', [0.001, 365, 365, 2, 12], 0.0009997917]], [['regression basis ratio direction 1', [0.0475, 365, 360, 1, 12], 0.0458724565], ['regression basis ratio direction 2', [0.03, 365, 360, 4, 4], 0.0295890411], ['partial repair probe 1', [0.0475, 360, 360, 2, 2], 0.0475], ['partial repair probe 2', [0.001, 360, 360, 0, 1], 0.0010005002], ['boundary control 1', [0.05, 365, 365, 0, 0], 0.05], ['normal control 1', [0.03, 365, 365, 4, 12], 0.0299253109], ['normal control 2', [0.0125, 365, 365, 12, 1], 0.0125718638], ['normal control 3', [0.15, 365, 365, 1, 1], 0.15]], [['regression basis ratio direction 1', [0.0475, 360, 365, 2, 2], 0.0481597222], ['regression basis ratio direction 2', [0.001, 365, 360, 1, 0], 0.0009858153], ['partial repair probe 1', [0.03, 360, 360, 12, 4], 0.0300750625], ['partial repair probe 2', [0.0125, 360, 360, 4, 2], 0.0125195313], ['boundary control 1', [0.05, 365, 365, 0, 0], 0.05], ['normal control 1', [0.15, 365, 365, 0, 4], 0.1528479883], ['normal control 2', [0.001, 365, 365, 1, 4], 0.0009996252], ['normal control 3', [0.15, 365, 365, 4, 4], 0.15]]]
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 basis ratio direction 10.04666759110.0466675911Passed
regression basis ratio direction 20.0478684990.047868499Passed
partial repair probe 10.01250.0125Passed
partial repair probe 20.01253906250.0125390625Passed
boundary control 10.050.05Passed
normal control 10.01250.0125Passed
normal control 20.08080536010.0808053601Passed
normal control 30.03007506250.0300750625Passed

SHA-256 / d8f8cbfa3a80ca6c220632f418014db47b7791804bcea4281202d332776021d7

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.780912+00:00.

Case digest / 31d8364521c6598e01dfa5926935050dc259e806854d9fcfc4019e3ad25db862