FA-61881 / Currency rounding and FX conversion / Open access
A missing cross rate is silently treated as parity · case 01
Converting into a currency with no published rate returns the USD amount relabelled.
ROOT CAUSE
rate() returns Decimal(1) for any absent currency instead of None.
VERIFIED REPAIR
Only USD may default to 1; every other absent currency is reported as ERR:no-rate.
Unsuccessful approach: Rejecting only a missing target rate still converts from an unpriced source at parity.
Case contract
solve(amount, frm, to, rates): rates maps a currency to units of that currency per 1 USD (decimal strings); USD is implicitly 1 when absent. Convert exactly as amount / rate[frm] * rate[to] with no intermediate rounding, then round half-even to the target exponent (USD/EUR/GBP/CHF/SEK/NOK 2, JPY/KRW 0, KWD 3, CLF 4) and return a plain string. A missing rate returns 'ERR:no-rate:<code>', a zero or negative rate 'ERR:bad-rate:<code>' (source checked first).
Why this case matters
Currency amounts must be rounded at the right stage and in the right unit, or ledgers, quotes and settlements drift by minor units.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
from decimal import Decimal, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_FLOOR, ROUND_CEILING, ROUND_DOWN, ROUND_UP, ROUND_HALF_DOWN
N = 1
observations = []
def solve(amount, frm, to, rates):
exps = {'USD': 2, 'EUR': 2, 'GBP': 2, 'CHF': 2, 'SEK': 2, 'NOK': 2, 'JPY': 0, 'KRW': 0, 'KWD': 3, 'CLF': 4}
def rate(c):
if c == 'USD' and c not in rates: return Decimal(1)
if c not in rates: return Decimal(1)
return Decimal(rates[c])
rf, rt = rate(frm), rate(to)
for c, r in ((frm, rf), (to, rt)):
if r is None: return 'ERR:no-rate:' + c
if r <= 0: return 'ERR:bad-rate:' + c
usd = Decimal(amount) / rf
out = usd * rt
return format(out.quantize(Decimal(1).scaleb(-exps[to]), rounding=ROUND_HALF_EVEN), 'f')
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression missing-rate 1',
('10', 'SEK', 'EUR',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK'),
('regression missing-rate 2',
('10', 'EUR', 'SEK',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK'),
('partial repair guard 2',
('7', 'NOK', 'USD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:NOK'),
('control: euro to yen',
('100', 'EUR', 'JPY',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'16453'),
('control: usd to dinar',
('100.00', 'USD', 'KWD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'30.710'),
('control: pound to usd',
('5', 'GBP', 'USD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'6.33'),
('control: missing target',
('1', 'EUR', 'SEK',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK')],
[('regression missing-rate 1',
('7', 'NOK', 'USD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:NOK'),
('regression missing-rate 2',
('1', 'EUR', 'SEK',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK'),
('partial repair guard 1',
('60486', 'JPY', 'GBP', {'KRW': '1352.5', 'KWD': '0.3071', 'CLF': '0.02451', 'CHF': '0.8801', 'USD': '1'}),
'ERR:no-rate:JPY'),
('partial repair guard 2',
('86178.804', 'EUR', 'JPY',
{'JPY': '151.37', 'KRW': '1352.5', 'KWD': '0.3071', 'GBP': '0.7893', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:EUR'),
('control: won to franc',
('250000', 'KRW', 'CHF',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'162.68'),
('control: yen to unit of account',
('99999', 'JPY', 'CLF',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'16.1920'),
('control: zero rate target', ('10', 'EUR', 'CHF', {'EUR': '0.92', 'CHF': '0'}), 'ERR:bad-rate:CHF'),
('control: explicit usd rate', ('10', 'USD', 'EUR', {'USD': '1', 'EUR': '0.92'}), '9.20')],
[('regression missing-rate 1',
('133282.75', 'EUR', 'GBP',
{'EUR': '0.92', 'JPY': '151.37', 'KRW': '1352.5', 'KWD': '0.3071', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:GBP'),
('regression missing-rate 2',
('60486', 'JPY', 'GBP', {'KRW': '1352.5', 'KWD': '0.3071', 'CLF': '0.02451', 'CHF': '0.8801', 'USD': '1'}),
'ERR:no-rate:JPY'),
('partial repair guard 1',
('63563', 'EUR', 'JPY',
{'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801',
'USD': '1'}),
'ERR:no-rate:EUR'),
('partial repair guard 2',
('74606.31', 'JPY', 'KWD', {'KRW': '1352.5', 'KWD': '0.3071', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:JPY'),
('control: zero rate target', ('10', 'EUR', 'CHF', {'EUR': '0.92', 'CHF': '0'}), 'ERR:bad-rate:CHF'),
('control: explicit usd rate', ('10', 'USD', 'EUR', {'USD': '1', 'EUR': '0.92'}), '9.20'),
('control: usd absent', ('42.42', 'EUR', 'USD', {'EUR': '0.92'}), '46.11'),
('control: euro to yen',
('100', 'EUR', 'JPY',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'16453')],
[('regression missing-rate 1',
('86178.804', 'EUR', 'JPY',
{'JPY': '151.37', 'KRW': '1352.5', 'KWD': '0.3071', 'GBP': '0.7893', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:EUR'),
('regression missing-rate 2',
('63563', 'EUR', 'JPY',
{'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801',
'USD': '1'}),
'ERR:no-rate:EUR'),
('partial repair guard 1',
('37459.62', 'JPY', 'CHF',
{'EUR': '0.92', 'KRW': '1352.5', 'KWD': '0.3071', 'GBP': '0.7893', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:JPY'),
('partial repair guard 2',
('193634', 'EUR', 'JPY',
{'JPY': '151.37', 'KRW': '1352.5', 'KWD': '0.3071', 'GBP': '0.7893', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:EUR'),
('control: euro to yen',
('100', 'EUR', 'JPY',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'16453'),
('control: usd to dinar',
('100.00', 'USD', 'KWD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'30.710'),
('control: pound to usd',
('5', 'GBP', 'USD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'6.33'),
('control: missing target',
('1', 'EUR', 'SEK',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK')],
[('regression missing-rate 1',
('70022.25', 'GBP', 'EUR',
{'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801',
'USD': '1'}),
'ERR:no-rate:EUR'),
('regression missing-rate 2',
('74606.31', 'JPY', 'KWD', {'KRW': '1352.5', 'KWD': '0.3071', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:JPY'),
('partial repair guard 1',
('96568.41', 'JPY', 'KRW',
{'EUR': '0.92', 'KRW': '1352.5', 'KWD': '0.3071', 'GBP': '0.7893', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:JPY'),
('partial repair guard 2',
('127530', 'CHF', 'JPY', {'EUR': '0.92', 'KRW': '1352.5', 'GBP': '0.7893', 'CLF': '0.02451'}), 'ERR:no-rate:CHF'),
('control: missing target',
('1', 'EUR', 'SEK',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK'),
('control: won to franc',
('250000', 'KRW', 'CHF',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'162.68'),
('control: yen to unit of account',
('99999', 'JPY', 'CLF',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'16.1920'),
('control: zero rate target', ('10', 'EUR', 'CHF', {'EUR': '0.92', 'CHF': '0'}), 'ERR:bad-rate:CHF')]]
for label, args, expected in cases[N - 1]:
check(label, solve(*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 |
|---|---|---|---|
| regression missing-rate 1 | 9.20 | ERR:no-rate:SEK | Failed |
| regression missing-rate 2 | 10.87 | ERR:no-rate:SEK | Failed |
| partial repair guard 2 | 7.00 | ERR:no-rate:NOK | Failed |
| control: euro to yen | 16453 | 16453 | Passed |
| control: usd to dinar | 30.710 | 30.710 | Passed |
| control: pound to usd | 6.33 | 6.33 | Passed |
| control: missing target | 1.09 | ERR:no-rate:SEK | Failed |
SHA-256 / 3426e9b25f739d6a6a86cabba60a250c085892921abec790a358fbd40b1c6e5a
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
from decimal import Decimal, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_FLOOR, ROUND_CEILING, ROUND_DOWN, ROUND_UP, ROUND_HALF_DOWN
N = 1
observations = []
def solve(amount, frm, to, rates):
exps = {'USD': 2, 'EUR': 2, 'GBP': 2, 'CHF': 2, 'SEK': 2, 'NOK': 2, 'JPY': 0, 'KRW': 0, 'KWD': 3, 'CLF': 4}
def rate(c):
if c == 'USD' and c not in rates: return Decimal(1)
if c not in rates: return None if c == to else Decimal(1)
return Decimal(rates[c])
rf, rt = rate(frm), rate(to)
for c, r in ((frm, rf), (to, rt)):
if r is None: return 'ERR:no-rate:' + c
if r <= 0: return 'ERR:bad-rate:' + c
usd = Decimal(amount) / rf
out = usd * rt
return format(out.quantize(Decimal(1).scaleb(-exps[to]), rounding=ROUND_HALF_EVEN), 'f')
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression missing-rate 1',
('10', 'SEK', 'EUR',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK'),
('regression missing-rate 2',
('10', 'EUR', 'SEK',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK'),
('partial repair guard 2',
('7', 'NOK', 'USD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:NOK'),
('control: euro to yen',
('100', 'EUR', 'JPY',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'16453'),
('control: usd to dinar',
('100.00', 'USD', 'KWD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'30.710'),
('control: pound to usd',
('5', 'GBP', 'USD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'6.33'),
('control: missing target',
('1', 'EUR', 'SEK',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK')],
[('regression missing-rate 1',
('7', 'NOK', 'USD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:NOK'),
('regression missing-rate 2',
('1', 'EUR', 'SEK',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK'),
('partial repair guard 1',
('60486', 'JPY', 'GBP', {'KRW': '1352.5', 'KWD': '0.3071', 'CLF': '0.02451', 'CHF': '0.8801', 'USD': '1'}),
'ERR:no-rate:JPY'),
('partial repair guard 2',
('86178.804', 'EUR', 'JPY',
{'JPY': '151.37', 'KRW': '1352.5', 'KWD': '0.3071', 'GBP': '0.7893', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:EUR'),
('control: won to franc',
('250000', 'KRW', 'CHF',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'162.68'),
('control: yen to unit of account',
('99999', 'JPY', 'CLF',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'16.1920'),
('control: zero rate target', ('10', 'EUR', 'CHF', {'EUR': '0.92', 'CHF': '0'}), 'ERR:bad-rate:CHF'),
('control: explicit usd rate', ('10', 'USD', 'EUR', {'USD': '1', 'EUR': '0.92'}), '9.20')],
[('regression missing-rate 1',
('133282.75', 'EUR', 'GBP',
{'EUR': '0.92', 'JPY': '151.37', 'KRW': '1352.5', 'KWD': '0.3071', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:GBP'),
('regression missing-rate 2',
('60486', 'JPY', 'GBP', {'KRW': '1352.5', 'KWD': '0.3071', 'CLF': '0.02451', 'CHF': '0.8801', 'USD': '1'}),
'ERR:no-rate:JPY'),
('partial repair guard 1',
('63563', 'EUR', 'JPY',
{'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801',
'USD': '1'}),
'ERR:no-rate:EUR'),
('partial repair guard 2',
('74606.31', 'JPY', 'KWD', {'KRW': '1352.5', 'KWD': '0.3071', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:JPY'),
('control: zero rate target', ('10', 'EUR', 'CHF', {'EUR': '0.92', 'CHF': '0'}), 'ERR:bad-rate:CHF'),
('control: explicit usd rate', ('10', 'USD', 'EUR', {'USD': '1', 'EUR': '0.92'}), '9.20'),
('control: usd absent', ('42.42', 'EUR', 'USD', {'EUR': '0.92'}), '46.11'),
('control: euro to yen',
('100', 'EUR', 'JPY',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'16453')],
[('regression missing-rate 1',
('86178.804', 'EUR', 'JPY',
{'JPY': '151.37', 'KRW': '1352.5', 'KWD': '0.3071', 'GBP': '0.7893', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:EUR'),
('regression missing-rate 2',
('63563', 'EUR', 'JPY',
{'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801',
'USD': '1'}),
'ERR:no-rate:EUR'),
('partial repair guard 1',
('37459.62', 'JPY', 'CHF',
{'EUR': '0.92', 'KRW': '1352.5', 'KWD': '0.3071', 'GBP': '0.7893', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:JPY'),
('partial repair guard 2',
('193634', 'EUR', 'JPY',
{'JPY': '151.37', 'KRW': '1352.5', 'KWD': '0.3071', 'GBP': '0.7893', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:EUR'),
('control: euro to yen',
('100', 'EUR', 'JPY',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'16453'),
('control: usd to dinar',
('100.00', 'USD', 'KWD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'30.710'),
('control: pound to usd',
('5', 'GBP', 'USD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'6.33'),
('control: missing target',
('1', 'EUR', 'SEK',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK')],
[('regression missing-rate 1',
('70022.25', 'GBP', 'EUR',
{'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801',
'USD': '1'}),
'ERR:no-rate:EUR'),
('regression missing-rate 2',
('74606.31', 'JPY', 'KWD', {'KRW': '1352.5', 'KWD': '0.3071', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:JPY'),
('partial repair guard 1',
('96568.41', 'JPY', 'KRW',
{'EUR': '0.92', 'KRW': '1352.5', 'KWD': '0.3071', 'GBP': '0.7893', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:JPY'),
('partial repair guard 2',
('127530', 'CHF', 'JPY', {'EUR': '0.92', 'KRW': '1352.5', 'GBP': '0.7893', 'CLF': '0.02451'}), 'ERR:no-rate:CHF'),
('control: missing target',
('1', 'EUR', 'SEK',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK'),
('control: won to franc',
('250000', 'KRW', 'CHF',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'162.68'),
('control: yen to unit of account',
('99999', 'JPY', 'CLF',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'16.1920'),
('control: zero rate target', ('10', 'EUR', 'CHF', {'EUR': '0.92', 'CHF': '0'}), 'ERR:bad-rate:CHF')]]
for label, args, expected in cases[N - 1]:
check(label, solve(*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 |
|---|---|---|---|
| regression missing-rate 1 | 9.20 | ERR:no-rate:SEK | Failed |
| regression missing-rate 2 | ERR:no-rate:SEK | ERR:no-rate:SEK | Passed |
| partial repair guard 2 | 7.00 | ERR:no-rate:NOK | Failed |
| control: euro to yen | 16453 | 16453 | Passed |
| control: usd to dinar | 30.710 | 30.710 | Passed |
| control: pound to usd | 6.33 | 6.33 | Passed |
| control: missing target | ERR:no-rate:SEK | ERR:no-rate:SEK | Passed |
SHA-256 / 23a39b3629ec4172f97e8be582087166fc05fc65bbe5629f405df223dd8a099d
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
from decimal import Decimal, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_FLOOR, ROUND_CEILING, ROUND_DOWN, ROUND_UP, ROUND_HALF_DOWN
N = 1
observations = []
def solve(amount, frm, to, rates):
exps = {'USD': 2, 'EUR': 2, 'GBP': 2, 'CHF': 2, 'SEK': 2, 'NOK': 2, 'JPY': 0, 'KRW': 0, 'KWD': 3, 'CLF': 4}
def rate(c):
if c == 'USD' and c not in rates: return Decimal(1)
if c not in rates: return None
return Decimal(rates[c])
rf, rt = rate(frm), rate(to)
for c, r in ((frm, rf), (to, rt)):
if r is None: return 'ERR:no-rate:' + c
if r <= 0: return 'ERR:bad-rate:' + c
usd = Decimal(amount) / rf
out = usd * rt
return format(out.quantize(Decimal(1).scaleb(-exps[to]), rounding=ROUND_HALF_EVEN), 'f')
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression missing-rate 1',
('10', 'SEK', 'EUR',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK'),
('regression missing-rate 2',
('10', 'EUR', 'SEK',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK'),
('partial repair guard 2',
('7', 'NOK', 'USD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:NOK'),
('control: euro to yen',
('100', 'EUR', 'JPY',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'16453'),
('control: usd to dinar',
('100.00', 'USD', 'KWD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'30.710'),
('control: pound to usd',
('5', 'GBP', 'USD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'6.33'),
('control: missing target',
('1', 'EUR', 'SEK',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK')],
[('regression missing-rate 1',
('7', 'NOK', 'USD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:NOK'),
('regression missing-rate 2',
('1', 'EUR', 'SEK',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK'),
('partial repair guard 1',
('60486', 'JPY', 'GBP', {'KRW': '1352.5', 'KWD': '0.3071', 'CLF': '0.02451', 'CHF': '0.8801', 'USD': '1'}),
'ERR:no-rate:JPY'),
('partial repair guard 2',
('86178.804', 'EUR', 'JPY',
{'JPY': '151.37', 'KRW': '1352.5', 'KWD': '0.3071', 'GBP': '0.7893', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:EUR'),
('control: won to franc',
('250000', 'KRW', 'CHF',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'162.68'),
('control: yen to unit of account',
('99999', 'JPY', 'CLF',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'16.1920'),
('control: zero rate target', ('10', 'EUR', 'CHF', {'EUR': '0.92', 'CHF': '0'}), 'ERR:bad-rate:CHF'),
('control: explicit usd rate', ('10', 'USD', 'EUR', {'USD': '1', 'EUR': '0.92'}), '9.20')],
[('regression missing-rate 1',
('133282.75', 'EUR', 'GBP',
{'EUR': '0.92', 'JPY': '151.37', 'KRW': '1352.5', 'KWD': '0.3071', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:GBP'),
('regression missing-rate 2',
('60486', 'JPY', 'GBP', {'KRW': '1352.5', 'KWD': '0.3071', 'CLF': '0.02451', 'CHF': '0.8801', 'USD': '1'}),
'ERR:no-rate:JPY'),
('partial repair guard 1',
('63563', 'EUR', 'JPY',
{'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801',
'USD': '1'}),
'ERR:no-rate:EUR'),
('partial repair guard 2',
('74606.31', 'JPY', 'KWD', {'KRW': '1352.5', 'KWD': '0.3071', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:JPY'),
('control: zero rate target', ('10', 'EUR', 'CHF', {'EUR': '0.92', 'CHF': '0'}), 'ERR:bad-rate:CHF'),
('control: explicit usd rate', ('10', 'USD', 'EUR', {'USD': '1', 'EUR': '0.92'}), '9.20'),
('control: usd absent', ('42.42', 'EUR', 'USD', {'EUR': '0.92'}), '46.11'),
('control: euro to yen',
('100', 'EUR', 'JPY',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'16453')],
[('regression missing-rate 1',
('86178.804', 'EUR', 'JPY',
{'JPY': '151.37', 'KRW': '1352.5', 'KWD': '0.3071', 'GBP': '0.7893', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:EUR'),
('regression missing-rate 2',
('63563', 'EUR', 'JPY',
{'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801',
'USD': '1'}),
'ERR:no-rate:EUR'),
('partial repair guard 1',
('37459.62', 'JPY', 'CHF',
{'EUR': '0.92', 'KRW': '1352.5', 'KWD': '0.3071', 'GBP': '0.7893', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:JPY'),
('partial repair guard 2',
('193634', 'EUR', 'JPY',
{'JPY': '151.37', 'KRW': '1352.5', 'KWD': '0.3071', 'GBP': '0.7893', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:EUR'),
('control: euro to yen',
('100', 'EUR', 'JPY',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'16453'),
('control: usd to dinar',
('100.00', 'USD', 'KWD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'30.710'),
('control: pound to usd',
('5', 'GBP', 'USD',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'6.33'),
('control: missing target',
('1', 'EUR', 'SEK',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK')],
[('regression missing-rate 1',
('70022.25', 'GBP', 'EUR',
{'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801',
'USD': '1'}),
'ERR:no-rate:EUR'),
('regression missing-rate 2',
('74606.31', 'JPY', 'KWD', {'KRW': '1352.5', 'KWD': '0.3071', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:JPY'),
('partial repair guard 1',
('96568.41', 'JPY', 'KRW',
{'EUR': '0.92', 'KRW': '1352.5', 'KWD': '0.3071', 'GBP': '0.7893', 'CLF': '0.02451', 'CHF': '0.8801'}),
'ERR:no-rate:JPY'),
('partial repair guard 2',
('127530', 'CHF', 'JPY', {'EUR': '0.92', 'KRW': '1352.5', 'GBP': '0.7893', 'CLF': '0.02451'}), 'ERR:no-rate:CHF'),
('control: missing target',
('1', 'EUR', 'SEK',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'ERR:no-rate:SEK'),
('control: won to franc',
('250000', 'KRW', 'CHF',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'162.68'),
('control: yen to unit of account',
('99999', 'JPY', 'CLF',
{'EUR': '0.92',
'JPY': '151.37',
'KRW': '1352.5',
'KWD': '0.3071',
'GBP': '0.7893',
'CLF': '0.02451',
'CHF': '0.8801'}),
'16.1920'),
('control: zero rate target', ('10', 'EUR', 'CHF', {'EUR': '0.92', 'CHF': '0'}), 'ERR:bad-rate:CHF')]]
for label, args, expected in cases[N - 1]:
check(label, solve(*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 |
|---|---|---|---|
| regression missing-rate 1 | ERR:no-rate:SEK | ERR:no-rate:SEK | Passed |
| regression missing-rate 2 | ERR:no-rate:SEK | ERR:no-rate:SEK | Passed |
| partial repair guard 2 | ERR:no-rate:NOK | ERR:no-rate:NOK | Passed |
| control: euro to yen | 16453 | 16453 | Passed |
| control: usd to dinar | 30.710 | 30.710 | Passed |
| control: pound to usd | 6.33 | 6.33 | Passed |
| control: missing target | ERR:no-rate:SEK | ERR:no-rate:SEK | Passed |
SHA-256 / 79c8cbf20dff496c35b5df5ff14729a4f87ca6e20c315100929b4b66a4755850
Verification & scope
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.
Observations recorded using Python 3.12.14 at 2026-09-29T14:46:59.371798+00:00.
Case digest / db9022c6abe73dd13119a3a69e79362f04814c77cb15d81b46490e51e62742e0