FAILURE MAP
← Case archive

FA-84431 / Betting odds conversion / Open access

Additive method subtracts the whole overround from every outcome · case 01

Additive fair probabilities sum to well below one.

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

ROOT CAUSE

The overround is subtracted in full from each outcome instead of an equal share.

VERIFIED REPAIR

Subtract (book - 1) / n from each outcome.

Unsuccessful approach: Dividing by n - 1 over-corrects every outcome.

Case contract

Remove the bookmaker margin from decimal prices (implied p = 1/d, book = sum p > 1 assumed). multiplicative: p / book. additive: p - (book - 1) / n; if any result is negative return "additive infeasible". power: p ** k with k found by 60 bisection steps on [1, 10] so that the powered probabilities sum to 1 (k = midpoint of the final bracket). Any other method returns "invalid method". Return the fair probabilities formatted "%.4f".

Why this case matters

Pricing models strip margins differently; favourite-longshot bias makes the method matter.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(prices, method):
    ps = [1 / float(d) for d in prices]
    book = sum(ps)
    n = len(ps)
    if method == 'multiplicative':
        fair = [p / book for p in ps]
    elif method == 'additive':
        fair = [p - (book - 1) for p in ps]
        if any(x < 0 for x in fair):
            return 'additive infeasible'
    elif method == 'power':
        lo, hi = 1.0, 10.0
        for _ in range(60):
            mid = (lo + hi) / 2
            if sum(p ** mid for p in ps) > 1:
                lo = mid
            else:
                hi = mid
        k = (lo + hi) / 2
        fair = [p ** k for p in ps]
    else:
        return 'invalid method'
    return ['%.4f' % x for x in fair]
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 multiplicative', (['1.80', '2.00'], 'multiplicative'), ['0.5263', '0.4737']),
  ('control additive', (['1.80', '2.00'], 'additive'), ['0.5278', '0.4722']),
  ('control power', (['1.80', '2.00'], 'power'), ['0.5285', '0.4715']),
  ('boundary additive longshot',
   (['1.01', '15.00', '100.00', '100.00'], 'additive'),
   'additive infeasible'),
  ('boundary unknown method', (['1.80', '2.00'], 'shin'), 'invalid method'),
  ('regression: additive share',
   (['4.24', '2.41', '2.26'], 'additive'),
   ['0.2048', '0.3838', '0.4114']),
  ('variant scenario 1',
   (['3.13', '10.94', '3.74', '3.80', '7.37'], 'power'),
   ['0.3013', '0.0808', '0.2498', '0.2457', '0.1224']),
  ('variant scenario 2', (['2.76', '4.20', '18.02', '17.82', '2.41'], 'shin'), 'invalid method')],
 [('control multiplicative', (['1.80', '2.00'], 'multiplicative'), ['0.5263', '0.4737']),
  ('control additive', (['1.80', '2.00'], 'additive'), ['0.5278', '0.4722']),
  ('control power', (['1.80', '2.00'], 'power'), ['0.5285', '0.4715']),
  ('boundary additive longshot',
   (['1.01', '15.00', '100.00', '100.00'], 'additive'),
   'additive infeasible'),
  ('boundary unknown method', (['1.80', '2.00'], 'shin'), 'invalid method'),
  ('regression: additive share', (['1.06', '13.81'], 'additive'), ['0.9355', '0.0645']),
  ('variant scenario 1',
   (['4.95', '1.53', '3.74'], 'multiplicative'),
   ['0.1799', '0.5820', '0.2381']),
  ('variant scenario 2', (['2.57', '2.14', '3.17'], 'power'), ['0.3310', '0.4102', '0.2589'])],
 [('control multiplicative', (['1.80', '2.00'], 'multiplicative'), ['0.5263', '0.4737']),
  ('control additive', (['1.80', '2.00'], 'additive'), ['0.5278', '0.4722']),
  ('control power', (['1.80', '2.00'], 'power'), ['0.5285', '0.4715']),
  ('boundary additive longshot',
   (['1.01', '15.00', '100.00', '100.00'], 'additive'),
   'additive infeasible'),
  ('boundary unknown method', (['1.80', '2.00'], 'shin'), 'invalid method'),
  ('regression: additive share',
   (['5.15', '6.00', '9.30', '3.30', '3.41'], 'additive'),
   ['0.1812', '0.1537', '0.0946', '0.2901', '0.2803']),
  ('variant scenario 1', (['3.47', '2.27', '4.50', '6.40', '11.33'], 'shin'), 'invalid method'),
  ('variant scenario 2',
   (['1.19', '4.17', '10.00'], 'multiplicative'),
   ['0.7121', '0.2032', '0.0847'])],
 [('control multiplicative', (['1.80', '2.00'], 'multiplicative'), ['0.5263', '0.4737']),
  ('control additive', (['1.80', '2.00'], 'additive'), ['0.5278', '0.4722']),
  ('control power', (['1.80', '2.00'], 'power'), ['0.5285', '0.4715']),
  ('boundary additive longshot',
   (['1.01', '15.00', '100.00', '100.00'], 'additive'),
   'additive infeasible'),
  ('boundary unknown method', (['1.80', '2.00'], 'shin'), 'invalid method'),
  ('regression: additive share',
   (['12.06', '6.47', '2.90', '3.41', '4.16'], 'additive'),
   ['0.0597', '0.1314', '0.3216', '0.2701', '0.2172']),
  ('variant scenario 1', (['1.79', '3.93', '3.07'], 'power'), ['0.5138', '0.2090', '0.2772']),
  ('variant scenario 2',
   (['34.48', '3.06', '3.75', '8.76', '3.57'], 'multiplicative'),
   ['0.0285', '0.3214', '0.2623', '0.1123', '0.2755'])],
 [('control multiplicative', (['1.80', '2.00'], 'multiplicative'), ['0.5263', '0.4737']),
  ('control additive', (['1.80', '2.00'], 'additive'), ['0.5278', '0.4722']),
  ('control power', (['1.80', '2.00'], 'power'), ['0.5285', '0.4715']),
  ('boundary additive longshot',
   (['1.01', '15.00', '100.00', '100.00'], 'additive'),
   'additive infeasible'),
  ('boundary unknown method', (['1.80', '2.00'], 'shin'), 'invalid method'),
  ('regression: additive share',
   (['2.21', '2.18', '7.95', '13.06'], 'additive'),
   ['0.4241', '0.4303', '0.0974', '0.0482']),
  ('variant scenario 1',
   (['2.60', '6.34', '4.18', '2.94'], 'power'),
   ['0.3514', '0.1325', '0.2090', '0.3072']),
  ('variant scenario 2',
   (['2.29', '2.38', '4.59', '9.61'], 'power'),
   ['0.3850', '0.3683', '0.1728', '0.0738'])]]
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 multiplicative['0.5263', '0.4737']['0.5263', '0.4737']Passed
control additive['0.5000', '0.4444']['0.5278', '0.4722']Failed
control power['0.5285', '0.4715']['0.5285', '0.4715']Passed
boundary additive longshotadditive infeasibleadditive infeasiblePassed
boundary unknown methodinvalid methodinvalid methodPassed
regression: additive share['0.1426', '0.3217', '0.3492']['0.2048', '0.3838', '0.4114']Failed
variant scenario 1['0.3013', '0.0808', '0.2498', '0.2457', '0.1224']['0.3013', '0.0808', '0.2498', '0.2457', '0.1224']Passed
variant scenario 2invalid methodinvalid methodPassed

SHA-256 / 9c8c69feb4bfe539052267b95792cfd311ef0ce7f98b639cdccd4e6c40e53986

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(prices, method):
    ps = [1 / float(d) for d in prices]
    book = sum(ps)
    n = len(ps)
    if method == 'multiplicative':
        fair = [p / book for p in ps]
    elif method == 'additive':
        fair = [p - (book - 1) / (n - 1) for p in ps]
        if any(x < 0 for x in fair):
            return 'additive infeasible'
    elif method == 'power':
        lo, hi = 1.0, 10.0
        for _ in range(60):
            mid = (lo + hi) / 2
            if sum(p ** mid for p in ps) > 1:
                lo = mid
            else:
                hi = mid
        k = (lo + hi) / 2
        fair = [p ** k for p in ps]
    else:
        return 'invalid method'
    return ['%.4f' % x for x in fair]
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 multiplicative', (['1.80', '2.00'], 'multiplicative'), ['0.5263', '0.4737']),
  ('control additive', (['1.80', '2.00'], 'additive'), ['0.5278', '0.4722']),
  ('control power', (['1.80', '2.00'], 'power'), ['0.5285', '0.4715']),
  ('boundary additive longshot',
   (['1.01', '15.00', '100.00', '100.00'], 'additive'),
   'additive infeasible'),
  ('boundary unknown method', (['1.80', '2.00'], 'shin'), 'invalid method'),
  ('regression: additive share',
   (['4.24', '2.41', '2.26'], 'additive'),
   ['0.2048', '0.3838', '0.4114']),
  ('variant scenario 1',
   (['3.13', '10.94', '3.74', '3.80', '7.37'], 'power'),
   ['0.3013', '0.0808', '0.2498', '0.2457', '0.1224']),
  ('variant scenario 2', (['2.76', '4.20', '18.02', '17.82', '2.41'], 'shin'), 'invalid method')],
 [('control multiplicative', (['1.80', '2.00'], 'multiplicative'), ['0.5263', '0.4737']),
  ('control additive', (['1.80', '2.00'], 'additive'), ['0.5278', '0.4722']),
  ('control power', (['1.80', '2.00'], 'power'), ['0.5285', '0.4715']),
  ('boundary additive longshot',
   (['1.01', '15.00', '100.00', '100.00'], 'additive'),
   'additive infeasible'),
  ('boundary unknown method', (['1.80', '2.00'], 'shin'), 'invalid method'),
  ('regression: additive share', (['1.06', '13.81'], 'additive'), ['0.9355', '0.0645']),
  ('variant scenario 1',
   (['4.95', '1.53', '3.74'], 'multiplicative'),
   ['0.1799', '0.5820', '0.2381']),
  ('variant scenario 2', (['2.57', '2.14', '3.17'], 'power'), ['0.3310', '0.4102', '0.2589'])],
 [('control multiplicative', (['1.80', '2.00'], 'multiplicative'), ['0.5263', '0.4737']),
  ('control additive', (['1.80', '2.00'], 'additive'), ['0.5278', '0.4722']),
  ('control power', (['1.80', '2.00'], 'power'), ['0.5285', '0.4715']),
  ('boundary additive longshot',
   (['1.01', '15.00', '100.00', '100.00'], 'additive'),
   'additive infeasible'),
  ('boundary unknown method', (['1.80', '2.00'], 'shin'), 'invalid method'),
  ('regression: additive share',
   (['5.15', '6.00', '9.30', '3.30', '3.41'], 'additive'),
   ['0.1812', '0.1537', '0.0946', '0.2901', '0.2803']),
  ('variant scenario 1', (['3.47', '2.27', '4.50', '6.40', '11.33'], 'shin'), 'invalid method'),
  ('variant scenario 2',
   (['1.19', '4.17', '10.00'], 'multiplicative'),
   ['0.7121', '0.2032', '0.0847'])],
 [('control multiplicative', (['1.80', '2.00'], 'multiplicative'), ['0.5263', '0.4737']),
  ('control additive', (['1.80', '2.00'], 'additive'), ['0.5278', '0.4722']),
  ('control power', (['1.80', '2.00'], 'power'), ['0.5285', '0.4715']),
  ('boundary additive longshot',
   (['1.01', '15.00', '100.00', '100.00'], 'additive'),
   'additive infeasible'),
  ('boundary unknown method', (['1.80', '2.00'], 'shin'), 'invalid method'),
  ('regression: additive share',
   (['12.06', '6.47', '2.90', '3.41', '4.16'], 'additive'),
   ['0.0597', '0.1314', '0.3216', '0.2701', '0.2172']),
  ('variant scenario 1', (['1.79', '3.93', '3.07'], 'power'), ['0.5138', '0.2090', '0.2772']),
  ('variant scenario 2',
   (['34.48', '3.06', '3.75', '8.76', '3.57'], 'multiplicative'),
   ['0.0285', '0.3214', '0.2623', '0.1123', '0.2755'])],
 [('control multiplicative', (['1.80', '2.00'], 'multiplicative'), ['0.5263', '0.4737']),
  ('control additive', (['1.80', '2.00'], 'additive'), ['0.5278', '0.4722']),
  ('control power', (['1.80', '2.00'], 'power'), ['0.5285', '0.4715']),
  ('boundary additive longshot',
   (['1.01', '15.00', '100.00', '100.00'], 'additive'),
   'additive infeasible'),
  ('boundary unknown method', (['1.80', '2.00'], 'shin'), 'invalid method'),
  ('regression: additive share',
   (['2.21', '2.18', '7.95', '13.06'], 'additive'),
   ['0.4241', '0.4303', '0.0974', '0.0482']),
  ('variant scenario 1',
   (['2.60', '6.34', '4.18', '2.94'], 'power'),
   ['0.3514', '0.1325', '0.2090', '0.3072']),
  ('variant scenario 2',
   (['2.29', '2.38', '4.59', '9.61'], 'power'),
   ['0.3850', '0.3683', '0.1728', '0.0738'])]]
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 multiplicative['0.5263', '0.4737']['0.5263', '0.4737']Passed
control additive['0.5000', '0.4444']['0.5278', '0.4722']Failed
control power['0.5285', '0.4715']['0.5285', '0.4715']Passed
boundary additive longshotadditive infeasibleadditive infeasiblePassed
boundary unknown methodinvalid methodinvalid methodPassed
regression: additive share['0.1892', '0.3683', '0.3958']['0.2048', '0.3838', '0.4114']Failed
variant scenario 1['0.3013', '0.0808', '0.2498', '0.2457', '0.1224']['0.3013', '0.0808', '0.2498', '0.2457', '0.1224']Passed
variant scenario 2invalid methodinvalid methodPassed

SHA-256 / a02cd8c16a262da22697ceb24e3900966e0544352563f9e015aa4a565c705655

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(prices, method):
    ps = [1 / float(d) for d in prices]
    book = sum(ps)
    n = len(ps)
    if method == 'multiplicative':
        fair = [p / book for p in ps]
    elif method == 'additive':
        fair = [p - (book - 1) / n for p in ps]
        if any(x < 0 for x in fair):
            return 'additive infeasible'
    elif method == 'power':
        lo, hi = 1.0, 10.0
        for _ in range(60):
            mid = (lo + hi) / 2
            if sum(p ** mid for p in ps) > 1:
                lo = mid
            else:
                hi = mid
        k = (lo + hi) / 2
        fair = [p ** k for p in ps]
    else:
        return 'invalid method'
    return ['%.4f' % x for x in fair]
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 multiplicative', (['1.80', '2.00'], 'multiplicative'), ['0.5263', '0.4737']),
  ('control additive', (['1.80', '2.00'], 'additive'), ['0.5278', '0.4722']),
  ('control power', (['1.80', '2.00'], 'power'), ['0.5285', '0.4715']),
  ('boundary additive longshot',
   (['1.01', '15.00', '100.00', '100.00'], 'additive'),
   'additive infeasible'),
  ('boundary unknown method', (['1.80', '2.00'], 'shin'), 'invalid method'),
  ('regression: additive share',
   (['4.24', '2.41', '2.26'], 'additive'),
   ['0.2048', '0.3838', '0.4114']),
  ('variant scenario 1',
   (['3.13', '10.94', '3.74', '3.80', '7.37'], 'power'),
   ['0.3013', '0.0808', '0.2498', '0.2457', '0.1224']),
  ('variant scenario 2', (['2.76', '4.20', '18.02', '17.82', '2.41'], 'shin'), 'invalid method')],
 [('control multiplicative', (['1.80', '2.00'], 'multiplicative'), ['0.5263', '0.4737']),
  ('control additive', (['1.80', '2.00'], 'additive'), ['0.5278', '0.4722']),
  ('control power', (['1.80', '2.00'], 'power'), ['0.5285', '0.4715']),
  ('boundary additive longshot',
   (['1.01', '15.00', '100.00', '100.00'], 'additive'),
   'additive infeasible'),
  ('boundary unknown method', (['1.80', '2.00'], 'shin'), 'invalid method'),
  ('regression: additive share', (['1.06', '13.81'], 'additive'), ['0.9355', '0.0645']),
  ('variant scenario 1',
   (['4.95', '1.53', '3.74'], 'multiplicative'),
   ['0.1799', '0.5820', '0.2381']),
  ('variant scenario 2', (['2.57', '2.14', '3.17'], 'power'), ['0.3310', '0.4102', '0.2589'])],
 [('control multiplicative', (['1.80', '2.00'], 'multiplicative'), ['0.5263', '0.4737']),
  ('control additive', (['1.80', '2.00'], 'additive'), ['0.5278', '0.4722']),
  ('control power', (['1.80', '2.00'], 'power'), ['0.5285', '0.4715']),
  ('boundary additive longshot',
   (['1.01', '15.00', '100.00', '100.00'], 'additive'),
   'additive infeasible'),
  ('boundary unknown method', (['1.80', '2.00'], 'shin'), 'invalid method'),
  ('regression: additive share',
   (['5.15', '6.00', '9.30', '3.30', '3.41'], 'additive'),
   ['0.1812', '0.1537', '0.0946', '0.2901', '0.2803']),
  ('variant scenario 1', (['3.47', '2.27', '4.50', '6.40', '11.33'], 'shin'), 'invalid method'),
  ('variant scenario 2',
   (['1.19', '4.17', '10.00'], 'multiplicative'),
   ['0.7121', '0.2032', '0.0847'])],
 [('control multiplicative', (['1.80', '2.00'], 'multiplicative'), ['0.5263', '0.4737']),
  ('control additive', (['1.80', '2.00'], 'additive'), ['0.5278', '0.4722']),
  ('control power', (['1.80', '2.00'], 'power'), ['0.5285', '0.4715']),
  ('boundary additive longshot',
   (['1.01', '15.00', '100.00', '100.00'], 'additive'),
   'additive infeasible'),
  ('boundary unknown method', (['1.80', '2.00'], 'shin'), 'invalid method'),
  ('regression: additive share',
   (['12.06', '6.47', '2.90', '3.41', '4.16'], 'additive'),
   ['0.0597', '0.1314', '0.3216', '0.2701', '0.2172']),
  ('variant scenario 1', (['1.79', '3.93', '3.07'], 'power'), ['0.5138', '0.2090', '0.2772']),
  ('variant scenario 2',
   (['34.48', '3.06', '3.75', '8.76', '3.57'], 'multiplicative'),
   ['0.0285', '0.3214', '0.2623', '0.1123', '0.2755'])],
 [('control multiplicative', (['1.80', '2.00'], 'multiplicative'), ['0.5263', '0.4737']),
  ('control additive', (['1.80', '2.00'], 'additive'), ['0.5278', '0.4722']),
  ('control power', (['1.80', '2.00'], 'power'), ['0.5285', '0.4715']),
  ('boundary additive longshot',
   (['1.01', '15.00', '100.00', '100.00'], 'additive'),
   'additive infeasible'),
  ('boundary unknown method', (['1.80', '2.00'], 'shin'), 'invalid method'),
  ('regression: additive share',
   (['2.21', '2.18', '7.95', '13.06'], 'additive'),
   ['0.4241', '0.4303', '0.0974', '0.0482']),
  ('variant scenario 1',
   (['2.60', '6.34', '4.18', '2.94'], 'power'),
   ['0.3514', '0.1325', '0.2090', '0.3072']),
  ('variant scenario 2',
   (['2.29', '2.38', '4.59', '9.61'], 'power'),
   ['0.3850', '0.3683', '0.1728', '0.0738'])]]
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 multiplicative['0.5263', '0.4737']['0.5263', '0.4737']Passed
control additive['0.5278', '0.4722']['0.5278', '0.4722']Passed
control power['0.5285', '0.4715']['0.5285', '0.4715']Passed
boundary additive longshotadditive infeasibleadditive infeasiblePassed
boundary unknown methodinvalid methodinvalid methodPassed
regression: additive share['0.2048', '0.3838', '0.4114']['0.2048', '0.3838', '0.4114']Passed
variant scenario 1['0.3013', '0.0808', '0.2498', '0.2457', '0.1224']['0.3013', '0.0808', '0.2498', '0.2457', '0.1224']Passed
variant scenario 2invalid methodinvalid methodPassed

SHA-256 / 6236d5a234d697cd34c075957924412f2441d0c6545b2e65d8cf62d83b20456e

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

Case digest / fc76fd4d730f2163935d6302f7860e7448a907772cbd48025ff31dc9e99c808f