FAILURE MAP
← Case archive

FA-84566 / Betting odds conversion / Open access

Stake cap applied before the Kelly multiplier · case 01

Half-Kelly stakes are halved again after capping, or the multiplier is ignored.

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

ROOT CAUSE

The cap is applied to the full Kelly fraction and then scaled by the multiplier.

VERIFIED REPAIR

Scale by the Kelly multiplier first, then cap.

Unsuccessful approach: Capping the full Kelly fraction and ignoring the multiplier overstakes fractional Kelly users.

Case contract

Kelly staking. With b = price - 1, p = prob and q = 1 - p, the full Kelly fraction is (b * p - q) / b, floored at 0 when the edge is not positive. The stake is bankroll * min(full Kelly * fraction, max_pct / 100), rounded down to a cent. Return [full Kelly fraction rounded half up to four decimals as a string, stake cents].

Why this case matters

Bankroll tools size stakes with fractional Kelly and a hard cap.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
import math
N = 1
observations = []
def solve(prob, price, fraction, bankroll_cents, max_pct):
    p = Fraction(prob)
    b = Fraction(price) - 1
    q = 1 - p
    k = (b * p - q) / b
    if k < 0:
        k = Fraction(0)
    use = min(k, Fraction(max_pct) / 100) * Fraction(fraction)
    stake = math.floor(bankroll_cents * use)
    r = math.floor(k * 10000 + Fraction(1, 2))
    return ['%d.%04d' % (r // 10000, r % 10000), stake]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
def run(args):
    try:
        return solve(*args)
    except Exception as exc:
        return 'raised ' + type(exc).__name__
cases = [[('control even-money edge', ('0.55', '2.00', '1', 100000, '100'), ['0.1000', 10000]),
  ('control half kelly', ('0.55', '2.00', '0.5', 100000, '100'), ['0.1000', 5000]),
  ('boundary capped stake', ('0.60', '2.00', '1', 100000, '5'), ['0.2000', 5000]),
  ('boundary no edge', ('0.40', '2.00', '1', 100000, '5'), ['0.0000', 0]),
  ('control underdog edge', ('0.30', '4.00', '1', 100000, '100'), ['0.0667', 6666]),
  ('regression: cap order', ('0.55', '3.08', '0.5', 100000, '5'), ['0.3337', 5000]),
  ('regression: cap order', ('0.55', '2.51', '0.25', 100000, '100'), ['0.2520', 6299]),
  ('variant scenario 1', ('0.55', '3.41', '0.5', 50000, '5'), ['0.3633', 2500]),
  ('variant scenario 2', ('0.76', '5.95', '0.25', 100000, '10'), ['0.7115', 10000])],
 [('control even-money edge', ('0.55', '2.00', '1', 100000, '100'), ['0.1000', 10000]),
  ('control half kelly', ('0.55', '2.00', '0.5', 100000, '100'), ['0.1000', 5000]),
  ('boundary capped stake', ('0.60', '2.00', '1', 100000, '5'), ['0.2000', 5000]),
  ('boundary no edge', ('0.40', '2.00', '1', 100000, '5'), ['0.0000', 0]),
  ('control underdog edge', ('0.30', '4.00', '1', 100000, '100'), ['0.0667', 6666]),
  ('regression: cap order', ('0.65', '4.43', '0.25', 100000, '5'), ['0.5480', 5000]),
  ('regression: cap order', ('0.40', '5.78', '0.25', 50000, '10'), ['0.2745', 3430]),
  ('variant scenario 1', ('0.50', '2.74', '1', 100000, '10'), ['0.2126', 10000]),
  ('variant scenario 2', ('0.50', '1.57', '0.5', 12345, '5'), ['0.0000', 0])],
 [('control even-money edge', ('0.55', '2.00', '1', 100000, '100'), ['0.1000', 10000]),
  ('control half kelly', ('0.55', '2.00', '0.5', 100000, '100'), ['0.1000', 5000]),
  ('boundary capped stake', ('0.60', '2.00', '1', 100000, '5'), ['0.2000', 5000]),
  ('boundary no edge', ('0.40', '2.00', '1', 100000, '5'), ['0.0000', 0]),
  ('control underdog edge', ('0.30', '4.00', '1', 100000, '100'), ['0.0667', 6666]),
  ('regression: cap order', ('0.50', '3.97', '0.25', 50000, '100'), ['0.3316', 4145]),
  ('regression: cap order', ('0.55', '4.19', '0.25', 100000, '10'), ['0.4089', 10000]),
  ('variant scenario 1', ('0.55', '3.12', '1', 50000, '5'), ['0.3377', 2500]),
  ('variant scenario 2', ('0.55', '4.80', '1', 50000, '100'), ['0.4316', 21578])],
 [('control even-money edge', ('0.55', '2.00', '1', 100000, '100'), ['0.1000', 10000]),
  ('control half kelly', ('0.55', '2.00', '0.5', 100000, '100'), ['0.1000', 5000]),
  ('boundary capped stake', ('0.60', '2.00', '1', 100000, '5'), ['0.2000', 5000]),
  ('boundary no edge', ('0.40', '2.00', '1', 100000, '5'), ['0.0000', 0]),
  ('control underdog edge', ('0.30', '4.00', '1', 100000, '100'), ['0.0667', 6666]),
  ('regression: cap order', ('0.50', '3.30', '0.5', 50000, '2'), ['0.2826', 1000]),
  ('regression: cap order', ('0.50', '5.60', '0.5', 50000, '100'), ['0.3913', 9782]),
  ('variant scenario 1', ('0.50', '3.50', '0.25', 50000, '5'), ['0.3000', 2500]),
  ('variant scenario 2', ('0.60', '4.06', '1', 12345, '2'), ['0.4693', 246])],
 [('control even-money edge', ('0.55', '2.00', '1', 100000, '100'), ['0.1000', 10000]),
  ('control half kelly', ('0.55', '2.00', '0.5', 100000, '100'), ['0.1000', 5000]),
  ('boundary capped stake', ('0.60', '2.00', '1', 100000, '5'), ['0.2000', 5000]),
  ('boundary no edge', ('0.40', '2.00', '1', 100000, '5'), ['0.0000', 0]),
  ('control underdog edge', ('0.30', '4.00', '1', 100000, '100'), ['0.0667', 6666]),
  ('regression: cap order', ('0.55', '2.71', '0.25', 50000, '2'), ['0.2868', 1000]),
  ('regression: cap order', ('0.79', '4.28', '0.5', 100000, '100'), ['0.7260', 36298]),
  ('variant scenario 1', ('0.57', '5.73', '0.25', 50000, '5'), ['0.4791', 2500]),
  ('variant scenario 2', ('0.60', '2.44', '1', 12345, '2'), ['0.3222', 246])]]
for label, args, expected in cases[N - 1]:
    check(label, run(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
control even-money edge['0.1000', 10000]['0.1000', 10000]Passed
control half kelly['0.1000', 5000]['0.1000', 5000]Passed
boundary capped stake['0.2000', 5000]['0.2000', 5000]Passed
boundary no edge['0.0000', 0]['0.0000', 0]Passed
control underdog edge['0.0667', 6666]['0.0667', 6666]Passed
regression: cap order['0.3337', 2500]['0.3337', 5000]Failed
regression: cap order['0.2520', 6299]['0.2520', 6299]Passed
variant scenario 1['0.3633', 1250]['0.3633', 2500]Failed
variant scenario 2['0.7115', 2500]['0.7115', 10000]Failed

SHA-256 / bba164f3cbffea41b8f373f933deea2d4d0fa67bd35542eb25bd65fc08a1fe4a

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
import math
N = 1
observations = []
def solve(prob, price, fraction, bankroll_cents, max_pct):
    p = Fraction(prob)
    b = Fraction(price) - 1
    q = 1 - p
    k = (b * p - q) / b
    if k < 0:
        k = Fraction(0)
    use = min(k, Fraction(max_pct) / 100)
    stake = math.floor(bankroll_cents * use)
    r = math.floor(k * 10000 + Fraction(1, 2))
    return ['%d.%04d' % (r // 10000, r % 10000), stake]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
def run(args):
    try:
        return solve(*args)
    except Exception as exc:
        return 'raised ' + type(exc).__name__
cases = [[('control even-money edge', ('0.55', '2.00', '1', 100000, '100'), ['0.1000', 10000]),
  ('control half kelly', ('0.55', '2.00', '0.5', 100000, '100'), ['0.1000', 5000]),
  ('boundary capped stake', ('0.60', '2.00', '1', 100000, '5'), ['0.2000', 5000]),
  ('boundary no edge', ('0.40', '2.00', '1', 100000, '5'), ['0.0000', 0]),
  ('control underdog edge', ('0.30', '4.00', '1', 100000, '100'), ['0.0667', 6666]),
  ('regression: cap order', ('0.55', '3.08', '0.5', 100000, '5'), ['0.3337', 5000]),
  ('regression: cap order', ('0.55', '2.51', '0.25', 100000, '100'), ['0.2520', 6299]),
  ('variant scenario 1', ('0.55', '3.41', '0.5', 50000, '5'), ['0.3633', 2500]),
  ('variant scenario 2', ('0.76', '5.95', '0.25', 100000, '10'), ['0.7115', 10000])],
 [('control even-money edge', ('0.55', '2.00', '1', 100000, '100'), ['0.1000', 10000]),
  ('control half kelly', ('0.55', '2.00', '0.5', 100000, '100'), ['0.1000', 5000]),
  ('boundary capped stake', ('0.60', '2.00', '1', 100000, '5'), ['0.2000', 5000]),
  ('boundary no edge', ('0.40', '2.00', '1', 100000, '5'), ['0.0000', 0]),
  ('control underdog edge', ('0.30', '4.00', '1', 100000, '100'), ['0.0667', 6666]),
  ('regression: cap order', ('0.65', '4.43', '0.25', 100000, '5'), ['0.5480', 5000]),
  ('regression: cap order', ('0.40', '5.78', '0.25', 50000, '10'), ['0.2745', 3430]),
  ('variant scenario 1', ('0.50', '2.74', '1', 100000, '10'), ['0.2126', 10000]),
  ('variant scenario 2', ('0.50', '1.57', '0.5', 12345, '5'), ['0.0000', 0])],
 [('control even-money edge', ('0.55', '2.00', '1', 100000, '100'), ['0.1000', 10000]),
  ('control half kelly', ('0.55', '2.00', '0.5', 100000, '100'), ['0.1000', 5000]),
  ('boundary capped stake', ('0.60', '2.00', '1', 100000, '5'), ['0.2000', 5000]),
  ('boundary no edge', ('0.40', '2.00', '1', 100000, '5'), ['0.0000', 0]),
  ('control underdog edge', ('0.30', '4.00', '1', 100000, '100'), ['0.0667', 6666]),
  ('regression: cap order', ('0.50', '3.97', '0.25', 50000, '100'), ['0.3316', 4145]),
  ('regression: cap order', ('0.55', '4.19', '0.25', 100000, '10'), ['0.4089', 10000]),
  ('variant scenario 1', ('0.55', '3.12', '1', 50000, '5'), ['0.3377', 2500]),
  ('variant scenario 2', ('0.55', '4.80', '1', 50000, '100'), ['0.4316', 21578])],
 [('control even-money edge', ('0.55', '2.00', '1', 100000, '100'), ['0.1000', 10000]),
  ('control half kelly', ('0.55', '2.00', '0.5', 100000, '100'), ['0.1000', 5000]),
  ('boundary capped stake', ('0.60', '2.00', '1', 100000, '5'), ['0.2000', 5000]),
  ('boundary no edge', ('0.40', '2.00', '1', 100000, '5'), ['0.0000', 0]),
  ('control underdog edge', ('0.30', '4.00', '1', 100000, '100'), ['0.0667', 6666]),
  ('regression: cap order', ('0.50', '3.30', '0.5', 50000, '2'), ['0.2826', 1000]),
  ('regression: cap order', ('0.50', '5.60', '0.5', 50000, '100'), ['0.3913', 9782]),
  ('variant scenario 1', ('0.50', '3.50', '0.25', 50000, '5'), ['0.3000', 2500]),
  ('variant scenario 2', ('0.60', '4.06', '1', 12345, '2'), ['0.4693', 246])],
 [('control even-money edge', ('0.55', '2.00', '1', 100000, '100'), ['0.1000', 10000]),
  ('control half kelly', ('0.55', '2.00', '0.5', 100000, '100'), ['0.1000', 5000]),
  ('boundary capped stake', ('0.60', '2.00', '1', 100000, '5'), ['0.2000', 5000]),
  ('boundary no edge', ('0.40', '2.00', '1', 100000, '5'), ['0.0000', 0]),
  ('control underdog edge', ('0.30', '4.00', '1', 100000, '100'), ['0.0667', 6666]),
  ('regression: cap order', ('0.55', '2.71', '0.25', 50000, '2'), ['0.2868', 1000]),
  ('regression: cap order', ('0.79', '4.28', '0.5', 100000, '100'), ['0.7260', 36298]),
  ('variant scenario 1', ('0.57', '5.73', '0.25', 50000, '5'), ['0.4791', 2500]),
  ('variant scenario 2', ('0.60', '2.44', '1', 12345, '2'), ['0.3222', 246])]]
for label, args, expected in cases[N - 1]:
    check(label, run(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
control even-money edge['0.1000', 10000]['0.1000', 10000]Passed
control half kelly['0.1000', 10000]['0.1000', 5000]Failed
boundary capped stake['0.2000', 5000]['0.2000', 5000]Passed
boundary no edge['0.0000', 0]['0.0000', 0]Passed
control underdog edge['0.0667', 6666]['0.0667', 6666]Passed
regression: cap order['0.3337', 5000]['0.3337', 5000]Passed
regression: cap order['0.2520', 25198]['0.2520', 6299]Failed
variant scenario 1['0.3633', 2500]['0.3633', 2500]Passed
variant scenario 2['0.7115', 10000]['0.7115', 10000]Passed

SHA-256 / 18596b20d6e55cfafe5fab9dfedede3e930d8f5c562595d7b5028244479d728d

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
import math
N = 1
observations = []
def solve(prob, price, fraction, bankroll_cents, max_pct):
    p = Fraction(prob)
    b = Fraction(price) - 1
    q = 1 - p
    k = (b * p - q) / b
    if k < 0:
        k = Fraction(0)
    use = min(k * Fraction(fraction), Fraction(max_pct) / 100)
    stake = math.floor(bankroll_cents * use)
    r = math.floor(k * 10000 + Fraction(1, 2))
    return ['%d.%04d' % (r // 10000, r % 10000), stake]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
def run(args):
    try:
        return solve(*args)
    except Exception as exc:
        return 'raised ' + type(exc).__name__
cases = [[('control even-money edge', ('0.55', '2.00', '1', 100000, '100'), ['0.1000', 10000]),
  ('control half kelly', ('0.55', '2.00', '0.5', 100000, '100'), ['0.1000', 5000]),
  ('boundary capped stake', ('0.60', '2.00', '1', 100000, '5'), ['0.2000', 5000]),
  ('boundary no edge', ('0.40', '2.00', '1', 100000, '5'), ['0.0000', 0]),
  ('control underdog edge', ('0.30', '4.00', '1', 100000, '100'), ['0.0667', 6666]),
  ('regression: cap order', ('0.55', '3.08', '0.5', 100000, '5'), ['0.3337', 5000]),
  ('regression: cap order', ('0.55', '2.51', '0.25', 100000, '100'), ['0.2520', 6299]),
  ('variant scenario 1', ('0.55', '3.41', '0.5', 50000, '5'), ['0.3633', 2500]),
  ('variant scenario 2', ('0.76', '5.95', '0.25', 100000, '10'), ['0.7115', 10000])],
 [('control even-money edge', ('0.55', '2.00', '1', 100000, '100'), ['0.1000', 10000]),
  ('control half kelly', ('0.55', '2.00', '0.5', 100000, '100'), ['0.1000', 5000]),
  ('boundary capped stake', ('0.60', '2.00', '1', 100000, '5'), ['0.2000', 5000]),
  ('boundary no edge', ('0.40', '2.00', '1', 100000, '5'), ['0.0000', 0]),
  ('control underdog edge', ('0.30', '4.00', '1', 100000, '100'), ['0.0667', 6666]),
  ('regression: cap order', ('0.65', '4.43', '0.25', 100000, '5'), ['0.5480', 5000]),
  ('regression: cap order', ('0.40', '5.78', '0.25', 50000, '10'), ['0.2745', 3430]),
  ('variant scenario 1', ('0.50', '2.74', '1', 100000, '10'), ['0.2126', 10000]),
  ('variant scenario 2', ('0.50', '1.57', '0.5', 12345, '5'), ['0.0000', 0])],
 [('control even-money edge', ('0.55', '2.00', '1', 100000, '100'), ['0.1000', 10000]),
  ('control half kelly', ('0.55', '2.00', '0.5', 100000, '100'), ['0.1000', 5000]),
  ('boundary capped stake', ('0.60', '2.00', '1', 100000, '5'), ['0.2000', 5000]),
  ('boundary no edge', ('0.40', '2.00', '1', 100000, '5'), ['0.0000', 0]),
  ('control underdog edge', ('0.30', '4.00', '1', 100000, '100'), ['0.0667', 6666]),
  ('regression: cap order', ('0.50', '3.97', '0.25', 50000, '100'), ['0.3316', 4145]),
  ('regression: cap order', ('0.55', '4.19', '0.25', 100000, '10'), ['0.4089', 10000]),
  ('variant scenario 1', ('0.55', '3.12', '1', 50000, '5'), ['0.3377', 2500]),
  ('variant scenario 2', ('0.55', '4.80', '1', 50000, '100'), ['0.4316', 21578])],
 [('control even-money edge', ('0.55', '2.00', '1', 100000, '100'), ['0.1000', 10000]),
  ('control half kelly', ('0.55', '2.00', '0.5', 100000, '100'), ['0.1000', 5000]),
  ('boundary capped stake', ('0.60', '2.00', '1', 100000, '5'), ['0.2000', 5000]),
  ('boundary no edge', ('0.40', '2.00', '1', 100000, '5'), ['0.0000', 0]),
  ('control underdog edge', ('0.30', '4.00', '1', 100000, '100'), ['0.0667', 6666]),
  ('regression: cap order', ('0.50', '3.30', '0.5', 50000, '2'), ['0.2826', 1000]),
  ('regression: cap order', ('0.50', '5.60', '0.5', 50000, '100'), ['0.3913', 9782]),
  ('variant scenario 1', ('0.50', '3.50', '0.25', 50000, '5'), ['0.3000', 2500]),
  ('variant scenario 2', ('0.60', '4.06', '1', 12345, '2'), ['0.4693', 246])],
 [('control even-money edge', ('0.55', '2.00', '1', 100000, '100'), ['0.1000', 10000]),
  ('control half kelly', ('0.55', '2.00', '0.5', 100000, '100'), ['0.1000', 5000]),
  ('boundary capped stake', ('0.60', '2.00', '1', 100000, '5'), ['0.2000', 5000]),
  ('boundary no edge', ('0.40', '2.00', '1', 100000, '5'), ['0.0000', 0]),
  ('control underdog edge', ('0.30', '4.00', '1', 100000, '100'), ['0.0667', 6666]),
  ('regression: cap order', ('0.55', '2.71', '0.25', 50000, '2'), ['0.2868', 1000]),
  ('regression: cap order', ('0.79', '4.28', '0.5', 100000, '100'), ['0.7260', 36298]),
  ('variant scenario 1', ('0.57', '5.73', '0.25', 50000, '5'), ['0.4791', 2500]),
  ('variant scenario 2', ('0.60', '2.44', '1', 12345, '2'), ['0.3222', 246])]]
for label, args, expected in cases[N - 1]:
    check(label, run(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
control even-money edge['0.1000', 10000]['0.1000', 10000]Passed
control half kelly['0.1000', 5000]['0.1000', 5000]Passed
boundary capped stake['0.2000', 5000]['0.2000', 5000]Passed
boundary no edge['0.0000', 0]['0.0000', 0]Passed
control underdog edge['0.0667', 6666]['0.0667', 6666]Passed
regression: cap order['0.3337', 5000]['0.3337', 5000]Passed
regression: cap order['0.2520', 6299]['0.2520', 6299]Passed
variant scenario 1['0.3633', 2500]['0.3633', 2500]Passed
variant scenario 2['0.7115', 10000]['0.7115', 10000]Passed

SHA-256 / a23cf9a571db1cc6fecf24943513651dbce2decf7ba2131ab89dccc14ede7bc0

Verification & scope

Stipulated, bounded toy contract stated in the contract field; not a claim of conformance with any operator, exchange or regulator rule set. 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:50:32.093548+00:00.

Case digest / 0352e4d1c1dfe8e00cfbf7a577b4d6341b47f762d15bc5458f17122d76a7e686