FAILURE MAP
← Case archive

FA-84426 / Betting odds conversion / Open access

Negative overround formatted with floor-division digits · case 01

An under-round book shows "-1.99" style garbage instead of "-0.01".

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

ROOT CAUSE

The helper splits a negative cent count with // and %, which floor toward negative infinity.

VERIFIED REPAIR

Split the absolute cent count and prefix the sign.

Unsuccessful approach: Taking the sign from the unrounded value prints "-0.00" for tiny negative overrounds.

Case contract

Market book analysis for decimal prices (strings, each > 1, else "invalid"). Implied probability is 1/d; book = sum of implied probabilities. Return [overround percent (book - 1) * 100, bookmaker margin percent (1 - 1/book) * 100, fair prices d * book for proportional margin removal], every number rounded half up to two decimals (negative values are rounded toward +infinity at the half) and formatted with two decimals.

Why this case matters

Trading tools report overround and margin separately and derive no-vig fair prices.

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(prices):
    def fmt(x):
        c = math.floor(x * 100 + Fraction(1, 2))
        return '%d.%02d' % (c // 100, c % 100)
    ds = [Fraction(p) for p in prices]
    if any(d <= 1 for d in ds):
        return 'invalid'
    book = sum(1 / d for d in ds)
    over = (book - 1) * 100
    margin = (1 - 1 / book) * 100
    fair = [fmt(d * book) for d in ds]
    return [fmt(over), fmt(margin), 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 fair coin', (['2.00', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('control standard juice', (['1.91', '1.91'],), ['4.71', '4.50', ['2.00', '2.00']]),
  ('boundary three-way', (['2.50', '3.20', '2.90'],), ['5.73', '5.42', ['2.64', '3.38', '3.07']]),
  ('boundary no-profit price', (['1.00', '5.00'],), 'invalid'),
  ('regression: negative format',
   (['3.13', '2.06', '5.16'],),
   ['-0.13', '-0.13', ['3.13', '2.06', '5.15']]),
  ('regression: negative format', (['2.0002', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('variant scenario 1',
   (['9.05', '2.06', '1.87'],),
   ['13.07', '11.56', ['10.23', '2.33', '2.11']]),
  ('variant scenario 2', (['5.64', '2.16', '2.75'],), ['0.39', '0.39', ['5.66', '2.17', '2.76']])],
 [('control fair coin', (['2.00', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('control standard juice', (['1.91', '1.91'],), ['4.71', '4.50', ['2.00', '2.00']]),
  ('boundary three-way', (['2.50', '3.20', '2.90'],), ['5.73', '5.42', ['2.64', '3.38', '3.07']]),
  ('boundary no-profit price', (['1.00', '5.00'],), 'invalid'),
  ('regression: negative format',
   (['2.70', '2.85', '17.25', '5.00'],),
   ['-2.08', '-2.12', ['2.64', '2.79', '16.89', '4.90']]),
  ('regression: negative format', (['2.0002', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('variant scenario 1', (['3.09', '1.42'],), ['2.78', '2.71', ['3.18', '1.46']]),
  ('variant scenario 2', (['4.24', '1.99', '3.04'],), ['6.73', '6.31', ['4.53', '2.12', '3.24']])],
 [('control fair coin', (['2.00', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('control standard juice', (['1.91', '1.91'],), ['4.71', '4.50', ['2.00', '2.00']]),
  ('boundary three-way', (['2.50', '3.20', '2.90'],), ['5.73', '5.42', ['2.64', '3.38', '3.07']]),
  ('boundary no-profit price', (['1.00', '5.00'],), 'invalid'),
  ('regression: negative format',
   (['8.77', '3.61', '3.44', '3.17'],),
   ['-0.28', '-0.28', ['8.75', '3.60', '3.43', '3.16']]),
  ('regression: negative format', (['2.0001', '2.0001'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('variant scenario 1', (['2.70', '2.41', '2.77'],), ['14.63', '12.76', ['3.10', '2.76', '3.18']]),
  ('variant scenario 2', (['4.44', '1.08'],), ['15.12', '13.13', ['5.11', '1.24']])],
 [('control fair coin', (['2.00', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('control standard juice', (['1.91', '1.91'],), ['4.71', '4.50', ['2.00', '2.00']]),
  ('boundary three-way', (['2.50', '3.20', '2.90'],), ['5.73', '5.42', ['2.64', '3.38', '3.07']]),
  ('boundary no-profit price', (['1.00', '5.00'],), 'invalid'),
  ('regression: negative format',
   (['14.48', '2.85', '3.84', '3.27'],),
   ['-1.38', '-1.40', ['14.28', '2.81', '3.79', '3.22']]),
  ('regression: negative format', (['2.0002', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('variant scenario 1',
   (['4.40', '5.01', '2.99', '2.89'],),
   ['10.73', '9.69', ['4.87', '5.55', '3.31', '3.20']]),
  ('variant scenario 2', (['2.01', '1.74'],), ['7.22', '6.74', ['2.16', '1.87']])],
 [('control fair coin', (['2.00', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('control standard juice', (['1.91', '1.91'],), ['4.71', '4.50', ['2.00', '2.00']]),
  ('boundary three-way', (['2.50', '3.20', '2.90'],), ['5.73', '5.42', ['2.64', '3.38', '3.07']]),
  ('boundary no-profit price', (['1.00', '5.00'],), 'invalid'),
  ('regression: negative format',
   (['2.26', '3.08', '4.63'],),
   ['-1.69', '-1.72', ['2.22', '3.03', '4.55']]),
  ('regression: negative format',
   (['3.15', '2.98', '3.25', '25.47'],),
   ['0.00', '0.00', ['3.15', '2.98', '3.25', '25.47']]),
  ('variant scenario 1', (['0.90', '3.50', '2.48'],), 'invalid'),
  ('variant scenario 2',
   (['7.05', '4.46', '2.67', '3.12'],),
   ['6.11', '5.76', ['7.48', '4.73', '2.83', '3.31']])]]
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 fair coin['0.00', '0.00', ['2.00', '2.00']]['0.00', '0.00', ['2.00', '2.00']]Passed
control standard juice['4.71', '4.50', ['2.00', '2.00']]['4.71', '4.50', ['2.00', '2.00']]Passed
boundary three-way['5.73', '5.42', ['2.64', '3.38', '3.07']]['5.73', '5.42', ['2.64', '3.38', '3.07']]Passed
boundary no-profit priceinvalidinvalidPassed
regression: negative format['-1.87', '-1.87', ['3.13', '2.06', '5.15']]['-0.13', '-0.13', ['3.13', '2.06', '5.15']]Failed
regression: negative format['0.00', '0.00', ['2.00', '2.00']]['0.00', '0.00', ['2.00', '2.00']]Passed
variant scenario 1['13.07', '11.56', ['10.23', '2.33', '2.11']]['13.07', '11.56', ['10.23', '2.33', '2.11']]Passed
variant scenario 2['0.39', '0.39', ['5.66', '2.17', '2.76']]['0.39', '0.39', ['5.66', '2.17', '2.76']]Passed

SHA-256 / bb2f7402daac774daab7ab417a7ed65f3214171edc399222fd6c4701cfccf738

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(prices):
    def fmt(x):
        sign = '-' if x < 0 else ''
        c = math.floor(abs(x) * 100 + Fraction(1, 2))
        return sign + '%d.%02d' % (c // 100, c % 100)
    ds = [Fraction(p) for p in prices]
    if any(d <= 1 for d in ds):
        return 'invalid'
    book = sum(1 / d for d in ds)
    over = (book - 1) * 100
    margin = (1 - 1 / book) * 100
    fair = [fmt(d * book) for d in ds]
    return [fmt(over), fmt(margin), 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 fair coin', (['2.00', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('control standard juice', (['1.91', '1.91'],), ['4.71', '4.50', ['2.00', '2.00']]),
  ('boundary three-way', (['2.50', '3.20', '2.90'],), ['5.73', '5.42', ['2.64', '3.38', '3.07']]),
  ('boundary no-profit price', (['1.00', '5.00'],), 'invalid'),
  ('regression: negative format',
   (['3.13', '2.06', '5.16'],),
   ['-0.13', '-0.13', ['3.13', '2.06', '5.15']]),
  ('regression: negative format', (['2.0002', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('variant scenario 1',
   (['9.05', '2.06', '1.87'],),
   ['13.07', '11.56', ['10.23', '2.33', '2.11']]),
  ('variant scenario 2', (['5.64', '2.16', '2.75'],), ['0.39', '0.39', ['5.66', '2.17', '2.76']])],
 [('control fair coin', (['2.00', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('control standard juice', (['1.91', '1.91'],), ['4.71', '4.50', ['2.00', '2.00']]),
  ('boundary three-way', (['2.50', '3.20', '2.90'],), ['5.73', '5.42', ['2.64', '3.38', '3.07']]),
  ('boundary no-profit price', (['1.00', '5.00'],), 'invalid'),
  ('regression: negative format',
   (['2.70', '2.85', '17.25', '5.00'],),
   ['-2.08', '-2.12', ['2.64', '2.79', '16.89', '4.90']]),
  ('regression: negative format', (['2.0002', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('variant scenario 1', (['3.09', '1.42'],), ['2.78', '2.71', ['3.18', '1.46']]),
  ('variant scenario 2', (['4.24', '1.99', '3.04'],), ['6.73', '6.31', ['4.53', '2.12', '3.24']])],
 [('control fair coin', (['2.00', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('control standard juice', (['1.91', '1.91'],), ['4.71', '4.50', ['2.00', '2.00']]),
  ('boundary three-way', (['2.50', '3.20', '2.90'],), ['5.73', '5.42', ['2.64', '3.38', '3.07']]),
  ('boundary no-profit price', (['1.00', '5.00'],), 'invalid'),
  ('regression: negative format',
   (['8.77', '3.61', '3.44', '3.17'],),
   ['-0.28', '-0.28', ['8.75', '3.60', '3.43', '3.16']]),
  ('regression: negative format', (['2.0001', '2.0001'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('variant scenario 1', (['2.70', '2.41', '2.77'],), ['14.63', '12.76', ['3.10', '2.76', '3.18']]),
  ('variant scenario 2', (['4.44', '1.08'],), ['15.12', '13.13', ['5.11', '1.24']])],
 [('control fair coin', (['2.00', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('control standard juice', (['1.91', '1.91'],), ['4.71', '4.50', ['2.00', '2.00']]),
  ('boundary three-way', (['2.50', '3.20', '2.90'],), ['5.73', '5.42', ['2.64', '3.38', '3.07']]),
  ('boundary no-profit price', (['1.00', '5.00'],), 'invalid'),
  ('regression: negative format',
   (['14.48', '2.85', '3.84', '3.27'],),
   ['-1.38', '-1.40', ['14.28', '2.81', '3.79', '3.22']]),
  ('regression: negative format', (['2.0002', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('variant scenario 1',
   (['4.40', '5.01', '2.99', '2.89'],),
   ['10.73', '9.69', ['4.87', '5.55', '3.31', '3.20']]),
  ('variant scenario 2', (['2.01', '1.74'],), ['7.22', '6.74', ['2.16', '1.87']])],
 [('control fair coin', (['2.00', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('control standard juice', (['1.91', '1.91'],), ['4.71', '4.50', ['2.00', '2.00']]),
  ('boundary three-way', (['2.50', '3.20', '2.90'],), ['5.73', '5.42', ['2.64', '3.38', '3.07']]),
  ('boundary no-profit price', (['1.00', '5.00'],), 'invalid'),
  ('regression: negative format',
   (['2.26', '3.08', '4.63'],),
   ['-1.69', '-1.72', ['2.22', '3.03', '4.55']]),
  ('regression: negative format',
   (['3.15', '2.98', '3.25', '25.47'],),
   ['0.00', '0.00', ['3.15', '2.98', '3.25', '25.47']]),
  ('variant scenario 1', (['0.90', '3.50', '2.48'],), 'invalid'),
  ('variant scenario 2',
   (['7.05', '4.46', '2.67', '3.12'],),
   ['6.11', '5.76', ['7.48', '4.73', '2.83', '3.31']])]]
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 fair coin['0.00', '0.00', ['2.00', '2.00']]['0.00', '0.00', ['2.00', '2.00']]Passed
control standard juice['4.71', '4.50', ['2.00', '2.00']]['4.71', '4.50', ['2.00', '2.00']]Passed
boundary three-way['5.73', '5.42', ['2.64', '3.38', '3.07']]['5.73', '5.42', ['2.64', '3.38', '3.07']]Passed
boundary no-profit priceinvalidinvalidPassed
regression: negative format['-0.13', '-0.13', ['3.13', '2.06', '5.15']]['-0.13', '-0.13', ['3.13', '2.06', '5.15']]Passed
regression: negative format['-0.00', '-0.00', ['2.00', '2.00']]['0.00', '0.00', ['2.00', '2.00']]Failed
variant scenario 1['13.07', '11.56', ['10.23', '2.33', '2.11']]['13.07', '11.56', ['10.23', '2.33', '2.11']]Passed
variant scenario 2['0.39', '0.39', ['5.66', '2.17', '2.76']]['0.39', '0.39', ['5.66', '2.17', '2.76']]Passed

SHA-256 / f601e6b02c997e4ea3edbfc3a741260c829996b67c81eef9af30b19a1a46052f

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(prices):
    def fmt(x):
        c = math.floor(x * 100 + Fraction(1, 2))
        sign = '-' if c < 0 else ''
        c = abs(c)
        return sign + '%d.%02d' % (c // 100, c % 100)
    ds = [Fraction(p) for p in prices]
    if any(d <= 1 for d in ds):
        return 'invalid'
    book = sum(1 / d for d in ds)
    over = (book - 1) * 100
    margin = (1 - 1 / book) * 100
    fair = [fmt(d * book) for d in ds]
    return [fmt(over), fmt(margin), 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 fair coin', (['2.00', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('control standard juice', (['1.91', '1.91'],), ['4.71', '4.50', ['2.00', '2.00']]),
  ('boundary three-way', (['2.50', '3.20', '2.90'],), ['5.73', '5.42', ['2.64', '3.38', '3.07']]),
  ('boundary no-profit price', (['1.00', '5.00'],), 'invalid'),
  ('regression: negative format',
   (['3.13', '2.06', '5.16'],),
   ['-0.13', '-0.13', ['3.13', '2.06', '5.15']]),
  ('regression: negative format', (['2.0002', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('variant scenario 1',
   (['9.05', '2.06', '1.87'],),
   ['13.07', '11.56', ['10.23', '2.33', '2.11']]),
  ('variant scenario 2', (['5.64', '2.16', '2.75'],), ['0.39', '0.39', ['5.66', '2.17', '2.76']])],
 [('control fair coin', (['2.00', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('control standard juice', (['1.91', '1.91'],), ['4.71', '4.50', ['2.00', '2.00']]),
  ('boundary three-way', (['2.50', '3.20', '2.90'],), ['5.73', '5.42', ['2.64', '3.38', '3.07']]),
  ('boundary no-profit price', (['1.00', '5.00'],), 'invalid'),
  ('regression: negative format',
   (['2.70', '2.85', '17.25', '5.00'],),
   ['-2.08', '-2.12', ['2.64', '2.79', '16.89', '4.90']]),
  ('regression: negative format', (['2.0002', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('variant scenario 1', (['3.09', '1.42'],), ['2.78', '2.71', ['3.18', '1.46']]),
  ('variant scenario 2', (['4.24', '1.99', '3.04'],), ['6.73', '6.31', ['4.53', '2.12', '3.24']])],
 [('control fair coin', (['2.00', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('control standard juice', (['1.91', '1.91'],), ['4.71', '4.50', ['2.00', '2.00']]),
  ('boundary three-way', (['2.50', '3.20', '2.90'],), ['5.73', '5.42', ['2.64', '3.38', '3.07']]),
  ('boundary no-profit price', (['1.00', '5.00'],), 'invalid'),
  ('regression: negative format',
   (['8.77', '3.61', '3.44', '3.17'],),
   ['-0.28', '-0.28', ['8.75', '3.60', '3.43', '3.16']]),
  ('regression: negative format', (['2.0001', '2.0001'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('variant scenario 1', (['2.70', '2.41', '2.77'],), ['14.63', '12.76', ['3.10', '2.76', '3.18']]),
  ('variant scenario 2', (['4.44', '1.08'],), ['15.12', '13.13', ['5.11', '1.24']])],
 [('control fair coin', (['2.00', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('control standard juice', (['1.91', '1.91'],), ['4.71', '4.50', ['2.00', '2.00']]),
  ('boundary three-way', (['2.50', '3.20', '2.90'],), ['5.73', '5.42', ['2.64', '3.38', '3.07']]),
  ('boundary no-profit price', (['1.00', '5.00'],), 'invalid'),
  ('regression: negative format',
   (['14.48', '2.85', '3.84', '3.27'],),
   ['-1.38', '-1.40', ['14.28', '2.81', '3.79', '3.22']]),
  ('regression: negative format', (['2.0002', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('variant scenario 1',
   (['4.40', '5.01', '2.99', '2.89'],),
   ['10.73', '9.69', ['4.87', '5.55', '3.31', '3.20']]),
  ('variant scenario 2', (['2.01', '1.74'],), ['7.22', '6.74', ['2.16', '1.87']])],
 [('control fair coin', (['2.00', '2.00'],), ['0.00', '0.00', ['2.00', '2.00']]),
  ('control standard juice', (['1.91', '1.91'],), ['4.71', '4.50', ['2.00', '2.00']]),
  ('boundary three-way', (['2.50', '3.20', '2.90'],), ['5.73', '5.42', ['2.64', '3.38', '3.07']]),
  ('boundary no-profit price', (['1.00', '5.00'],), 'invalid'),
  ('regression: negative format',
   (['2.26', '3.08', '4.63'],),
   ['-1.69', '-1.72', ['2.22', '3.03', '4.55']]),
  ('regression: negative format',
   (['3.15', '2.98', '3.25', '25.47'],),
   ['0.00', '0.00', ['3.15', '2.98', '3.25', '25.47']]),
  ('variant scenario 1', (['0.90', '3.50', '2.48'],), 'invalid'),
  ('variant scenario 2',
   (['7.05', '4.46', '2.67', '3.12'],),
   ['6.11', '5.76', ['7.48', '4.73', '2.83', '3.31']])]]
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 fair coin['0.00', '0.00', ['2.00', '2.00']]['0.00', '0.00', ['2.00', '2.00']]Passed
control standard juice['4.71', '4.50', ['2.00', '2.00']]['4.71', '4.50', ['2.00', '2.00']]Passed
boundary three-way['5.73', '5.42', ['2.64', '3.38', '3.07']]['5.73', '5.42', ['2.64', '3.38', '3.07']]Passed
boundary no-profit priceinvalidinvalidPassed
regression: negative format['-0.13', '-0.13', ['3.13', '2.06', '5.15']]['-0.13', '-0.13', ['3.13', '2.06', '5.15']]Passed
regression: negative format['0.00', '0.00', ['2.00', '2.00']]['0.00', '0.00', ['2.00', '2.00']]Passed
variant scenario 1['13.07', '11.56', ['10.23', '2.33', '2.11']]['13.07', '11.56', ['10.23', '2.33', '2.11']]Passed
variant scenario 2['0.39', '0.39', ['5.66', '2.17', '2.76']]['0.39', '0.39', ['5.66', '2.17', '2.76']]Passed

SHA-256 / d00b64325f468fcb26e96add76d474c5b4d62ef2b45be805887d99abc0de8e0a

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

Case digest / 734b2c8c78c4e9ee461652bd8ea079dfe7c7059ed198e5a31670089ae34aff2c