FA-62106 / Currency rounding and FX conversion / Open access
Net amounts are emitted with the raw Decimal exponent · case 01
A net of five dollars is written as '5' rather than '5.00'.
ROOT CAUSE
The summed Decimal is formatted without quantizing to the currency exponent.
VERIFIED REPAIR
Quantize each net to its currency exponent before formatting.
Unsuccessful approach: Quantizing every currency to two decimals mis-formats yen and dinar nets.
Case contract
solve(trades): each trade is [pay_ccy, pay_amount, recv_ccy, recv_amount] from our side. Net per currency = received - paid. Return [[ccy, net], ...] sorted by currency code, omitting currencies whose net is exactly zero; nets are plain strings at the currency exponent (JPY 0, KWD 3, else 2).
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(trades):
exps = {'JPY': 0, 'KWD': 3}
net = {}
for pay_c, pay_a, rec_c, rec_a in trades:
net[pay_c] = net.get(pay_c, Decimal(0)) - Decimal(pay_a)
net[rec_c] = net.get(rec_c, Decimal(0)) + Decimal(rec_a)
out = []
for c in sorted(net):
v = net[c]
if v == 0: continue
out.append([c, format(v, 'f')])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression net-exponent 1', ([['USD', '5', 'GBP', '4']],), [['GBP', '4.00'], ['USD', '-5.00']]),
('regression net-exponent 2',
([['GBP', '3755.04', 'GBP', '2258.67'], ['JPY', '4', 'GBP', '4532.21'], ['USD', '3940', 'EUR', '3321.70'],
['KWD', '2315', 'JPY', '2875']],),
[['EUR', '3321.70'], ['GBP', '3035.84'], ['JPY', '2871'], ['KWD', '-2315.000'], ['USD', '-3940.00']]),
('partial repair guard 1', ([['KWD', '1.250', 'KWD', '1.000']],), [['KWD', '-0.250']]),
('partial repair guard 2', ([['USD', '108.35', 'EUR', '100.00'], ['EUR', '100.00', 'JPY', '16200']],),
[['JPY', '16200'], ['USD', '-108.35']]),
('control: fully offset', ([['USD', '10.00', 'EUR', '9.20'], ['EUR', '9.20', 'USD', '10.00']],), []),
('control: empty', ([],), []),
('control: unsorted codes',
([['USD', '1.00', 'EUR', '0.92'], ['GBP', '0.79', 'USD', '1.00'], ['KWD', '0.307', 'CHF', '0.88']],),
[['CHF', '0.88'], ['EUR', '0.92'], ['GBP', '-0.79'], ['KWD', '-0.307']])],
[('regression net-exponent 1',
([['EUR', '4780', 'GBP', '4817.42'], ['EUR', '937.30', 'JPY', '1728'], ['GBP', '394', 'USD', '949']],),
[['EUR', '-5717.30'], ['GBP', '4423.42'], ['JPY', '1728'], ['USD', '949.00']]),
('regression net-exponent 2',
([['GBP', '2181', 'KWD', '1051.460'], ['JPY', '550', 'EUR', '3789'], ['USD', '506.38', 'JPY', '1697'],
['KWD', '1052.629', 'EUR', '763.75']],),
[['EUR', '4552.75'], ['GBP', '-2181.00'], ['JPY', '1147'], ['KWD', '-1.169'], ['USD', '-506.38']]),
('partial repair guard 1',
([['USD', '1.00', 'EUR', '0.92'], ['GBP', '0.79', 'USD', '1.00'], ['KWD', '0.307', 'CHF', '0.88']],),
[['CHF', '0.88'], ['EUR', '0.92'], ['GBP', '-0.79'], ['KWD', '-0.307']]),
('partial repair guard 2',
([['JPY', '1806', 'KWD', '4720.108'], ['USD', '3724.50', 'JPY', '222'], ['KWD', '4720.108', 'JPY', '1806']],),
[['JPY', '222'], ['USD', '-3724.50']]),
('control: same currency swap', ([['KWD', '1.250', 'KWD', '1.000']],), [['KWD', '-0.250']]),
('control: empty', ([],), []),
('control: chained trades', ([['USD', '108.35', 'EUR', '100.00'], ['EUR', '100.00', 'JPY', '16200']],),
[['JPY', '16200'], ['USD', '-108.35']]),
('control: short amounts', ([['USD', '5', 'GBP', '4']],), [['GBP', '4.00'], ['USD', '-5.00']])],
[('regression net-exponent 1',
([['EUR', '4958.34', 'JPY', '456'], ['KWD', '149.894', 'EUR', '4865.00'], ['GBP', '4322.22', 'GBP', '4150.09'],
['USD', '4134', 'GBP', '151.91'], ['JPY', '456', 'EUR', '4958.34']],),
[['EUR', '4865.00'], ['GBP', '-20.22'], ['KWD', '-149.894'], ['USD', '-4134.00']]),
('regression net-exponent 2', ([['USD', '313.17', 'GBP', '4250'], ['USD', '4617', 'JPY', '3628']],),
[['GBP', '4250.00'], ['JPY', '3628'], ['USD', '-4930.17']]),
('partial repair guard 1',
([['GBP', '3755.04', 'GBP', '2258.67'], ['JPY', '4', 'GBP', '4532.21'], ['USD', '3940', 'EUR', '3321.70'],
['KWD', '2315', 'JPY', '2875']],),
[['EUR', '3321.70'], ['GBP', '3035.84'], ['JPY', '2871'], ['KWD', '-2315.000'], ['USD', '-3940.00']]),
('partial repair guard 2',
([['USD', '3559.19', 'EUR', '1234.78'], ['USD', '3870', 'KWD', '4202'], ['USD', '3791.99', 'KWD', '3508.411'],
['USD', '3404.57', 'GBP', '663.83']],),
[['EUR', '1234.78'], ['GBP', '663.83'], ['KWD', '7710.411'], ['USD', '-14625.75']]),
('control: chained trades', ([['USD', '108.35', 'EUR', '100.00'], ['EUR', '100.00', 'JPY', '16200']],),
[['JPY', '16200'], ['USD', '-108.35']]),
('control: short amounts', ([['USD', '5', 'GBP', '4']],), [['GBP', '4.00'], ['USD', '-5.00']]),
('control: fully offset', ([['USD', '10.00', 'EUR', '9.20'], ['EUR', '9.20', 'USD', '10.00']],), []),
('control: same currency swap', ([['KWD', '1.250', 'KWD', '1.000']],), [['KWD', '-0.250']])],
[('regression net-exponent 1',
([['JPY', '1210', 'GBP', '400.13'], ['JPY', '1882', 'EUR', '1387'], ['JPY', '133', 'KWD', '4882'],
['GBP', '400.13', 'JPY', '1210']],),
[['EUR', '1387.00'], ['JPY', '-2015'], ['KWD', '4882.000']]),
('regression net-exponent 2',
([['EUR', '2398.23', 'JPY', '1126'], ['JPY', '3068', 'JPY', '622'], ['KWD', '86.693', 'GBP', '3555'],
['KWD', '3551', 'JPY', '3728']],),
[['EUR', '-2398.23'], ['GBP', '3555.00'], ['JPY', '2408'], ['KWD', '-3637.693']]),
('partial repair guard 1',
([['EUR', '4780', 'GBP', '4817.42'], ['EUR', '937.30', 'JPY', '1728'], ['GBP', '394', 'USD', '949']],),
[['EUR', '-5717.30'], ['GBP', '4423.42'], ['JPY', '1728'], ['USD', '949.00']]),
('partial repair guard 2',
([['GBP', '2181', 'KWD', '1051.460'], ['JPY', '550', 'EUR', '3789'], ['USD', '506.38', 'JPY', '1697'],
['KWD', '1052.629', 'EUR', '763.75']],),
[['EUR', '4552.75'], ['GBP', '-2181.00'], ['JPY', '1147'], ['KWD', '-1.169'], ['USD', '-506.38']]),
('control: same currency swap', ([['KWD', '1.250', 'KWD', '1.000']],), [['KWD', '-0.250']]),
('control: empty', ([],), []),
('control: unsorted codes',
([['USD', '1.00', 'EUR', '0.92'], ['GBP', '0.79', 'USD', '1.00'], ['KWD', '0.307', 'CHF', '0.88']],),
[['CHF', '0.88'], ['EUR', '0.92'], ['GBP', '-0.79'], ['KWD', '-0.307']]),
('control: chained trades', ([['USD', '108.35', 'EUR', '100.00'], ['EUR', '100.00', 'JPY', '16200']],),
[['JPY', '16200'], ['USD', '-108.35']])],
[('regression net-exponent 1',
([['GBP', '3480.24', 'KWD', '2947.345'], ['GBP', '1426.56', 'USD', '1564'], ['KWD', '4552.575', 'GBP', '4813.80'],
['EUR', '2477.75', 'GBP', '2397.09']],),
[['EUR', '-2477.75'], ['GBP', '2304.09'], ['KWD', '-1605.230'], ['USD', '1564.00']]),
('regression net-exponent 2',
([['USD', '1923', 'GBP', '3301'], ['JPY', '4033', 'JPY', '2447'], ['USD', '819.80', 'EUR', '4094.27'],
['USD', '2815.32', 'JPY', '479']],),
[['EUR', '4094.27'], ['GBP', '3301.00'], ['JPY', '-1107'], ['USD', '-5558.12']]),
('partial repair guard 1',
([['EUR', '4958.34', 'JPY', '456'], ['KWD', '149.894', 'EUR', '4865.00'], ['GBP', '4322.22', 'GBP', '4150.09'],
['USD', '4134', 'GBP', '151.91'], ['JPY', '456', 'EUR', '4958.34']],),
[['EUR', '4865.00'], ['GBP', '-20.22'], ['KWD', '-149.894'], ['USD', '-4134.00']]),
('partial repair guard 2', ([['USD', '313.17', 'GBP', '4250'], ['USD', '4617', 'JPY', '3628']],),
[['GBP', '4250.00'], ['JPY', '3628'], ['USD', '-4930.17']]),
('control: chained trades', ([['USD', '108.35', 'EUR', '100.00'], ['EUR', '100.00', 'JPY', '16200']],),
[['JPY', '16200'], ['USD', '-108.35']]),
('control: short amounts', ([['USD', '5', 'GBP', '4']],), [['GBP', '4.00'], ['USD', '-5.00']]),
('control: fully offset', ([['USD', '10.00', 'EUR', '9.20'], ['EUR', '9.20', 'USD', '10.00']],), []),
('control: same currency swap', ([['KWD', '1.250', 'KWD', '1.000']],), [['KWD', '-0.250']])]]
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 net-exponent 1 | [['GBP', '4'], ['USD', '-5']] | [['GBP', '4.00'], ['USD', '-5.00']] | Failed |
| regression net-exponent 2 | [['EUR', '3321.70'], ['GBP', '3035.84'], ['JPY', '2871'], ['KWD', '-2315'], ['USD', '-3940']] | [['EUR', '3321.70'], ['GBP', '3035.84'], ['JPY', '2871'], ['KWD', '-2315.000'], ['USD', '-3940.00']] | Failed |
| partial repair guard 1 | [['KWD', '-0.250']] | [['KWD', '-0.250']] | Passed |
| partial repair guard 2 | [['JPY', '16200'], ['USD', '-108.35']] | [['JPY', '16200'], ['USD', '-108.35']] | Passed |
| control: fully offset | [] | [] | Passed |
| control: empty | [] | [] | Passed |
| control: unsorted codes | [['CHF', '0.88'], ['EUR', '0.92'], ['GBP', '-0.79'], ['KWD', '-0.307']] | [['CHF', '0.88'], ['EUR', '0.92'], ['GBP', '-0.79'], ['KWD', '-0.307']] | Passed |
SHA-256 / 7e27d28ff53d47e607085fbfb6ba4d024400ab774cf969beaa1517eb07fae48a
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(trades):
exps = {'JPY': 0, 'KWD': 3}
net = {}
for pay_c, pay_a, rec_c, rec_a in trades:
net[pay_c] = net.get(pay_c, Decimal(0)) - Decimal(pay_a)
net[rec_c] = net.get(rec_c, Decimal(0)) + Decimal(rec_a)
out = []
for c in sorted(net):
v = net[c]
if v == 0: continue
out.append([c, format(v.quantize(Decimal('0.01')), 'f')])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression net-exponent 1', ([['USD', '5', 'GBP', '4']],), [['GBP', '4.00'], ['USD', '-5.00']]),
('regression net-exponent 2',
([['GBP', '3755.04', 'GBP', '2258.67'], ['JPY', '4', 'GBP', '4532.21'], ['USD', '3940', 'EUR', '3321.70'],
['KWD', '2315', 'JPY', '2875']],),
[['EUR', '3321.70'], ['GBP', '3035.84'], ['JPY', '2871'], ['KWD', '-2315.000'], ['USD', '-3940.00']]),
('partial repair guard 1', ([['KWD', '1.250', 'KWD', '1.000']],), [['KWD', '-0.250']]),
('partial repair guard 2', ([['USD', '108.35', 'EUR', '100.00'], ['EUR', '100.00', 'JPY', '16200']],),
[['JPY', '16200'], ['USD', '-108.35']]),
('control: fully offset', ([['USD', '10.00', 'EUR', '9.20'], ['EUR', '9.20', 'USD', '10.00']],), []),
('control: empty', ([],), []),
('control: unsorted codes',
([['USD', '1.00', 'EUR', '0.92'], ['GBP', '0.79', 'USD', '1.00'], ['KWD', '0.307', 'CHF', '0.88']],),
[['CHF', '0.88'], ['EUR', '0.92'], ['GBP', '-0.79'], ['KWD', '-0.307']])],
[('regression net-exponent 1',
([['EUR', '4780', 'GBP', '4817.42'], ['EUR', '937.30', 'JPY', '1728'], ['GBP', '394', 'USD', '949']],),
[['EUR', '-5717.30'], ['GBP', '4423.42'], ['JPY', '1728'], ['USD', '949.00']]),
('regression net-exponent 2',
([['GBP', '2181', 'KWD', '1051.460'], ['JPY', '550', 'EUR', '3789'], ['USD', '506.38', 'JPY', '1697'],
['KWD', '1052.629', 'EUR', '763.75']],),
[['EUR', '4552.75'], ['GBP', '-2181.00'], ['JPY', '1147'], ['KWD', '-1.169'], ['USD', '-506.38']]),
('partial repair guard 1',
([['USD', '1.00', 'EUR', '0.92'], ['GBP', '0.79', 'USD', '1.00'], ['KWD', '0.307', 'CHF', '0.88']],),
[['CHF', '0.88'], ['EUR', '0.92'], ['GBP', '-0.79'], ['KWD', '-0.307']]),
('partial repair guard 2',
([['JPY', '1806', 'KWD', '4720.108'], ['USD', '3724.50', 'JPY', '222'], ['KWD', '4720.108', 'JPY', '1806']],),
[['JPY', '222'], ['USD', '-3724.50']]),
('control: same currency swap', ([['KWD', '1.250', 'KWD', '1.000']],), [['KWD', '-0.250']]),
('control: empty', ([],), []),
('control: chained trades', ([['USD', '108.35', 'EUR', '100.00'], ['EUR', '100.00', 'JPY', '16200']],),
[['JPY', '16200'], ['USD', '-108.35']]),
('control: short amounts', ([['USD', '5', 'GBP', '4']],), [['GBP', '4.00'], ['USD', '-5.00']])],
[('regression net-exponent 1',
([['EUR', '4958.34', 'JPY', '456'], ['KWD', '149.894', 'EUR', '4865.00'], ['GBP', '4322.22', 'GBP', '4150.09'],
['USD', '4134', 'GBP', '151.91'], ['JPY', '456', 'EUR', '4958.34']],),
[['EUR', '4865.00'], ['GBP', '-20.22'], ['KWD', '-149.894'], ['USD', '-4134.00']]),
('regression net-exponent 2', ([['USD', '313.17', 'GBP', '4250'], ['USD', '4617', 'JPY', '3628']],),
[['GBP', '4250.00'], ['JPY', '3628'], ['USD', '-4930.17']]),
('partial repair guard 1',
([['GBP', '3755.04', 'GBP', '2258.67'], ['JPY', '4', 'GBP', '4532.21'], ['USD', '3940', 'EUR', '3321.70'],
['KWD', '2315', 'JPY', '2875']],),
[['EUR', '3321.70'], ['GBP', '3035.84'], ['JPY', '2871'], ['KWD', '-2315.000'], ['USD', '-3940.00']]),
('partial repair guard 2',
([['USD', '3559.19', 'EUR', '1234.78'], ['USD', '3870', 'KWD', '4202'], ['USD', '3791.99', 'KWD', '3508.411'],
['USD', '3404.57', 'GBP', '663.83']],),
[['EUR', '1234.78'], ['GBP', '663.83'], ['KWD', '7710.411'], ['USD', '-14625.75']]),
('control: chained trades', ([['USD', '108.35', 'EUR', '100.00'], ['EUR', '100.00', 'JPY', '16200']],),
[['JPY', '16200'], ['USD', '-108.35']]),
('control: short amounts', ([['USD', '5', 'GBP', '4']],), [['GBP', '4.00'], ['USD', '-5.00']]),
('control: fully offset', ([['USD', '10.00', 'EUR', '9.20'], ['EUR', '9.20', 'USD', '10.00']],), []),
('control: same currency swap', ([['KWD', '1.250', 'KWD', '1.000']],), [['KWD', '-0.250']])],
[('regression net-exponent 1',
([['JPY', '1210', 'GBP', '400.13'], ['JPY', '1882', 'EUR', '1387'], ['JPY', '133', 'KWD', '4882'],
['GBP', '400.13', 'JPY', '1210']],),
[['EUR', '1387.00'], ['JPY', '-2015'], ['KWD', '4882.000']]),
('regression net-exponent 2',
([['EUR', '2398.23', 'JPY', '1126'], ['JPY', '3068', 'JPY', '622'], ['KWD', '86.693', 'GBP', '3555'],
['KWD', '3551', 'JPY', '3728']],),
[['EUR', '-2398.23'], ['GBP', '3555.00'], ['JPY', '2408'], ['KWD', '-3637.693']]),
('partial repair guard 1',
([['EUR', '4780', 'GBP', '4817.42'], ['EUR', '937.30', 'JPY', '1728'], ['GBP', '394', 'USD', '949']],),
[['EUR', '-5717.30'], ['GBP', '4423.42'], ['JPY', '1728'], ['USD', '949.00']]),
('partial repair guard 2',
([['GBP', '2181', 'KWD', '1051.460'], ['JPY', '550', 'EUR', '3789'], ['USD', '506.38', 'JPY', '1697'],
['KWD', '1052.629', 'EUR', '763.75']],),
[['EUR', '4552.75'], ['GBP', '-2181.00'], ['JPY', '1147'], ['KWD', '-1.169'], ['USD', '-506.38']]),
('control: same currency swap', ([['KWD', '1.250', 'KWD', '1.000']],), [['KWD', '-0.250']]),
('control: empty', ([],), []),
('control: unsorted codes',
([['USD', '1.00', 'EUR', '0.92'], ['GBP', '0.79', 'USD', '1.00'], ['KWD', '0.307', 'CHF', '0.88']],),
[['CHF', '0.88'], ['EUR', '0.92'], ['GBP', '-0.79'], ['KWD', '-0.307']]),
('control: chained trades', ([['USD', '108.35', 'EUR', '100.00'], ['EUR', '100.00', 'JPY', '16200']],),
[['JPY', '16200'], ['USD', '-108.35']])],
[('regression net-exponent 1',
([['GBP', '3480.24', 'KWD', '2947.345'], ['GBP', '1426.56', 'USD', '1564'], ['KWD', '4552.575', 'GBP', '4813.80'],
['EUR', '2477.75', 'GBP', '2397.09']],),
[['EUR', '-2477.75'], ['GBP', '2304.09'], ['KWD', '-1605.230'], ['USD', '1564.00']]),
('regression net-exponent 2',
([['USD', '1923', 'GBP', '3301'], ['JPY', '4033', 'JPY', '2447'], ['USD', '819.80', 'EUR', '4094.27'],
['USD', '2815.32', 'JPY', '479']],),
[['EUR', '4094.27'], ['GBP', '3301.00'], ['JPY', '-1107'], ['USD', '-5558.12']]),
('partial repair guard 1',
([['EUR', '4958.34', 'JPY', '456'], ['KWD', '149.894', 'EUR', '4865.00'], ['GBP', '4322.22', 'GBP', '4150.09'],
['USD', '4134', 'GBP', '151.91'], ['JPY', '456', 'EUR', '4958.34']],),
[['EUR', '4865.00'], ['GBP', '-20.22'], ['KWD', '-149.894'], ['USD', '-4134.00']]),
('partial repair guard 2', ([['USD', '313.17', 'GBP', '4250'], ['USD', '4617', 'JPY', '3628']],),
[['GBP', '4250.00'], ['JPY', '3628'], ['USD', '-4930.17']]),
('control: chained trades', ([['USD', '108.35', 'EUR', '100.00'], ['EUR', '100.00', 'JPY', '16200']],),
[['JPY', '16200'], ['USD', '-108.35']]),
('control: short amounts', ([['USD', '5', 'GBP', '4']],), [['GBP', '4.00'], ['USD', '-5.00']]),
('control: fully offset', ([['USD', '10.00', 'EUR', '9.20'], ['EUR', '9.20', 'USD', '10.00']],), []),
('control: same currency swap', ([['KWD', '1.250', 'KWD', '1.000']],), [['KWD', '-0.250']])]]
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 net-exponent 1 | [['GBP', '4.00'], ['USD', '-5.00']] | [['GBP', '4.00'], ['USD', '-5.00']] | Passed |
| regression net-exponent 2 | [['EUR', '3321.70'], ['GBP', '3035.84'], ['JPY', '2871.00'], ['KWD', '-2315.00'], ['USD', '-3940.00']] | [['EUR', '3321.70'], ['GBP', '3035.84'], ['JPY', '2871'], ['KWD', '-2315.000'], ['USD', '-3940.00']] | Failed |
| partial repair guard 1 | [['KWD', '-0.25']] | [['KWD', '-0.250']] | Failed |
| partial repair guard 2 | [['JPY', '16200.00'], ['USD', '-108.35']] | [['JPY', '16200'], ['USD', '-108.35']] | Failed |
| control: fully offset | [] | [] | Passed |
| control: empty | [] | [] | Passed |
| control: unsorted codes | [['CHF', '0.88'], ['EUR', '0.92'], ['GBP', '-0.79'], ['KWD', '-0.31']] | [['CHF', '0.88'], ['EUR', '0.92'], ['GBP', '-0.79'], ['KWD', '-0.307']] | Failed |
SHA-256 / 025facf7059ef4e383c9148fd99298a07fe9751bad07e5a320432fa8752b25a2
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(trades):
exps = {'JPY': 0, 'KWD': 3}
net = {}
for pay_c, pay_a, rec_c, rec_a in trades:
net[pay_c] = net.get(pay_c, Decimal(0)) - Decimal(pay_a)
net[rec_c] = net.get(rec_c, Decimal(0)) + Decimal(rec_a)
out = []
for c in sorted(net):
v = net[c]
if v == 0: continue
out.append([c, format(v.quantize(Decimal(1).scaleb(-exps.get(c, 2))), 'f')])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression net-exponent 1', ([['USD', '5', 'GBP', '4']],), [['GBP', '4.00'], ['USD', '-5.00']]),
('regression net-exponent 2',
([['GBP', '3755.04', 'GBP', '2258.67'], ['JPY', '4', 'GBP', '4532.21'], ['USD', '3940', 'EUR', '3321.70'],
['KWD', '2315', 'JPY', '2875']],),
[['EUR', '3321.70'], ['GBP', '3035.84'], ['JPY', '2871'], ['KWD', '-2315.000'], ['USD', '-3940.00']]),
('partial repair guard 1', ([['KWD', '1.250', 'KWD', '1.000']],), [['KWD', '-0.250']]),
('partial repair guard 2', ([['USD', '108.35', 'EUR', '100.00'], ['EUR', '100.00', 'JPY', '16200']],),
[['JPY', '16200'], ['USD', '-108.35']]),
('control: fully offset', ([['USD', '10.00', 'EUR', '9.20'], ['EUR', '9.20', 'USD', '10.00']],), []),
('control: empty', ([],), []),
('control: unsorted codes',
([['USD', '1.00', 'EUR', '0.92'], ['GBP', '0.79', 'USD', '1.00'], ['KWD', '0.307', 'CHF', '0.88']],),
[['CHF', '0.88'], ['EUR', '0.92'], ['GBP', '-0.79'], ['KWD', '-0.307']])],
[('regression net-exponent 1',
([['EUR', '4780', 'GBP', '4817.42'], ['EUR', '937.30', 'JPY', '1728'], ['GBP', '394', 'USD', '949']],),
[['EUR', '-5717.30'], ['GBP', '4423.42'], ['JPY', '1728'], ['USD', '949.00']]),
('regression net-exponent 2',
([['GBP', '2181', 'KWD', '1051.460'], ['JPY', '550', 'EUR', '3789'], ['USD', '506.38', 'JPY', '1697'],
['KWD', '1052.629', 'EUR', '763.75']],),
[['EUR', '4552.75'], ['GBP', '-2181.00'], ['JPY', '1147'], ['KWD', '-1.169'], ['USD', '-506.38']]),
('partial repair guard 1',
([['USD', '1.00', 'EUR', '0.92'], ['GBP', '0.79', 'USD', '1.00'], ['KWD', '0.307', 'CHF', '0.88']],),
[['CHF', '0.88'], ['EUR', '0.92'], ['GBP', '-0.79'], ['KWD', '-0.307']]),
('partial repair guard 2',
([['JPY', '1806', 'KWD', '4720.108'], ['USD', '3724.50', 'JPY', '222'], ['KWD', '4720.108', 'JPY', '1806']],),
[['JPY', '222'], ['USD', '-3724.50']]),
('control: same currency swap', ([['KWD', '1.250', 'KWD', '1.000']],), [['KWD', '-0.250']]),
('control: empty', ([],), []),
('control: chained trades', ([['USD', '108.35', 'EUR', '100.00'], ['EUR', '100.00', 'JPY', '16200']],),
[['JPY', '16200'], ['USD', '-108.35']]),
('control: short amounts', ([['USD', '5', 'GBP', '4']],), [['GBP', '4.00'], ['USD', '-5.00']])],
[('regression net-exponent 1',
([['EUR', '4958.34', 'JPY', '456'], ['KWD', '149.894', 'EUR', '4865.00'], ['GBP', '4322.22', 'GBP', '4150.09'],
['USD', '4134', 'GBP', '151.91'], ['JPY', '456', 'EUR', '4958.34']],),
[['EUR', '4865.00'], ['GBP', '-20.22'], ['KWD', '-149.894'], ['USD', '-4134.00']]),
('regression net-exponent 2', ([['USD', '313.17', 'GBP', '4250'], ['USD', '4617', 'JPY', '3628']],),
[['GBP', '4250.00'], ['JPY', '3628'], ['USD', '-4930.17']]),
('partial repair guard 1',
([['GBP', '3755.04', 'GBP', '2258.67'], ['JPY', '4', 'GBP', '4532.21'], ['USD', '3940', 'EUR', '3321.70'],
['KWD', '2315', 'JPY', '2875']],),
[['EUR', '3321.70'], ['GBP', '3035.84'], ['JPY', '2871'], ['KWD', '-2315.000'], ['USD', '-3940.00']]),
('partial repair guard 2',
([['USD', '3559.19', 'EUR', '1234.78'], ['USD', '3870', 'KWD', '4202'], ['USD', '3791.99', 'KWD', '3508.411'],
['USD', '3404.57', 'GBP', '663.83']],),
[['EUR', '1234.78'], ['GBP', '663.83'], ['KWD', '7710.411'], ['USD', '-14625.75']]),
('control: chained trades', ([['USD', '108.35', 'EUR', '100.00'], ['EUR', '100.00', 'JPY', '16200']],),
[['JPY', '16200'], ['USD', '-108.35']]),
('control: short amounts', ([['USD', '5', 'GBP', '4']],), [['GBP', '4.00'], ['USD', '-5.00']]),
('control: fully offset', ([['USD', '10.00', 'EUR', '9.20'], ['EUR', '9.20', 'USD', '10.00']],), []),
('control: same currency swap', ([['KWD', '1.250', 'KWD', '1.000']],), [['KWD', '-0.250']])],
[('regression net-exponent 1',
([['JPY', '1210', 'GBP', '400.13'], ['JPY', '1882', 'EUR', '1387'], ['JPY', '133', 'KWD', '4882'],
['GBP', '400.13', 'JPY', '1210']],),
[['EUR', '1387.00'], ['JPY', '-2015'], ['KWD', '4882.000']]),
('regression net-exponent 2',
([['EUR', '2398.23', 'JPY', '1126'], ['JPY', '3068', 'JPY', '622'], ['KWD', '86.693', 'GBP', '3555'],
['KWD', '3551', 'JPY', '3728']],),
[['EUR', '-2398.23'], ['GBP', '3555.00'], ['JPY', '2408'], ['KWD', '-3637.693']]),
('partial repair guard 1',
([['EUR', '4780', 'GBP', '4817.42'], ['EUR', '937.30', 'JPY', '1728'], ['GBP', '394', 'USD', '949']],),
[['EUR', '-5717.30'], ['GBP', '4423.42'], ['JPY', '1728'], ['USD', '949.00']]),
('partial repair guard 2',
([['GBP', '2181', 'KWD', '1051.460'], ['JPY', '550', 'EUR', '3789'], ['USD', '506.38', 'JPY', '1697'],
['KWD', '1052.629', 'EUR', '763.75']],),
[['EUR', '4552.75'], ['GBP', '-2181.00'], ['JPY', '1147'], ['KWD', '-1.169'], ['USD', '-506.38']]),
('control: same currency swap', ([['KWD', '1.250', 'KWD', '1.000']],), [['KWD', '-0.250']]),
('control: empty', ([],), []),
('control: unsorted codes',
([['USD', '1.00', 'EUR', '0.92'], ['GBP', '0.79', 'USD', '1.00'], ['KWD', '0.307', 'CHF', '0.88']],),
[['CHF', '0.88'], ['EUR', '0.92'], ['GBP', '-0.79'], ['KWD', '-0.307']]),
('control: chained trades', ([['USD', '108.35', 'EUR', '100.00'], ['EUR', '100.00', 'JPY', '16200']],),
[['JPY', '16200'], ['USD', '-108.35']])],
[('regression net-exponent 1',
([['GBP', '3480.24', 'KWD', '2947.345'], ['GBP', '1426.56', 'USD', '1564'], ['KWD', '4552.575', 'GBP', '4813.80'],
['EUR', '2477.75', 'GBP', '2397.09']],),
[['EUR', '-2477.75'], ['GBP', '2304.09'], ['KWD', '-1605.230'], ['USD', '1564.00']]),
('regression net-exponent 2',
([['USD', '1923', 'GBP', '3301'], ['JPY', '4033', 'JPY', '2447'], ['USD', '819.80', 'EUR', '4094.27'],
['USD', '2815.32', 'JPY', '479']],),
[['EUR', '4094.27'], ['GBP', '3301.00'], ['JPY', '-1107'], ['USD', '-5558.12']]),
('partial repair guard 1',
([['EUR', '4958.34', 'JPY', '456'], ['KWD', '149.894', 'EUR', '4865.00'], ['GBP', '4322.22', 'GBP', '4150.09'],
['USD', '4134', 'GBP', '151.91'], ['JPY', '456', 'EUR', '4958.34']],),
[['EUR', '4865.00'], ['GBP', '-20.22'], ['KWD', '-149.894'], ['USD', '-4134.00']]),
('partial repair guard 2', ([['USD', '313.17', 'GBP', '4250'], ['USD', '4617', 'JPY', '3628']],),
[['GBP', '4250.00'], ['JPY', '3628'], ['USD', '-4930.17']]),
('control: chained trades', ([['USD', '108.35', 'EUR', '100.00'], ['EUR', '100.00', 'JPY', '16200']],),
[['JPY', '16200'], ['USD', '-108.35']]),
('control: short amounts', ([['USD', '5', 'GBP', '4']],), [['GBP', '4.00'], ['USD', '-5.00']]),
('control: fully offset', ([['USD', '10.00', 'EUR', '9.20'], ['EUR', '9.20', 'USD', '10.00']],), []),
('control: same currency swap', ([['KWD', '1.250', 'KWD', '1.000']],), [['KWD', '-0.250']])]]
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 net-exponent 1 | [['GBP', '4.00'], ['USD', '-5.00']] | [['GBP', '4.00'], ['USD', '-5.00']] | Passed |
| regression net-exponent 2 | [['EUR', '3321.70'], ['GBP', '3035.84'], ['JPY', '2871'], ['KWD', '-2315.000'], ['USD', '-3940.00']] | [['EUR', '3321.70'], ['GBP', '3035.84'], ['JPY', '2871'], ['KWD', '-2315.000'], ['USD', '-3940.00']] | Passed |
| partial repair guard 1 | [['KWD', '-0.250']] | [['KWD', '-0.250']] | Passed |
| partial repair guard 2 | [['JPY', '16200'], ['USD', '-108.35']] | [['JPY', '16200'], ['USD', '-108.35']] | Passed |
| control: fully offset | [] | [] | Passed |
| control: empty | [] | [] | Passed |
| control: unsorted codes | [['CHF', '0.88'], ['EUR', '0.92'], ['GBP', '-0.79'], ['KWD', '-0.307']] | [['CHF', '0.88'], ['EUR', '0.92'], ['GBP', '-0.79'], ['KWD', '-0.307']] | Passed |
SHA-256 / 217260206e6a62b2aa2aa7cc045ac6158e7ba8f34c575af68f60395f04fcf952
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:47:01.462110+00:00.
Case digest / 6f2edb95bbb155de3c9311bd8c6e7282fe5845307bfc97a9a25a893a8cafc053