FA-84541 / Betting odds conversion / Open access
Commission computed on losing markets · case 01
A losing market produces a negative commission refund or a charge on the loss.
ROOT CAUSE
The commission loop has no positive-net guard.
VERIFIED REPAIR
Charge commission only when the market net is positive.
Unsuccessful approach: Charging commission on the absolute net penalises losing markets.
Case contract
Betting exchange settlement. bets rows are [market, side, stake_cents, price, won] where won says whether the bet won. Back: win profit floor(stake * (price - 1)), loss -stake. Lay: win +stake, loss -ceil(stake * (price - 1)) (the liability). Commission is charged per market on the market net profit only when that net is positive, at rate_pct percent rounded half up to a cent. Return [total net after commission, total commission] in cents.
Why this case matters
Exchanges charge commission on net market winnings, not per winning bet.
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(bets, rate_pct):
nets = {}
for market, side, stake, price, won in bets:
p = Fraction(price)
if side == 'back':
pl = math.floor(stake * (p - 1)) if won else -stake
else:
pl = stake if won else -math.ceil(stake * (p - 1))
nets[market] = nets.get(market, 0) + pl
comm = 0
for m, net in nets.items():
comm += math.floor(net * Fraction(rate_pct) / 100 + Fraction(1, 2))
return [sum(nets.values()) - comm, comm]
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 single back winner', ([['m1', 'back', 1000, '3.00', True]], '5'), [1900, 100]),
('boundary hedged market nets out',
([['m1', 'back', 1000, '3.00', True], ['m1', 'lay', 1000, '2.50', False]], '5'),
[475, 25]),
('control lay winner', ([['m2', 'lay', 1000, '4.00', True]], '5'), [950, 50]),
('boundary losing market no commission',
([['m1', 'back', 1000, '3.00', False], ['m1', 'lay', 500, '2.00', True]], '5'),
[-500, 0]),
('regression: loss market commission',
([['m1', 'back', 250, '7.43', True],
['m1', 'back', 250, '5.08', True],
['m2', 'back', 250, '6.10', False]],
'2'),
[2324, 53]),
('variant scenario 1',
([['m1', 'back', 777, '5.62', True], ['m3', 'back', 100, '2.02', False]], '6.5'),
[3256, 233]),
('variant scenario 2', ([['m3', 'lay', 777, '6.38', False]], '2'), [-4181, 0])],
[('control single back winner', ([['m1', 'back', 1000, '3.00', True]], '5'), [1900, 100]),
('boundary hedged market nets out',
([['m1', 'back', 1000, '3.00', True], ['m1', 'lay', 1000, '2.50', False]], '5'),
[475, 25]),
('control lay winner', ([['m2', 'lay', 1000, '4.00', True]], '5'), [950, 50]),
('boundary losing market no commission',
([['m1', 'back', 1000, '3.00', False], ['m1', 'lay', 500, '2.00', True]], '5'),
[-500, 0]),
('regression: loss market commission',
([['m1', 'back', 250, '4.78', False], ['m3', 'lay', 1000, '4.13', False]], '5'),
[-3380, 0]),
('variant scenario 1', ([['m1', 'lay', 2000, '7.96', True]], '5'), [1900, 100]),
('variant scenario 2',
([['m3', 'lay', 2000, '2.30', True],
['m1', 'back', 1000, '2.62', False],
['m1', 'lay', 777, '6.91', False],
['m2', 'back', 100, '2.31', True],
['m1', 'lay', 250, '5.96', True]],
'2'),
[-3255, 43])],
[('control single back winner', ([['m1', 'back', 1000, '3.00', True]], '5'), [1900, 100]),
('boundary hedged market nets out',
([['m1', 'back', 1000, '3.00', True], ['m1', 'lay', 1000, '2.50', False]], '5'),
[475, 25]),
('control lay winner', ([['m2', 'lay', 1000, '4.00', True]], '5'), [950, 50]),
('boundary losing market no commission',
([['m1', 'back', 1000, '3.00', False], ['m1', 'lay', 500, '2.00', True]], '5'),
[-500, 0]),
('regression: loss market commission',
([['m1', 'lay', 777, '6.98', False],
['m3', 'back', 250, '4.94', False],
['m1', 'back', 777, '5.13', True],
['m3', 'back', 2000, '7.64', True]],
'6.5'),
[10745, 847]),
('variant scenario 1',
([['m2', 'back', 250, '4.54', True],
['m3', 'back', 250, '4.14', True],
['m3', 'lay', 250, '3.05', False],
['m2', 'lay', 1000, '2.30', True]],
'6.5'),
[2016, 141]),
('variant scenario 2',
([['m2', 'back', 777, '3.62', True],
['m2', 'back', 1000, '2.28', False],
['m3', 'back', 250, '7.79', False]],
'5'),
[733, 52])],
[('control single back winner', ([['m1', 'back', 1000, '3.00', True]], '5'), [1900, 100]),
('boundary hedged market nets out',
([['m1', 'back', 1000, '3.00', True], ['m1', 'lay', 1000, '2.50', False]], '5'),
[475, 25]),
('control lay winner', ([['m2', 'lay', 1000, '4.00', True]], '5'), [950, 50]),
('boundary losing market no commission',
([['m1', 'back', 1000, '3.00', False], ['m1', 'lay', 500, '2.00', True]], '5'),
[-500, 0]),
('regression: loss market commission',
([['m2', 'lay', 777, '1.69', False],
['m1', 'lay', 100, '7.97', True],
['m1', 'back', 250, '4.99', False],
['m3', 'lay', 250, '2.98', True],
['m1', 'lay', 777, '1.65', False]],
'2'),
[-948, 5]),
('variant scenario 1',
([['m3', 'lay', 2000, '3.64', False], ['m2', 'back', 1000, '6.39', True]], '6.5'),
[-240, 350]),
('variant scenario 2',
([['m2', 'lay', 1000, '7.63', True],
['m2', 'back', 2000, '1.39', True],
['m3', 'back', 1000, '6.88', True]],
'5'),
[7277, 383])],
[('control single back winner', ([['m1', 'back', 1000, '3.00', True]], '5'), [1900, 100]),
('boundary hedged market nets out',
([['m1', 'back', 1000, '3.00', True], ['m1', 'lay', 1000, '2.50', False]], '5'),
[475, 25]),
('control lay winner', ([['m2', 'lay', 1000, '4.00', True]], '5'), [950, 50]),
('boundary losing market no commission',
([['m1', 'back', 1000, '3.00', False], ['m1', 'lay', 500, '2.00', True]], '5'),
[-500, 0]),
('regression: loss market commission',
([['m2', 'lay', 777, '1.85', False],
['m1', 'back', 1000, '2.64', False],
['m1', 'lay', 2000, '3.74', False],
['m2', 'back', 1000, '7.08', True],
['m3', 'back', 1000, '5.02', False]],
'2'),
[-2169, 108]),
('variant scenario 1', ([['m2', 'lay', 777, '7.81', False]], '6.5'), [-5292, 0]),
('variant scenario 2',
([['m1', 'back', 777, '2.56', False], ['m3', 'back', 1000, '2.29', True]], '2'),
[487, 26])]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| control single back winner | [1900, 100] | [1900, 100] | Passed |
| boundary hedged market nets out | [475, 25] | [475, 25] | Passed |
| control lay winner | [950, 50] | [950, 50] | Passed |
| boundary losing market no commission | [-475, -25] | [-500, 0] | Failed |
| regression: loss market commission | [2329, 48] | [2324, 53] | Failed |
| variant scenario 1 | [3262, 227] | [3256, 233] | Failed |
| variant scenario 2 | [-4097, -84] | [-4181, 0] | Failed |
SHA-256 / 11732b668780c5ed294933b2bdc3750e49b45e011d45c0fb565f20e16f2b2723
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(bets, rate_pct):
nets = {}
for market, side, stake, price, won in bets:
p = Fraction(price)
if side == 'back':
pl = math.floor(stake * (p - 1)) if won else -stake
else:
pl = stake if won else -math.ceil(stake * (p - 1))
nets[market] = nets.get(market, 0) + pl
comm = 0
for m, net in nets.items():
comm += math.floor(abs(net) * Fraction(rate_pct) / 100 + Fraction(1, 2))
return [sum(nets.values()) - comm, comm]
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 single back winner', ([['m1', 'back', 1000, '3.00', True]], '5'), [1900, 100]),
('boundary hedged market nets out',
([['m1', 'back', 1000, '3.00', True], ['m1', 'lay', 1000, '2.50', False]], '5'),
[475, 25]),
('control lay winner', ([['m2', 'lay', 1000, '4.00', True]], '5'), [950, 50]),
('boundary losing market no commission',
([['m1', 'back', 1000, '3.00', False], ['m1', 'lay', 500, '2.00', True]], '5'),
[-500, 0]),
('regression: loss market commission',
([['m1', 'back', 250, '7.43', True],
['m1', 'back', 250, '5.08', True],
['m2', 'back', 250, '6.10', False]],
'2'),
[2324, 53]),
('variant scenario 1',
([['m1', 'back', 777, '5.62', True], ['m3', 'back', 100, '2.02', False]], '6.5'),
[3256, 233]),
('variant scenario 2', ([['m3', 'lay', 777, '6.38', False]], '2'), [-4181, 0])],
[('control single back winner', ([['m1', 'back', 1000, '3.00', True]], '5'), [1900, 100]),
('boundary hedged market nets out',
([['m1', 'back', 1000, '3.00', True], ['m1', 'lay', 1000, '2.50', False]], '5'),
[475, 25]),
('control lay winner', ([['m2', 'lay', 1000, '4.00', True]], '5'), [950, 50]),
('boundary losing market no commission',
([['m1', 'back', 1000, '3.00', False], ['m1', 'lay', 500, '2.00', True]], '5'),
[-500, 0]),
('regression: loss market commission',
([['m1', 'back', 250, '4.78', False], ['m3', 'lay', 1000, '4.13', False]], '5'),
[-3380, 0]),
('variant scenario 1', ([['m1', 'lay', 2000, '7.96', True]], '5'), [1900, 100]),
('variant scenario 2',
([['m3', 'lay', 2000, '2.30', True],
['m1', 'back', 1000, '2.62', False],
['m1', 'lay', 777, '6.91', False],
['m2', 'back', 100, '2.31', True],
['m1', 'lay', 250, '5.96', True]],
'2'),
[-3255, 43])],
[('control single back winner', ([['m1', 'back', 1000, '3.00', True]], '5'), [1900, 100]),
('boundary hedged market nets out',
([['m1', 'back', 1000, '3.00', True], ['m1', 'lay', 1000, '2.50', False]], '5'),
[475, 25]),
('control lay winner', ([['m2', 'lay', 1000, '4.00', True]], '5'), [950, 50]),
('boundary losing market no commission',
([['m1', 'back', 1000, '3.00', False], ['m1', 'lay', 500, '2.00', True]], '5'),
[-500, 0]),
('regression: loss market commission',
([['m1', 'lay', 777, '6.98', False],
['m3', 'back', 250, '4.94', False],
['m1', 'back', 777, '5.13', True],
['m3', 'back', 2000, '7.64', True]],
'6.5'),
[10745, 847]),
('variant scenario 1',
([['m2', 'back', 250, '4.54', True],
['m3', 'back', 250, '4.14', True],
['m3', 'lay', 250, '3.05', False],
['m2', 'lay', 1000, '2.30', True]],
'6.5'),
[2016, 141]),
('variant scenario 2',
([['m2', 'back', 777, '3.62', True],
['m2', 'back', 1000, '2.28', False],
['m3', 'back', 250, '7.79', False]],
'5'),
[733, 52])],
[('control single back winner', ([['m1', 'back', 1000, '3.00', True]], '5'), [1900, 100]),
('boundary hedged market nets out',
([['m1', 'back', 1000, '3.00', True], ['m1', 'lay', 1000, '2.50', False]], '5'),
[475, 25]),
('control lay winner', ([['m2', 'lay', 1000, '4.00', True]], '5'), [950, 50]),
('boundary losing market no commission',
([['m1', 'back', 1000, '3.00', False], ['m1', 'lay', 500, '2.00', True]], '5'),
[-500, 0]),
('regression: loss market commission',
([['m2', 'lay', 777, '1.69', False],
['m1', 'lay', 100, '7.97', True],
['m1', 'back', 250, '4.99', False],
['m3', 'lay', 250, '2.98', True],
['m1', 'lay', 777, '1.65', False]],
'2'),
[-948, 5]),
('variant scenario 1',
([['m3', 'lay', 2000, '3.64', False], ['m2', 'back', 1000, '6.39', True]], '6.5'),
[-240, 350]),
('variant scenario 2',
([['m2', 'lay', 1000, '7.63', True],
['m2', 'back', 2000, '1.39', True],
['m3', 'back', 1000, '6.88', True]],
'5'),
[7277, 383])],
[('control single back winner', ([['m1', 'back', 1000, '3.00', True]], '5'), [1900, 100]),
('boundary hedged market nets out',
([['m1', 'back', 1000, '3.00', True], ['m1', 'lay', 1000, '2.50', False]], '5'),
[475, 25]),
('control lay winner', ([['m2', 'lay', 1000, '4.00', True]], '5'), [950, 50]),
('boundary losing market no commission',
([['m1', 'back', 1000, '3.00', False], ['m1', 'lay', 500, '2.00', True]], '5'),
[-500, 0]),
('regression: loss market commission',
([['m2', 'lay', 777, '1.85', False],
['m1', 'back', 1000, '2.64', False],
['m1', 'lay', 2000, '3.74', False],
['m2', 'back', 1000, '7.08', True],
['m3', 'back', 1000, '5.02', False]],
'2'),
[-2169, 108]),
('variant scenario 1', ([['m2', 'lay', 777, '7.81', False]], '6.5'), [-5292, 0]),
('variant scenario 2',
([['m1', 'back', 777, '2.56', False], ['m3', 'back', 1000, '2.29', True]], '2'),
[487, 26])]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| control single back winner | [1900, 100] | [1900, 100] | Passed |
| boundary hedged market nets out | [475, 25] | [475, 25] | Passed |
| control lay winner | [950, 50] | [950, 50] | Passed |
| boundary losing market no commission | [-525, 25] | [-500, 0] | Failed |
| regression: loss market commission | [2319, 58] | [2324, 53] | Failed |
| variant scenario 1 | [3249, 240] | [3256, 233] | Failed |
| variant scenario 2 | [-4265, 84] | [-4181, 0] | Failed |
SHA-256 / e576f84aa1d849a890405484bf086ea4eaadf3b634d83a477a468d2ba813551a
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(bets, rate_pct):
nets = {}
for market, side, stake, price, won in bets:
p = Fraction(price)
if side == 'back':
pl = math.floor(stake * (p - 1)) if won else -stake
else:
pl = stake if won else -math.ceil(stake * (p - 1))
nets[market] = nets.get(market, 0) + pl
comm = 0
for m, net in nets.items():
if net > 0:
comm += math.floor(net * Fraction(rate_pct) / 100 + Fraction(1, 2))
return [sum(nets.values()) - comm, comm]
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 single back winner', ([['m1', 'back', 1000, '3.00', True]], '5'), [1900, 100]),
('boundary hedged market nets out',
([['m1', 'back', 1000, '3.00', True], ['m1', 'lay', 1000, '2.50', False]], '5'),
[475, 25]),
('control lay winner', ([['m2', 'lay', 1000, '4.00', True]], '5'), [950, 50]),
('boundary losing market no commission',
([['m1', 'back', 1000, '3.00', False], ['m1', 'lay', 500, '2.00', True]], '5'),
[-500, 0]),
('regression: loss market commission',
([['m1', 'back', 250, '7.43', True],
['m1', 'back', 250, '5.08', True],
['m2', 'back', 250, '6.10', False]],
'2'),
[2324, 53]),
('variant scenario 1',
([['m1', 'back', 777, '5.62', True], ['m3', 'back', 100, '2.02', False]], '6.5'),
[3256, 233]),
('variant scenario 2', ([['m3', 'lay', 777, '6.38', False]], '2'), [-4181, 0])],
[('control single back winner', ([['m1', 'back', 1000, '3.00', True]], '5'), [1900, 100]),
('boundary hedged market nets out',
([['m1', 'back', 1000, '3.00', True], ['m1', 'lay', 1000, '2.50', False]], '5'),
[475, 25]),
('control lay winner', ([['m2', 'lay', 1000, '4.00', True]], '5'), [950, 50]),
('boundary losing market no commission',
([['m1', 'back', 1000, '3.00', False], ['m1', 'lay', 500, '2.00', True]], '5'),
[-500, 0]),
('regression: loss market commission',
([['m1', 'back', 250, '4.78', False], ['m3', 'lay', 1000, '4.13', False]], '5'),
[-3380, 0]),
('variant scenario 1', ([['m1', 'lay', 2000, '7.96', True]], '5'), [1900, 100]),
('variant scenario 2',
([['m3', 'lay', 2000, '2.30', True],
['m1', 'back', 1000, '2.62', False],
['m1', 'lay', 777, '6.91', False],
['m2', 'back', 100, '2.31', True],
['m1', 'lay', 250, '5.96', True]],
'2'),
[-3255, 43])],
[('control single back winner', ([['m1', 'back', 1000, '3.00', True]], '5'), [1900, 100]),
('boundary hedged market nets out',
([['m1', 'back', 1000, '3.00', True], ['m1', 'lay', 1000, '2.50', False]], '5'),
[475, 25]),
('control lay winner', ([['m2', 'lay', 1000, '4.00', True]], '5'), [950, 50]),
('boundary losing market no commission',
([['m1', 'back', 1000, '3.00', False], ['m1', 'lay', 500, '2.00', True]], '5'),
[-500, 0]),
('regression: loss market commission',
([['m1', 'lay', 777, '6.98', False],
['m3', 'back', 250, '4.94', False],
['m1', 'back', 777, '5.13', True],
['m3', 'back', 2000, '7.64', True]],
'6.5'),
[10745, 847]),
('variant scenario 1',
([['m2', 'back', 250, '4.54', True],
['m3', 'back', 250, '4.14', True],
['m3', 'lay', 250, '3.05', False],
['m2', 'lay', 1000, '2.30', True]],
'6.5'),
[2016, 141]),
('variant scenario 2',
([['m2', 'back', 777, '3.62', True],
['m2', 'back', 1000, '2.28', False],
['m3', 'back', 250, '7.79', False]],
'5'),
[733, 52])],
[('control single back winner', ([['m1', 'back', 1000, '3.00', True]], '5'), [1900, 100]),
('boundary hedged market nets out',
([['m1', 'back', 1000, '3.00', True], ['m1', 'lay', 1000, '2.50', False]], '5'),
[475, 25]),
('control lay winner', ([['m2', 'lay', 1000, '4.00', True]], '5'), [950, 50]),
('boundary losing market no commission',
([['m1', 'back', 1000, '3.00', False], ['m1', 'lay', 500, '2.00', True]], '5'),
[-500, 0]),
('regression: loss market commission',
([['m2', 'lay', 777, '1.69', False],
['m1', 'lay', 100, '7.97', True],
['m1', 'back', 250, '4.99', False],
['m3', 'lay', 250, '2.98', True],
['m1', 'lay', 777, '1.65', False]],
'2'),
[-948, 5]),
('variant scenario 1',
([['m3', 'lay', 2000, '3.64', False], ['m2', 'back', 1000, '6.39', True]], '6.5'),
[-240, 350]),
('variant scenario 2',
([['m2', 'lay', 1000, '7.63', True],
['m2', 'back', 2000, '1.39', True],
['m3', 'back', 1000, '6.88', True]],
'5'),
[7277, 383])],
[('control single back winner', ([['m1', 'back', 1000, '3.00', True]], '5'), [1900, 100]),
('boundary hedged market nets out',
([['m1', 'back', 1000, '3.00', True], ['m1', 'lay', 1000, '2.50', False]], '5'),
[475, 25]),
('control lay winner', ([['m2', 'lay', 1000, '4.00', True]], '5'), [950, 50]),
('boundary losing market no commission',
([['m1', 'back', 1000, '3.00', False], ['m1', 'lay', 500, '2.00', True]], '5'),
[-500, 0]),
('regression: loss market commission',
([['m2', 'lay', 777, '1.85', False],
['m1', 'back', 1000, '2.64', False],
['m1', 'lay', 2000, '3.74', False],
['m2', 'back', 1000, '7.08', True],
['m3', 'back', 1000, '5.02', False]],
'2'),
[-2169, 108]),
('variant scenario 1', ([['m2', 'lay', 777, '7.81', False]], '6.5'), [-5292, 0]),
('variant scenario 2',
([['m1', 'back', 777, '2.56', False], ['m3', 'back', 1000, '2.29', True]], '2'),
[487, 26])]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| control single back winner | [1900, 100] | [1900, 100] | Passed |
| boundary hedged market nets out | [475, 25] | [475, 25] | Passed |
| control lay winner | [950, 50] | [950, 50] | Passed |
| boundary losing market no commission | [-500, 0] | [-500, 0] | Passed |
| regression: loss market commission | [2324, 53] | [2324, 53] | Passed |
| variant scenario 1 | [3256, 233] | [3256, 233] | Passed |
| variant scenario 2 | [-4181, 0] | [-4181, 0] | Passed |
SHA-256 / 101ebb5f82f5d28b8cf31c2f91431d51737d4c3e7f9494d3d449ee54bdae967a
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:31.896291+00:00.
Case digest / e5f4e13b12e38de547199e3324baf29bb19020d952957be53779bedad097db90