{"abstract":"Points disagree in the second decimal with points computed from the exact forward.","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":"Switching the outright rounding to half-up keeps deriving points from a rounded outright and still loses hundredths of a pip.","family":"w2-currency_rounding_and_fx_conversion-interest-parity-forward-points-from-rounded-forward","id":"FA-62331","implementations":{"attempt":{"sha256":"7b0da3a3ba789c5cfdba4f50949e3106fb723bb02e137e157556923146a7c524","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 * days / basis[quote]) / (1 + rb * days / basis[base])\n    pe = 2 if quote == 'JPY' else 4\n    pts = ((F.quantize(Decimal(1).scaleb(-(pe + 1)), rounding=ROUND_HALF_UP) - 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 points-from-rounded-forward 1', ('EURUSD', '1.0800', '3.60', '5.40', 360), ['1.09876', '187.64']),\n  ('regression points-from-rounded-forward 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 points-from-rounded-forward 1', ('GBPUSD', '1.2650', '5.25', '5.30', 91), ['1.26538', '3.85']),\n  ('regression points-from-rounded-forward 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 points-from-rounded-forward 1', ('USDCAD', '1.3577', '5.30', '4.75', 182), ['1.35359', '-41.12']),\n  ('regression points-from-rounded-forward 2', ('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  ('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 points-from-rounded-forward 1', ('USDCAD', '128.6366', '0.30', '6.36', 365), ['136.40300', '77663.95']),\n  ('regression points-from-rounded-forward 2', ('AUDJPY', '54.4548', '0.49', '4.06', 91), ['54.947', '49.17']),\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 points-from-rounded-forward 1', ('GBPUSD', '17.5535', '4.72', '0.07', 182), ['17.15594', '-3975.59']),\n  ('regression points-from-rounded-forward 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":"526dbdf5d07af4016c785ef70532756c561eb91137c94f3fa0be94f11656aac1","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 * days / basis[quote]) / (1 + rb * days / basis[base])\n    pe = 2 if quote == 'JPY' else 4\n    pts = ((F.quantize(Decimal(1).scaleb(-(pe + 1)), rounding=ROUND_HALF_EVEN) - 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 points-from-rounded-forward 1', ('EURUSD', '1.0800', '3.60', '5.40', 360), ['1.09876', '187.64']),\n  ('regression points-from-rounded-forward 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 points-from-rounded-forward 1', ('GBPUSD', '1.2650', '5.25', '5.30', 91), ['1.26538', '3.85']),\n  ('regression points-from-rounded-forward 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 points-from-rounded-forward 1', ('USDCAD', '1.3577', '5.30', '4.75', 182), ['1.35359', '-41.12']),\n  ('regression points-from-rounded-forward 2', ('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  ('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 points-from-rounded-forward 1', ('USDCAD', '128.6366', '0.30', '6.36', 365), ['136.40300', '77663.95']),\n  ('regression points-from-rounded-forward 2', ('AUDJPY', '54.4548', '0.49', '4.06', 91), ['54.947', '49.17']),\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 points-from-rounded-forward 1', ('GBPUSD', '17.5535', '4.72', '0.07', 182), ['17.15594', '-3975.59']),\n  ('regression points-from-rounded-forward 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-points-from-rounded-forward","generated_at":"2026-09-29T14:47:03.674060+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":"Points are computed from F already rounded to pip exponent + 1 decimals.","sha256":"12a0d91dd3e2e169c9485907b2421ee8c439244d5be5b667c8dd8b754ba132d5","title":"Forward points are derived from the rounded outright · 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":44.623,"exit_code":1,"observations":[{"actual":["1.09876","187.60"],"check":"regression points-from-rounded-forward 1","expected":["1.09876","187.64"],"passed":false},{"actual":["146.341","-365.90"],"check":"regression points-from-rounded-forward 2","expected":["146.341","-365.85"],"passed":false},{"actual":["1.26538","3.80"],"check":"control: sterling dollar","expected":["1.26538","3.85"],"passed":false},{"actual":["98.421","-34.40"],"check":"control: aussie yen","expected":["98.421","-34.37"],"passed":false},{"actual":["1.35359","-41.10"],"check":"control: dollar cad","expected":["1.35359","-41.12"],"passed":false},{"actual":["0.95078","-4.20"],"check":"control: euro franc","expected":["0.95078","-4.16"],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression points-from-rounded-forward 1\", \"actual\": [\"1.09876\", \"187.60\"], \"expected\": [\"1.09876\", \"187.64\"], \"passed\": false}, {\"check\": \"regression points-from-rounded-forward 2\", \"actual\": [\"146.341\", \"-365.90\"], \"expected\": [\"146.341\", \"-365.85\"], \"passed\": false}, {\"check\": \"control: sterling dollar\", \"actual\": [\"1.26538\", \"3.80\"], \"expected\": [\"1.26538\", \"3.85\"], \"passed\": false}, {\"check\": \"control: aussie yen\", \"actual\": [\"98.421\", \"-34.40\"], \"expected\": [\"98.421\", \"-34.37\"], \"passed\": false}, {\"check\": \"control: dollar cad\", \"actual\": [\"1.35359\", \"-41.10\"], \"expected\": [\"1.35359\", \"-41.12\"], \"passed\": false}, {\"check\": \"control: euro franc\", \"actual\": [\"0.95078\", \"-4.20\"], \"expected\": [\"0.95078\", \"-4.16\"], \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":41.648,"exit_code":1,"observations":[{"actual":["1.09876","187.60"],"check":"regression points-from-rounded-forward 1","expected":["1.09876","187.64"],"passed":false},{"actual":["146.341","-365.90"],"check":"regression points-from-rounded-forward 2","expected":["146.341","-365.85"],"passed":false},{"actual":["1.26538","3.80"],"check":"control: sterling dollar","expected":["1.26538","3.85"],"passed":false},{"actual":["98.421","-34.40"],"check":"control: aussie yen","expected":["98.421","-34.37"],"passed":false},{"actual":["1.35359","-41.10"],"check":"control: dollar cad","expected":["1.35359","-41.12"],"passed":false},{"actual":["0.95078","-4.20"],"check":"control: euro franc","expected":["0.95078","-4.16"],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression points-from-rounded-forward 1\", \"actual\": [\"1.09876\", \"187.60\"], \"expected\": [\"1.09876\", \"187.64\"], \"passed\": false}, {\"check\": \"regression points-from-rounded-forward 2\", \"actual\": [\"146.341\", \"-365.90\"], \"expected\": [\"146.341\", \"-365.85\"], \"passed\": false}, {\"check\": \"control: sterling dollar\", \"actual\": [\"1.26538\", \"3.80\"], \"expected\": [\"1.26538\", \"3.85\"], \"passed\": false}, {\"check\": \"control: aussie yen\", \"actual\": [\"98.421\", \"-34.40\"], \"expected\": [\"98.421\", \"-34.37\"], \"passed\": false}, {\"check\": \"control: dollar cad\", \"actual\": [\"1.35359\", \"-41.10\"], \"expected\": [\"1.35359\", \"-41.12\"], \"passed\": false}, {\"check\": \"control: euro franc\", \"actual\": [\"0.95078\", \"-4.20\"], \"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."}}