{"abstract":"A higher-yielding quote currency produces forward discount points instead of premium points.","category":"Currency rounding and FX conversion","checks":6,"contract":"solve(pair, spot, base_pct, quote_pct, days): covered-interest-parity outright F = S*(1 + rq*days/Bq)/(1 + rb*days/Bb) with money-market bases GBP, AUD, CAD 365 and USD, EUR, JPY, CHF 360; rates are given in percent. The pip exponent is 2 for JPY-quoted pairs, else 4. Return [F rounded half-even to pip exponent + 1 decimals, forward points = (F - S)*10**pip_exp rounded half-even to 2 decimals] as strings, both computed from the exact F.","contract_signature":"pair, spot, base_pct, quote_pct, days","evaluation_group":"w2-currency_rounding_and_fx_conversion-interest-parity-forward","failed_approach":"A linear rate-difference approximation has the right sign but the wrong magnitude.","family":"w2-currency_rounding_and_fx_conversion-interest-parity-forward-parity-orientation","id":"FA-62326","implementations":{"attempt":{"sha256":"0b7ae53958d3d0565190d3efec90f395ce391495bba6986c55f65e57cc2a258a","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(pair, spot, base_pct, quote_pct, days):\n    basis = {'USD': 360, 'EUR': 360, 'JPY': 360, 'CHF': 360, 'GBP': 365, 'AUD': 365, 'CAD': 365}\n    base, quote = pair[:3], pair[3:]\n    S = Decimal(spot)\n    rb, rq = Decimal(base_pct) / 100, Decimal(quote_pct) / 100\n    F = S * (1 + (rq - rb) * days / basis[quote])\n    pe = 2 if quote == 'JPY' else 4\n    pts = ((F - S) * Decimal(10) ** pe).quantize(Decimal('0.01'), rounding=ROUND_HALF_EVEN)\n    return [format(F.quantize(Decimal(1).scaleb(-(pe + 1)), rounding=ROUND_HALF_EVEN), 'f'), format(pts, 'f')]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[('regression parity-orientation 1', ('EURUSD', '1.0800', '3.60', '5.40', 360), ['1.09876', '187.64']),\n  ('regression parity-orientation 2', ('USDJPY', '150.00', '5.00', '0.00', 180), ['146.341', '-365.85']),\n  ('control: sterling dollar', ('GBPUSD', '1.2650', '5.25', '5.30', 91), ['1.26538', '3.85']),\n  ('control: aussie yen', ('AUDJPY', '98.765', '4.35', '0.10', 30), ['98.421', '-34.37']),\n  ('control: dollar cad', ('USDCAD', '1.3577', '5.30', '4.75', 182), ['1.35359', '-41.12']),\n  ('control: euro franc', ('EURCHF', '0.9512', '3.75', '1.50', 7), ['0.95078', '-4.16'])],\n [('regression parity-orientation 1', ('GBPUSD', '1.2650', '5.25', '5.30', 91), ['1.26538', '3.85']),\n  ('regression parity-orientation 2', ('AUDJPY', '98.765', '4.35', '0.10', 30), ['98.421', '-34.37']),\n  ('control: dollar cad', ('USDCAD', '1.3577', '5.30', '4.75', 182), ['1.35359', '-41.12']),\n  ('control: euro franc', ('EURCHF', '0.9512', '3.75', '1.50', 7), ['0.95078', '-4.16']),\n  ('control: euro dollar year', ('EURUSD', '1.0800', '3.60', '5.40', 360), ['1.09876', '187.64']),\n  ('control: dollar yen half year', ('USDJPY', '150.00', '5.00', '0.00', 180), ['146.341', '-365.85'])],\n [('regression parity-orientation 1', ('USDCAD', '1.3577', '5.30', '4.75', 182), ['1.35359', '-41.12']),\n  ('regression parity-orientation 2', ('EURCHF', '0.9512', '3.75', '1.50', 7), ['0.95078', '-4.16']),\n  ('partial repair guard 2', ('USDCAD', '128.6366', '0.30', '6.36', 365), ['136.40300', '77663.95']),\n  ('control: euro dollar year', ('EURUSD', '1.0800', '3.60', '5.40', 360), ['1.09876', '187.64']),\n  ('control: dollar yen half year', ('USDJPY', '150.00', '5.00', '0.00', 180), ['146.341', '-365.85']),\n  ('control: sterling dollar', ('GBPUSD', '1.2650', '5.25', '5.30', 91), ['1.26538', '3.85']),\n  ('control: aussie yen', ('AUDJPY', '98.765', '4.35', '0.10', 30), ['98.421', '-34.37'])],\n [('regression parity-orientation 1', ('USDCAD', '128.6366', '0.30', '6.36', 365), ['136.40300', '77663.95']),\n  ('regression parity-orientation 2', ('AUDJPY', '54.4548', '0.49', '4.06', 91), ['54.947', '49.17']),\n  ('partial repair guard 2', ('GBPUSD', '17.5535', '4.72', '0.07', 182), ['17.15594', '-3975.59']),\n  ('control: aussie yen', ('AUDJPY', '98.765', '4.35', '0.10', 30), ['98.421', '-34.37']),\n  ('control: dollar cad', ('USDCAD', '1.3577', '5.30', '4.75', 182), ['1.35359', '-41.12']),\n  ('control: euro franc', ('EURCHF', '0.9512', '3.75', '1.50', 7), ['0.95078', '-4.16']),\n  ('control: euro dollar year', ('EURUSD', '1.0800', '3.60', '5.40', 360), ['1.09876', '187.64'])],\n [('regression parity-orientation 1', ('GBPUSD', '17.5535', '4.72', '0.07', 182), ['17.15594', '-3975.59']),\n  ('regression parity-orientation 2', ('AUDJPY', '5.9212', '0.74', '1.63', 182), ['5.948', '2.68']),\n  ('partial repair guard 2', ('GBPJPY', '137.7426', '3.56', '5.48', 1), ['137.750', '0.75']),\n  ('control: euro dollar year', ('EURUSD', '1.0800', '3.60', '5.40', 360), ['1.09876', '187.64']),\n  ('control: dollar yen half year', ('USDJPY', '150.00', '5.00', '0.00', 180), ['146.341', '-365.85']),\n  ('control: sterling dollar', ('GBPUSD', '1.2650', '5.25', '5.30', 91), ['1.26538', '3.85']),\n  ('control: aussie yen', ('AUDJPY', '98.765', '4.35', '0.10', 30), ['98.421', '-34.37'])]]\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":"0f0bfa156914435cbe8b1da6fdb8c0e4a74744de78fc02b08476238333b34c9e","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(pair, spot, base_pct, quote_pct, days):\n    basis = {'USD': 360, 'EUR': 360, 'JPY': 360, 'CHF': 360, 'GBP': 365, 'AUD': 365, 'CAD': 365}\n    base, quote = pair[:3], pair[3:]\n    S = Decimal(spot)\n    rb, rq = Decimal(base_pct) / 100, Decimal(quote_pct) / 100\n    F = S * (1 + rb * days / basis[base]) / (1 + rq * days / basis[quote])\n    pe = 2 if quote == 'JPY' else 4\n    pts = ((F - S) * Decimal(10) ** pe).quantize(Decimal('0.01'), rounding=ROUND_HALF_EVEN)\n    return [format(F.quantize(Decimal(1).scaleb(-(pe + 1)), rounding=ROUND_HALF_EVEN), 'f'), format(pts, 'f')]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\ncases = [[('regression parity-orientation 1', ('EURUSD', '1.0800', '3.60', '5.40', 360), ['1.09876', '187.64']),\n  ('regression parity-orientation 2', ('USDJPY', '150.00', '5.00', '0.00', 180), ['146.341', '-365.85']),\n  ('control: sterling dollar', ('GBPUSD', '1.2650', '5.25', '5.30', 91), ['1.26538', '3.85']),\n  ('control: aussie yen', ('AUDJPY', '98.765', '4.35', '0.10', 30), ['98.421', '-34.37']),\n  ('control: dollar cad', ('USDCAD', '1.3577', '5.30', '4.75', 182), ['1.35359', '-41.12']),\n  ('control: euro franc', ('EURCHF', '0.9512', '3.75', '1.50', 7), ['0.95078', '-4.16'])],\n [('regression parity-orientation 1', ('GBPUSD', '1.2650', '5.25', '5.30', 91), ['1.26538', '3.85']),\n  ('regression parity-orientation 2', ('AUDJPY', '98.765', '4.35', '0.10', 30), ['98.421', '-34.37']),\n  ('control: dollar cad', ('USDCAD', '1.3577', '5.30', '4.75', 182), ['1.35359', '-41.12']),\n  ('control: euro franc', ('EURCHF', '0.9512', '3.75', '1.50', 7), ['0.95078', '-4.16']),\n  ('control: euro dollar year', ('EURUSD', '1.0800', '3.60', '5.40', 360), ['1.09876', '187.64']),\n  ('control: dollar yen half year', ('USDJPY', '150.00', '5.00', '0.00', 180), ['146.341', '-365.85'])],\n [('regression parity-orientation 1', ('USDCAD', '1.3577', '5.30', '4.75', 182), ['1.35359', '-41.12']),\n  ('regression parity-orientation 2', ('EURCHF', '0.9512', '3.75', '1.50', 7), ['0.95078', '-4.16']),\n  ('partial repair guard 2', ('USDCAD', '128.6366', '0.30', '6.36', 365), ['136.40300', '77663.95']),\n  ('control: euro dollar year', ('EURUSD', '1.0800', '3.60', '5.40', 360), ['1.09876', '187.64']),\n  ('control: dollar yen half year', ('USDJPY', '150.00', '5.00', '0.00', 180), ['146.341', '-365.85']),\n  ('control: sterling dollar', ('GBPUSD', '1.2650', '5.25', '5.30', 91), ['1.26538', '3.85']),\n  ('control: aussie yen', ('AUDJPY', '98.765', '4.35', '0.10', 30), ['98.421', '-34.37'])],\n [('regression parity-orientation 1', ('USDCAD', '128.6366', '0.30', '6.36', 365), ['136.40300', '77663.95']),\n  ('regression parity-orientation 2', ('AUDJPY', '54.4548', '0.49', '4.06', 91), ['54.947', '49.17']),\n  ('partial repair guard 2', ('GBPUSD', '17.5535', '4.72', '0.07', 182), ['17.15594', '-3975.59']),\n  ('control: aussie yen', ('AUDJPY', '98.765', '4.35', '0.10', 30), ['98.421', '-34.37']),\n  ('control: dollar cad', ('USDCAD', '1.3577', '5.30', '4.75', 182), ['1.35359', '-41.12']),\n  ('control: euro franc', ('EURCHF', '0.9512', '3.75', '1.50', 7), ['0.95078', '-4.16']),\n  ('control: euro dollar year', ('EURUSD', '1.0800', '3.60', '5.40', 360), ['1.09876', '187.64'])],\n [('regression parity-orientation 1', ('GBPUSD', '17.5535', '4.72', '0.07', 182), ['17.15594', '-3975.59']),\n  ('regression parity-orientation 2', ('AUDJPY', '5.9212', '0.74', '1.63', 182), ['5.948', '2.68']),\n  ('partial repair guard 2', ('GBPJPY', '137.7426', '3.56', '5.48', 1), ['137.750', '0.75']),\n  ('control: euro dollar year', ('EURUSD', '1.0800', '3.60', '5.40', 360), ['1.09876', '187.64']),\n  ('control: dollar yen half year', ('USDJPY', '150.00', '5.00', '0.00', 180), ['146.341', '-365.85']),\n  ('control: sterling dollar', ('GBPUSD', '1.2650', '5.25', '5.30', 91), ['1.26538', '3.85']),\n  ('control: aussie yen', ('AUDJPY', '98.765', '4.35', '0.10', 30), ['98.421', '-34.37'])]]\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-interest-parity-forward-parity-orientation","generated_at":"2026-09-29T14:47:03.670041+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.","root_cause":"The numerator uses the base rate and the denominator the quote rate.","sha256":"e5d399d9265292ac51d3909bd41d134d894c1191583cc07937b91a7963e5cb05","title":"The base and quote deposit rates are swapped in the parity formula · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verified":true,"visibility":"public","verification":{"attempt":{"elapsed_ms":42.701,"exit_code":1,"observations":[{"actual":["1.09944","194.40"],"check":"regression parity-orientation 1","expected":["1.09876","187.64"],"passed":false},{"actual":["146.250","-375.00"],"check":"regression parity-orientation 2","expected":["146.341","-365.85"],"passed":false},{"actual":["1.26516","1.60"],"check":"control: sterling dollar","expected":["1.26538","3.85"],"passed":false},{"actual":["98.415","-34.98"],"check":"control: aussie yen","expected":["98.421","-34.37"],"passed":false},{"actual":["1.35398","-37.23"],"check":"control: dollar cad","expected":["1.35359","-41.12"],"passed":false},{"actual":["0.95078","-4.16"],"check":"control: euro franc","expected":["0.95078","-4.16"],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression parity-orientation 1\", \"actual\": [\"1.09944\", \"194.40\"], \"expected\": [\"1.09876\", \"187.64\"], \"passed\": false}, {\"check\": \"regression parity-orientation 2\", \"actual\": [\"146.250\", \"-375.00\"], \"expected\": [\"146.341\", \"-365.85\"], \"passed\": false}, {\"check\": \"control: sterling dollar\", \"actual\": [\"1.26516\", \"1.60\"], \"expected\": [\"1.26538\", \"3.85\"], \"passed\": false}, {\"check\": \"control: aussie yen\", \"actual\": [\"98.415\", \"-34.98\"], \"expected\": [\"98.421\", \"-34.37\"], \"passed\": false}, {\"check\": \"control: dollar cad\", \"actual\": [\"1.35398\", \"-37.23\"], \"expected\": [\"1.35359\", \"-41.12\"], \"passed\": false}, {\"check\": \"control: euro franc\", \"actual\": [\"0.95078\", \"-4.16\"], \"expected\": [\"0.95078\", \"-4.16\"], \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":42.056,"exit_code":1,"observations":[{"actual":["1.06156","-184.44"],"check":"regression parity-orientation 1","expected":["1.09876","187.64"],"passed":false},{"actual":["153.750","375.00"],"check":"regression parity-orientation 2","expected":["146.341","-365.85"],"passed":false},{"actual":["1.26462","-3.85"],"check":"control: sterling dollar","expected":["1.26538","3.85"],"passed":false},{"actual":["99.110","34.49"],"check":"control: aussie yen","expected":["98.421","-34.37"],"passed":false},{"actual":["1.36182","41.24"],"check":"control: dollar cad","expected":["1.35359","-41.12"],"passed":false},{"actual":["0.95162","4.16"],"check":"control: euro franc","expected":["0.95078","-4.16"],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression parity-orientation 1\", \"actual\": [\"1.06156\", \"-184.44\"], \"expected\": [\"1.09876\", \"187.64\"], \"passed\": false}, {\"check\": \"regression parity-orientation 2\", \"actual\": [\"153.750\", \"375.00\"], \"expected\": [\"146.341\", \"-365.85\"], \"passed\": false}, {\"check\": \"control: sterling dollar\", \"actual\": [\"1.26462\", \"-3.85\"], \"expected\": [\"1.26538\", \"3.85\"], \"passed\": false}, {\"check\": \"control: aussie yen\", \"actual\": [\"99.110\", \"34.49\"], \"expected\": [\"98.421\", \"-34.37\"], \"passed\": false}, {\"check\": \"control: dollar cad\", \"actual\": [\"1.36182\", \"41.24\"], \"expected\": [\"1.35359\", \"-41.12\"], \"passed\": false}, {\"check\": \"control: euro franc\", \"actual\": [\"0.95162\", \"4.16\"], \"expected\": [\"0.95078\", \"-4.16\"], \"passed\": false}], \"passed\": false}\n"}},"member_only":{"stages":["fixed"],"fields":["implementations.fixed","verification.fixed","harness","repair"],"note":"The verified repair, its recorded checks, the repair description, and the scoring harness are available to members."}}