FAILURE MAP
← Case archive

FA-84341 / Betting odds conversion / Open access

Evens decimal price converted to a negative moneyline · case 01

A 2.00 price is displayed as -100 instead of +100.

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

ROOT CAUSE

The underdog branch requires d > 2, so evens falls through to the favourite formula.

VERIFIED REPAIR

Use the positive branch for d >= 2.

Unsuccessful approach: Special-casing evens as an unsigned "100" still violates the signed output format.

Case contract

Convert a decimal price string to an American moneyline string. Prices at or below 1 return "invalid". For d >= 2 the line is "+" followed by 100 * (d - 1); for d < 2 it is "-" followed by 100 / (d - 1). The magnitude is computed exactly from the decimal text and rounded half up to an integer. Evens (2.00) is "+100".

Why this case matters

Sportsbooks display the same price in decimal and American formats and must agree at every boundary.

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(decimal):
    d = Fraction(decimal)
    if d <= 1:
        return 'invalid'
    if d > 2:
        v = (d - 1) * 100
        sign = '+'
    else:
        v = 100 / (d - 1)
        sign = '-'
    n = math.floor(v + Fraction(1, 2))
    return sign + str(n)
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 underdog', ('2.50',), '+150'),
  ('control favourite', ('1.50',), '-200'),
  ('boundary evens', ('2.00',), '+100'),
  ('boundary half-cent rounds up', ('2.005',), '+101'),
  ('boundary no-profit price', ('1.00',), 'invalid'),
  ('control short favourite', ('1.08',), '-1250'),
  ('regression: evens branch', ('2.00',), '+100'),
  ('variant scenario 1', ('1.08',), '-1250'),
  ('variant scenario 2', ('2.125',), '+113')],
 [('control underdog', ('2.50',), '+150'),
  ('control favourite', ('1.50',), '-200'),
  ('boundary evens', ('2.00',), '+100'),
  ('boundary half-cent rounds up', ('2.005',), '+101'),
  ('boundary no-profit price', ('1.00',), 'invalid'),
  ('control short favourite', ('1.08',), '-1250'),
  ('regression: evens branch', ('2.00',), '+100'),
  ('variant scenario 1', ('6.11',), '+511'),
  ('variant scenario 2', ('5.20',), '+420')],
 [('control underdog', ('2.50',), '+150'),
  ('control favourite', ('1.50',), '-200'),
  ('boundary evens', ('2.00',), '+100'),
  ('boundary half-cent rounds up', ('2.005',), '+101'),
  ('boundary no-profit price', ('1.00',), 'invalid'),
  ('control short favourite', ('1.08',), '-1250'),
  ('regression: evens branch', ('2.00',), '+100'),
  ('variant scenario 1', ('6.85',), '+585'),
  ('variant scenario 2', ('4.10',), '+310')],
 [('control underdog', ('2.50',), '+150'),
  ('control favourite', ('1.50',), '-200'),
  ('boundary evens', ('2.00',), '+100'),
  ('boundary half-cent rounds up', ('2.005',), '+101'),
  ('boundary no-profit price', ('1.00',), 'invalid'),
  ('control short favourite', ('1.08',), '-1250'),
  ('regression: evens branch', ('2.00',), '+100'),
  ('variant scenario 1', ('6.35',), '+535'),
  ('variant scenario 2', ('2.806',), '+181')],
 [('control underdog', ('2.50',), '+150'),
  ('control favourite', ('1.50',), '-200'),
  ('boundary evens', ('2.00',), '+100'),
  ('boundary half-cent rounds up', ('2.005',), '+101'),
  ('boundary no-profit price', ('1.00',), 'invalid'),
  ('control short favourite', ('1.08',), '-1250'),
  ('regression: evens branch', ('2.00',), '+100'),
  ('variant scenario 1', ('8.36',), '+736'),
  ('variant scenario 2', ('5.69',), '+469')]]
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 underdog+150+150Passed
control favourite-200-200Passed
boundary evens-100+100Failed
boundary half-cent rounds up+101+101Passed
boundary no-profit priceinvalidinvalidPassed
control short favourite-1250-1250Passed
regression: evens branch-100+100Failed
variant scenario 1-1250-1250Passed
variant scenario 2+113+113Passed

SHA-256 / 817aae2462e04cfc0299f90d9fd7857ce33213dc83905f775b02a991d1263998

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(decimal):
    d = Fraction(decimal)
    if d <= 1:
        return 'invalid'
    if d == 2:
        return '100'
    if d > 2:
        v = (d - 1) * 100
        sign = '+'
    else:
        v = 100 / (d - 1)
        sign = '-'
    n = math.floor(v + Fraction(1, 2))
    return sign + str(n)
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 underdog', ('2.50',), '+150'),
  ('control favourite', ('1.50',), '-200'),
  ('boundary evens', ('2.00',), '+100'),
  ('boundary half-cent rounds up', ('2.005',), '+101'),
  ('boundary no-profit price', ('1.00',), 'invalid'),
  ('control short favourite', ('1.08',), '-1250'),
  ('regression: evens branch', ('2.00',), '+100'),
  ('variant scenario 1', ('1.08',), '-1250'),
  ('variant scenario 2', ('2.125',), '+113')],
 [('control underdog', ('2.50',), '+150'),
  ('control favourite', ('1.50',), '-200'),
  ('boundary evens', ('2.00',), '+100'),
  ('boundary half-cent rounds up', ('2.005',), '+101'),
  ('boundary no-profit price', ('1.00',), 'invalid'),
  ('control short favourite', ('1.08',), '-1250'),
  ('regression: evens branch', ('2.00',), '+100'),
  ('variant scenario 1', ('6.11',), '+511'),
  ('variant scenario 2', ('5.20',), '+420')],
 [('control underdog', ('2.50',), '+150'),
  ('control favourite', ('1.50',), '-200'),
  ('boundary evens', ('2.00',), '+100'),
  ('boundary half-cent rounds up', ('2.005',), '+101'),
  ('boundary no-profit price', ('1.00',), 'invalid'),
  ('control short favourite', ('1.08',), '-1250'),
  ('regression: evens branch', ('2.00',), '+100'),
  ('variant scenario 1', ('6.85',), '+585'),
  ('variant scenario 2', ('4.10',), '+310')],
 [('control underdog', ('2.50',), '+150'),
  ('control favourite', ('1.50',), '-200'),
  ('boundary evens', ('2.00',), '+100'),
  ('boundary half-cent rounds up', ('2.005',), '+101'),
  ('boundary no-profit price', ('1.00',), 'invalid'),
  ('control short favourite', ('1.08',), '-1250'),
  ('regression: evens branch', ('2.00',), '+100'),
  ('variant scenario 1', ('6.35',), '+535'),
  ('variant scenario 2', ('2.806',), '+181')],
 [('control underdog', ('2.50',), '+150'),
  ('control favourite', ('1.50',), '-200'),
  ('boundary evens', ('2.00',), '+100'),
  ('boundary half-cent rounds up', ('2.005',), '+101'),
  ('boundary no-profit price', ('1.00',), 'invalid'),
  ('control short favourite', ('1.08',), '-1250'),
  ('regression: evens branch', ('2.00',), '+100'),
  ('variant scenario 1', ('8.36',), '+736'),
  ('variant scenario 2', ('5.69',), '+469')]]
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 underdog+150+150Passed
control favourite-200-200Passed
boundary evens100+100Failed
boundary half-cent rounds up+101+101Passed
boundary no-profit priceinvalidinvalidPassed
control short favourite-1250-1250Passed
regression: evens branch100+100Failed
variant scenario 1-1250-1250Passed
variant scenario 2+113+113Passed

SHA-256 / bedbf93eb64d2b4e04b6f05ad81dd8e920309583484b7124ac95d159a396b073

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(decimal):
    d = Fraction(decimal)
    if d <= 1:
        return 'invalid'
    if d >= 2:
        v = (d - 1) * 100
        sign = '+'
    else:
        v = 100 / (d - 1)
        sign = '-'
    n = math.floor(v + Fraction(1, 2))
    return sign + str(n)
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 underdog', ('2.50',), '+150'),
  ('control favourite', ('1.50',), '-200'),
  ('boundary evens', ('2.00',), '+100'),
  ('boundary half-cent rounds up', ('2.005',), '+101'),
  ('boundary no-profit price', ('1.00',), 'invalid'),
  ('control short favourite', ('1.08',), '-1250'),
  ('regression: evens branch', ('2.00',), '+100'),
  ('variant scenario 1', ('1.08',), '-1250'),
  ('variant scenario 2', ('2.125',), '+113')],
 [('control underdog', ('2.50',), '+150'),
  ('control favourite', ('1.50',), '-200'),
  ('boundary evens', ('2.00',), '+100'),
  ('boundary half-cent rounds up', ('2.005',), '+101'),
  ('boundary no-profit price', ('1.00',), 'invalid'),
  ('control short favourite', ('1.08',), '-1250'),
  ('regression: evens branch', ('2.00',), '+100'),
  ('variant scenario 1', ('6.11',), '+511'),
  ('variant scenario 2', ('5.20',), '+420')],
 [('control underdog', ('2.50',), '+150'),
  ('control favourite', ('1.50',), '-200'),
  ('boundary evens', ('2.00',), '+100'),
  ('boundary half-cent rounds up', ('2.005',), '+101'),
  ('boundary no-profit price', ('1.00',), 'invalid'),
  ('control short favourite', ('1.08',), '-1250'),
  ('regression: evens branch', ('2.00',), '+100'),
  ('variant scenario 1', ('6.85',), '+585'),
  ('variant scenario 2', ('4.10',), '+310')],
 [('control underdog', ('2.50',), '+150'),
  ('control favourite', ('1.50',), '-200'),
  ('boundary evens', ('2.00',), '+100'),
  ('boundary half-cent rounds up', ('2.005',), '+101'),
  ('boundary no-profit price', ('1.00',), 'invalid'),
  ('control short favourite', ('1.08',), '-1250'),
  ('regression: evens branch', ('2.00',), '+100'),
  ('variant scenario 1', ('6.35',), '+535'),
  ('variant scenario 2', ('2.806',), '+181')],
 [('control underdog', ('2.50',), '+150'),
  ('control favourite', ('1.50',), '-200'),
  ('boundary evens', ('2.00',), '+100'),
  ('boundary half-cent rounds up', ('2.005',), '+101'),
  ('boundary no-profit price', ('1.00',), 'invalid'),
  ('control short favourite', ('1.08',), '-1250'),
  ('regression: evens branch', ('2.00',), '+100'),
  ('variant scenario 1', ('8.36',), '+736'),
  ('variant scenario 2', ('5.69',), '+469')]]
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 underdog+150+150Passed
control favourite-200-200Passed
boundary evens+100+100Passed
boundary half-cent rounds up+101+101Passed
boundary no-profit priceinvalidinvalidPassed
control short favourite-1250-1250Passed
regression: evens branch+100+100Passed
variant scenario 1-1250-1250Passed
variant scenario 2+113+113Passed

SHA-256 / 19d2d72f47fa6ac10e89a18b714ad0f3133ec5e16523d256996066d90deec00a

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

Case digest / a5e4f6f663de3d110963f3193eec87254cd2f0ce9f9c6bb490a1758322481976