{"abstract":"A converted value of 11.994 is listed at 11.99, below the converted amount.","category":"Currency rounding and FX conversion","checks":6,"contract":"solve(price, rate, ccy): a price list converted at rate is re-priced to the smallest charm price not below the exact converted value raw = price*rate. For JPY, charm prices end in 8 (…8 yen, i.e. 10k-2). For other currencies, charm prices end in .99. Return the charm price as a plain string.","evaluation_group":"w2-currency_rounding_and_fx_conversion-charm-price-conversion","failed_approach":"Pre-rounding to four decimals still hides sub-basis-point excess over a charm price.","family":"w2-currency_rounding_and_fx_conversion-charm-price-conversion-pre-rounded-raw","id":"FA-62316","implementations":{"attempt":{"sha256":"4f63509f4702a79d065a48202075f63039babc46095dcfa91cb6d51dffd49312","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nfrom decimal import Decimal, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_FLOOR, ROUND_CEILING, ROUND_DOWN, ROUND_UP, ROUND_HALF_DOWN\nN = 1\nobservations = []\ndef solve(price, rate, ccy):\n    raw = (Decimal(price) * Decimal(rate)).quantize(Decimal('0.0001'), rounding=ROUND_HALF_EVEN)\n    if ccy == 'JPY':\n        c = (raw / 10).to_integral_value(rounding=ROUND_CEILING) * 10 - 2\n        if c < raw: c += 10\n        return format(c, 'f')\n    c = raw.to_integral_value(rounding=ROUND_FLOOR) + Decimal('0.99')\n    if c < raw: c += 1\n    return format(c, 'f')\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[('regression pre-rounded-raw 1', ('11.994', '1', 'USD'), '12.99'),\n  ('regression pre-rounded-raw 2', ('11.99004', '1', 'GBP'), '12.99'),\n  ('control: whole number', ('12.00', '1', 'EUR'), '12.99'), ('control: already charm', ('11.99', '1', 'EUR'), '11.99'),\n  ('control: above charm', ('12.995', '1', 'EUR'), '13.99'),\n  ('control: yen round up', ('1234.5', '1', 'JPY'), '1238')],\n [('regression pre-rounded-raw 1', ('11.994', '1', 'USD'), '12.99'),\n  ('regression pre-rounded-raw 2', ('11.99004', '1', 'GBP'), '12.99'),\n  ('control: yen round up', ('1234.5', '1', 'JPY'), '1238'),\n  ('control: yen above ending', ('1239', '1', 'JPY'), '1248'),\n  ('control: yen exact ending', ('1238', '1', 'JPY'), '1238'),\n  ('control: converted euro', ('10.00', '0.92', 'EUR'), '9.99')],\n [('regression pre-rounded-raw 1', ('11.994', '1', 'USD'), '12.99'),\n  ('regression pre-rounded-raw 2', ('11.99004', '1', 'GBP'), '12.99'),\n  ('control: converted euro', ('10.00', '0.92', 'EUR'), '9.99'),\n  ('control: yen converted', ('9.99', '151.37', 'JPY'), '1518'),\n  ('control: whole number', ('12.00', '1', 'EUR'), '12.99'),\n  ('control: already charm', ('11.99', '1', 'EUR'), '11.99')],\n [('regression pre-rounded-raw 1', ('11.994', '1', 'USD'), '12.99'),\n  ('regression pre-rounded-raw 2', ('11.99004', '1', 'GBP'), '12.99'),\n  ('control: yen converted', ('9.99', '151.37', 'JPY'), '1518'),\n  ('control: whole number', ('12.00', '1', 'EUR'), '12.99'), ('control: already charm', ('11.99', '1', 'EUR'), '11.99'),\n  ('control: above charm', ('12.995', '1', 'EUR'), '13.99')],\n [('regression pre-rounded-raw 1', ('11.994', '1', 'USD'), '12.99'),\n  ('regression pre-rounded-raw 2', ('11.99004', '1', 'GBP'), '12.99'),\n  ('control: above charm', ('12.995', '1', 'EUR'), '13.99'), ('control: yen round up', ('1234.5', '1', 'JPY'), '1238'),\n  ('control: yen above ending', ('1239', '1', 'JPY'), '1248'),\n  ('control: yen exact ending', ('1238', '1', 'JPY'), '1238')]]\nfor label, args, expected in cases[N - 1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"d6dcb665128ec7a1a66c6f9417d0cc39199a8ca116b2b5117fa33a997078adf3","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nfrom decimal import Decimal, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_FLOOR, ROUND_CEILING, ROUND_DOWN, ROUND_UP, ROUND_HALF_DOWN\nN = 1\nobservations = []\ndef solve(price, rate, ccy):\n    raw = (Decimal(price) * Decimal(rate)).quantize(Decimal('0.01'), rounding=ROUND_HALF_EVEN)\n    if ccy == 'JPY':\n        c = (raw / 10).to_integral_value(rounding=ROUND_CEILING) * 10 - 2\n        if c < raw: c += 10\n        return format(c, 'f')\n    c = raw.to_integral_value(rounding=ROUND_FLOOR) + Decimal('0.99')\n    if c < raw: c += 1\n    return format(c, 'f')\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[('regression pre-rounded-raw 1', ('11.994', '1', 'USD'), '12.99'),\n  ('regression pre-rounded-raw 2', ('11.99004', '1', 'GBP'), '12.99'),\n  ('control: whole number', ('12.00', '1', 'EUR'), '12.99'), ('control: already charm', ('11.99', '1', 'EUR'), '11.99'),\n  ('control: above charm', ('12.995', '1', 'EUR'), '13.99'),\n  ('control: yen round up', ('1234.5', '1', 'JPY'), '1238')],\n [('regression pre-rounded-raw 1', ('11.994', '1', 'USD'), '12.99'),\n  ('regression pre-rounded-raw 2', ('11.99004', '1', 'GBP'), '12.99'),\n  ('control: yen round up', ('1234.5', '1', 'JPY'), '1238'),\n  ('control: yen above ending', ('1239', '1', 'JPY'), '1248'),\n  ('control: yen exact ending', ('1238', '1', 'JPY'), '1238'),\n  ('control: converted euro', ('10.00', '0.92', 'EUR'), '9.99')],\n [('regression pre-rounded-raw 1', ('11.994', '1', 'USD'), '12.99'),\n  ('regression pre-rounded-raw 2', ('11.99004', '1', 'GBP'), '12.99'),\n  ('control: converted euro', ('10.00', '0.92', 'EUR'), '9.99'),\n  ('control: yen converted', ('9.99', '151.37', 'JPY'), '1518'),\n  ('control: whole number', ('12.00', '1', 'EUR'), '12.99'),\n  ('control: already charm', ('11.99', '1', 'EUR'), '11.99')],\n [('regression pre-rounded-raw 1', ('11.994', '1', 'USD'), '12.99'),\n  ('regression pre-rounded-raw 2', ('11.99004', '1', 'GBP'), '12.99'),\n  ('control: yen converted', ('9.99', '151.37', 'JPY'), '1518'),\n  ('control: whole number', ('12.00', '1', 'EUR'), '12.99'), ('control: already charm', ('11.99', '1', 'EUR'), '11.99'),\n  ('control: above charm', ('12.995', '1', 'EUR'), '13.99')],\n [('regression pre-rounded-raw 1', ('11.994', '1', 'USD'), '12.99'),\n  ('regression pre-rounded-raw 2', ('11.99004', '1', 'GBP'), '12.99'),\n  ('control: above charm', ('12.995', '1', 'EUR'), '13.99'), ('control: yen round up', ('1234.5', '1', 'JPY'), '1238'),\n  ('control: yen above ending', ('1239', '1', 'JPY'), '1248'),\n  ('control: yen exact ending', ('1238', '1', 'JPY'), '1238')]]\nfor label, args, expected in cases[N - 1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"85c1277ebb63e8aa05d8f74951cfb9bc22a2865e706ffa82b4bda54a184e5a7b","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nfrom decimal import Decimal, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_FLOOR, ROUND_CEILING, ROUND_DOWN, ROUND_UP, ROUND_HALF_DOWN\nN = 1\nobservations = []\ndef solve(price, rate, ccy):\n    raw = Decimal(price) * Decimal(rate)\n    if ccy == 'JPY':\n        c = (raw / 10).to_integral_value(rounding=ROUND_CEILING) * 10 - 2\n        if c < raw: c += 10\n        return format(c, 'f')\n    c = raw.to_integral_value(rounding=ROUND_FLOOR) + Decimal('0.99')\n    if c < raw: c += 1\n    return format(c, 'f')\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[('regression pre-rounded-raw 1', ('11.994', '1', 'USD'), '12.99'),\n  ('regression pre-rounded-raw 2', ('11.99004', '1', 'GBP'), '12.99'),\n  ('control: whole number', ('12.00', '1', 'EUR'), '12.99'), ('control: already charm', ('11.99', '1', 'EUR'), '11.99'),\n  ('control: above charm', ('12.995', '1', 'EUR'), '13.99'),\n  ('control: yen round up', ('1234.5', '1', 'JPY'), '1238')],\n [('regression pre-rounded-raw 1', ('11.994', '1', 'USD'), '12.99'),\n  ('regression pre-rounded-raw 2', ('11.99004', '1', 'GBP'), '12.99'),\n  ('control: yen round up', ('1234.5', '1', 'JPY'), '1238'),\n  ('control: yen above ending', ('1239', '1', 'JPY'), '1248'),\n  ('control: yen exact ending', ('1238', '1', 'JPY'), '1238'),\n  ('control: converted euro', ('10.00', '0.92', 'EUR'), '9.99')],\n [('regression pre-rounded-raw 1', ('11.994', '1', 'USD'), '12.99'),\n  ('regression pre-rounded-raw 2', ('11.99004', '1', 'GBP'), '12.99'),\n  ('control: converted euro', ('10.00', '0.92', 'EUR'), '9.99'),\n  ('control: yen converted', ('9.99', '151.37', 'JPY'), '1518'),\n  ('control: whole number', ('12.00', '1', 'EUR'), '12.99'),\n  ('control: already charm', ('11.99', '1', 'EUR'), '11.99')],\n [('regression pre-rounded-raw 1', ('11.994', '1', 'USD'), '12.99'),\n  ('regression pre-rounded-raw 2', ('11.99004', '1', 'GBP'), '12.99'),\n  ('control: yen converted', ('9.99', '151.37', 'JPY'), '1518'),\n  ('control: whole number', ('12.00', '1', 'EUR'), '12.99'), ('control: already charm', ('11.99', '1', 'EUR'), '11.99'),\n  ('control: above charm', ('12.995', '1', 'EUR'), '13.99')],\n [('regression pre-rounded-raw 1', ('11.994', '1', 'USD'), '12.99'),\n  ('regression pre-rounded-raw 2', ('11.99004', '1', 'GBP'), '12.99'),\n  ('control: above charm', ('12.995', '1', 'EUR'), '13.99'), ('control: yen round up', ('1234.5', '1', 'JPY'), '1238'),\n  ('control: yen above ending', ('1239', '1', 'JPY'), '1248'),\n  ('control: yen exact ending', ('1238', '1', 'JPY'), '1238')]]\nfor label, args, expected in cases[N - 1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"A deterministic, bounded teaching model with a stipulated toy contract; it makes no claim of conformance to any real regulation, standard, or institution's rules. 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.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-currency_rounding_and_fx_conversion-charm-price-conversion-pre-rounded-raw","generated_at":"2026-09-29T14:47:03.492592+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Currency amounts must be rounded at the right stage and in the right unit, or ledgers, quotes and settlements drift by minor units.","repair":"Search charm prices against the exact converted value.","root_cause":"raw is quantized half-even to two decimals before the charm search.","sha256":"075de1fabb03a54d968df2973aa328612018824e238f3b6d6cc5145669150489","title":"The converted price is rounded to cents before charm pricing · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":46.073,"exit_code":1,"observations":[{"actual":"12.99","check":"regression pre-rounded-raw 1","expected":"12.99","passed":true},{"actual":"11.99","check":"regression pre-rounded-raw 2","expected":"12.99","passed":false},{"actual":"12.99","check":"control: whole number","expected":"12.99","passed":true},{"actual":"11.99","check":"control: already charm","expected":"11.99","passed":true},{"actual":"13.99","check":"control: above charm","expected":"13.99","passed":true},{"actual":"1238","check":"control: yen round up","expected":"1238","passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression pre-rounded-raw 1\", \"actual\": \"12.99\", \"expected\": \"12.99\", \"passed\": true}, {\"check\": \"regression pre-rounded-raw 2\", \"actual\": \"11.99\", \"expected\": \"12.99\", \"passed\": false}, {\"check\": \"control: whole number\", \"actual\": \"12.99\", \"expected\": \"12.99\", \"passed\": true}, {\"check\": \"control: already charm\", \"actual\": \"11.99\", \"expected\": \"11.99\", \"passed\": true}, {\"check\": \"control: above charm\", \"actual\": \"13.99\", \"expected\": \"13.99\", \"passed\": true}, {\"check\": \"control: yen round up\", \"actual\": \"1238\", \"expected\": \"1238\", \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":41.37,"exit_code":1,"observations":[{"actual":"11.99","check":"regression pre-rounded-raw 1","expected":"12.99","passed":false},{"actual":"11.99","check":"regression pre-rounded-raw 2","expected":"12.99","passed":false},{"actual":"12.99","check":"control: whole number","expected":"12.99","passed":true},{"actual":"11.99","check":"control: already charm","expected":"11.99","passed":true},{"actual":"13.99","check":"control: above charm","expected":"13.99","passed":true},{"actual":"1238","check":"control: yen round up","expected":"1238","passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression pre-rounded-raw 1\", \"actual\": \"11.99\", \"expected\": \"12.99\", \"passed\": false}, {\"check\": \"regression pre-rounded-raw 2\", \"actual\": \"11.99\", \"expected\": \"12.99\", \"passed\": false}, {\"check\": \"control: whole number\", \"actual\": \"12.99\", \"expected\": \"12.99\", \"passed\": true}, {\"check\": \"control: already charm\", \"actual\": \"11.99\", \"expected\": \"11.99\", \"passed\": true}, {\"check\": \"control: above charm\", \"actual\": \"13.99\", \"expected\": \"13.99\", \"passed\": true}, {\"check\": \"control: yen round up\", \"actual\": \"1238\", \"expected\": \"1238\", \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":41.764,"exit_code":0,"observations":[{"actual":"12.99","check":"regression pre-rounded-raw 1","expected":"12.99","passed":true},{"actual":"12.99","check":"regression pre-rounded-raw 2","expected":"12.99","passed":true},{"actual":"12.99","check":"control: whole number","expected":"12.99","passed":true},{"actual":"11.99","check":"control: already charm","expected":"11.99","passed":true},{"actual":"13.99","check":"control: above charm","expected":"13.99","passed":true},{"actual":"1238","check":"control: yen round up","expected":"1238","passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression pre-rounded-raw 1\", \"actual\": \"12.99\", \"expected\": \"12.99\", \"passed\": true}, {\"check\": \"regression pre-rounded-raw 2\", \"actual\": \"12.99\", \"expected\": \"12.99\", \"passed\": true}, {\"check\": \"control: whole number\", \"actual\": \"12.99\", \"expected\": \"12.99\", \"passed\": true}, {\"check\": \"control: already charm\", \"actual\": \"11.99\", \"expected\": \"11.99\", \"passed\": true}, {\"check\": \"control: above charm\", \"actual\": \"13.99\", \"expected\": \"13.99\", \"passed\": true}, {\"check\": \"control: yen round up\", \"actual\": \"1238\", \"expected\": \"1238\", \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}