FAILURE MAP
← Case archive

FA-61366 / Options payoff and settlement / Open access

Physical delivery on exercise and assignment: put exercises are booked as share receipts · case 01

Exercised puts add shares and debit cash instead of delivering shares for cash.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The delivery direction is fixed at +1 regardless of option type.

VERIFIED REPAIR

Receive shares on calls and deliver on puts before applying the short-side inversion.

Unsuccessful approach: Special-casing only long puts leaves short puts inverted twice.

Case contract

Inputs kind C/P, strike, signed contracts (+long exercised, -short assigned), deliverable shares per contract and whether exercise happened. Long calls and short puts receive shares and pay strike*shares; long puts and short calls deliver shares and receive strike*shares. Return [share delta, cash delta] (cash in currency, computed in cents); unexercised returns [0, 0.0].

Why this case matters

Option expiry, exercise and settlement engines move cash and shares; a wrong branch misstates obligations.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(kind, strike, contracts, deliverable, exercised):
    if not exercised:
        return [0, 0.0]
    n = abs(contracts) * deliverable
    k = round(strike * 100)
    direction = 1
    if contracts < 0:
        direction = -direction
    shares = direction * n
    cash = -direction * n * k
    return [shares, cash / 100]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression put delivery direction 1', ['P', 10, 5, 100, True], [-500, 5000.0]], ['regression put delivery direction 2', ['P', 42.5, -3, 100, True], [300, -12750.0]], ['partial repair probe 1', ['P', 250, -1, 50, True], [50, -12500.0]], ['partial repair probe 2', ['P', 101.25, -3, 133, True], [399, -40398.75]], ['boundary control 1', ['C', 50, 1, 100, True], [100, -5000.0]], ['boundary control 2', ['C', 50, 1, 100, False], [0, 0.0]], ['normal control 1', ['C', 250, 2, 133, True], [266, -66500.0]], ['normal control 2', ['C', 42.5, -1, 50, True], [-50, 2125.0]]], [['regression put delivery direction 1', ['P', 10, 5, 50, True], [-250, 2500.0]], ['regression put delivery direction 2', ['P', 10, 2, 150, True], [-300, 3000.0]], ['partial repair probe 1', ['P', 250, -3, 133, True], [399, -99750.0]], ['partial repair probe 2', ['P', 101.25, -1, 150, True], [150, -15187.5]], ['boundary control 1', ['C', 50, 1, 100, False], [0, 0.0]], ['boundary control 2', ['C', 50, 1, 100, True], [100, -5000.0]], ['normal control 1', ['C', 42.5, -3, 150, False], [0, 0.0]], ['normal control 2', ['P', 10, 1, 100, False], [0, 0.0]]], [['regression put delivery direction 1', ['P', 42.5, 2, 150, True], [-300, 12750.0]], ['regression put delivery direction 2', ['P', 250, 2, 100, True], [-200, 50000.0]], ['partial repair probe 1', ['P', 42.5, -1, 50, True], [50, -2125.0]], ['partial repair probe 2', ['P', 250, -3, 50, True], [150, -37500.0]], ['boundary control 1', ['C', 50, 1, 100, True], [100, -5000.0]], ['boundary control 2', ['C', 50, 1, 100, False], [0, 0.0]], ['normal control 1', ['C', 250, 1, 133, True], [133, -33250.0]], ['normal control 2', ['C', 250, 2, 100, True], [200, -50000.0]]], [['regression put delivery direction 1', ['P', 10, -3, 150, True], [450, -4500.0]], ['regression put delivery direction 2', ['P', 42.5, -1, 133, True], [133, -5652.5]], ['partial repair probe 1', ['P', 250, -3, 100, True], [300, -75000.0]], ['partial repair probe 2', ['P', 101.25, -3, 50, True], [150, -15187.5]], ['boundary control 1', ['C', 50, 1, 100, False], [0, 0.0]], ['boundary control 2', ['C', 50, 1, 100, True], [100, -5000.0]], ['normal control 1', ['C', 42.5, -1, 100, True], [-100, 4250.0]], ['normal control 2', ['C', 101.25, 5, 100, True], [500, -50625.0]]], [['regression put delivery direction 1', ['P', 42.5, 1, 50, True], [-50, 2125.0]], ['regression put delivery direction 2', ['P', 42.5, -3, 100, True], [300, -12750.0]], ['partial repair probe 1', ['P', 42.5, -1, 100, True], [100, -4250.0]], ['partial repair probe 2', ['P', 101.25, -1, 133, True], [133, -13466.25]], ['boundary control 1', ['C', 50, 1, 100, False], [0, 0.0]], ['boundary control 2', ['C', 50, 1, 100, True], [100, -5000.0]], ['normal control 1', ['C', 250, -3, 100, True], [-300, 75000.0]], ['normal control 2', ['C', 10, -3, 150, True], [-450, 4500.0]]]]
for label, args, expected in fixtures[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 fixtureActualExpectedOutcome
regression put delivery direction 1[500, -5000.0][-500, 5000.0]Failed
regression put delivery direction 2[-300, 12750.0][300, -12750.0]Failed
partial repair probe 1[-50, 12500.0][50, -12500.0]Failed
partial repair probe 2[-399, 40398.75][399, -40398.75]Failed
boundary control 1[100, -5000.0][100, -5000.0]Passed
boundary control 2[0, 0.0][0, 0.0]Passed
normal control 1[266, -66500.0][266, -66500.0]Passed
normal control 2[-50, 2125.0][-50, 2125.0]Passed

SHA-256 / 5d4bb78f1032a44c4fb2e416494bc2c8cc7ec2dec4ce641379c7cdefe95ac267

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(kind, strike, contracts, deliverable, exercised):
    if not exercised:
        return [0, 0.0]
    n = abs(contracts) * deliverable
    k = round(strike * 100)
    direction = -1 if kind == 'P' and contracts > 0 else 1
    if contracts < 0:
        direction = -direction
    shares = direction * n
    cash = -direction * n * k
    return [shares, cash / 100]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression put delivery direction 1', ['P', 10, 5, 100, True], [-500, 5000.0]], ['regression put delivery direction 2', ['P', 42.5, -3, 100, True], [300, -12750.0]], ['partial repair probe 1', ['P', 250, -1, 50, True], [50, -12500.0]], ['partial repair probe 2', ['P', 101.25, -3, 133, True], [399, -40398.75]], ['boundary control 1', ['C', 50, 1, 100, True], [100, -5000.0]], ['boundary control 2', ['C', 50, 1, 100, False], [0, 0.0]], ['normal control 1', ['C', 250, 2, 133, True], [266, -66500.0]], ['normal control 2', ['C', 42.5, -1, 50, True], [-50, 2125.0]]], [['regression put delivery direction 1', ['P', 10, 5, 50, True], [-250, 2500.0]], ['regression put delivery direction 2', ['P', 10, 2, 150, True], [-300, 3000.0]], ['partial repair probe 1', ['P', 250, -3, 133, True], [399, -99750.0]], ['partial repair probe 2', ['P', 101.25, -1, 150, True], [150, -15187.5]], ['boundary control 1', ['C', 50, 1, 100, False], [0, 0.0]], ['boundary control 2', ['C', 50, 1, 100, True], [100, -5000.0]], ['normal control 1', ['C', 42.5, -3, 150, False], [0, 0.0]], ['normal control 2', ['P', 10, 1, 100, False], [0, 0.0]]], [['regression put delivery direction 1', ['P', 42.5, 2, 150, True], [-300, 12750.0]], ['regression put delivery direction 2', ['P', 250, 2, 100, True], [-200, 50000.0]], ['partial repair probe 1', ['P', 42.5, -1, 50, True], [50, -2125.0]], ['partial repair probe 2', ['P', 250, -3, 50, True], [150, -37500.0]], ['boundary control 1', ['C', 50, 1, 100, True], [100, -5000.0]], ['boundary control 2', ['C', 50, 1, 100, False], [0, 0.0]], ['normal control 1', ['C', 250, 1, 133, True], [133, -33250.0]], ['normal control 2', ['C', 250, 2, 100, True], [200, -50000.0]]], [['regression put delivery direction 1', ['P', 10, -3, 150, True], [450, -4500.0]], ['regression put delivery direction 2', ['P', 42.5, -1, 133, True], [133, -5652.5]], ['partial repair probe 1', ['P', 250, -3, 100, True], [300, -75000.0]], ['partial repair probe 2', ['P', 101.25, -3, 50, True], [150, -15187.5]], ['boundary control 1', ['C', 50, 1, 100, False], [0, 0.0]], ['boundary control 2', ['C', 50, 1, 100, True], [100, -5000.0]], ['normal control 1', ['C', 42.5, -1, 100, True], [-100, 4250.0]], ['normal control 2', ['C', 101.25, 5, 100, True], [500, -50625.0]]], [['regression put delivery direction 1', ['P', 42.5, 1, 50, True], [-50, 2125.0]], ['regression put delivery direction 2', ['P', 42.5, -3, 100, True], [300, -12750.0]], ['partial repair probe 1', ['P', 42.5, -1, 100, True], [100, -4250.0]], ['partial repair probe 2', ['P', 101.25, -1, 133, True], [133, -13466.25]], ['boundary control 1', ['C', 50, 1, 100, False], [0, 0.0]], ['boundary control 2', ['C', 50, 1, 100, True], [100, -5000.0]], ['normal control 1', ['C', 250, -3, 100, True], [-300, 75000.0]], ['normal control 2', ['C', 10, -3, 150, True], [-450, 4500.0]]]]
for label, args, expected in fixtures[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 fixtureActualExpectedOutcome
regression put delivery direction 1[-500, 5000.0][-500, 5000.0]Passed
regression put delivery direction 2[-300, 12750.0][300, -12750.0]Failed
partial repair probe 1[-50, 12500.0][50, -12500.0]Failed
partial repair probe 2[-399, 40398.75][399, -40398.75]Failed
boundary control 1[100, -5000.0][100, -5000.0]Passed
boundary control 2[0, 0.0][0, 0.0]Passed
normal control 1[266, -66500.0][266, -66500.0]Passed
normal control 2[-50, 2125.0][-50, 2125.0]Passed

SHA-256 / 70f91724a365207826e0f89b700de7d27c22e57335af6680bb1032fc59db90c0

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(kind, strike, contracts, deliverable, exercised):
    if not exercised:
        return [0, 0.0]
    n = abs(contracts) * deliverable
    k = round(strike * 100)
    direction = 1 if kind == 'C' else -1
    if contracts < 0:
        direction = -direction
    shares = direction * n
    cash = -direction * n * k
    return [shares, cash / 100]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression put delivery direction 1', ['P', 10, 5, 100, True], [-500, 5000.0]], ['regression put delivery direction 2', ['P', 42.5, -3, 100, True], [300, -12750.0]], ['partial repair probe 1', ['P', 250, -1, 50, True], [50, -12500.0]], ['partial repair probe 2', ['P', 101.25, -3, 133, True], [399, -40398.75]], ['boundary control 1', ['C', 50, 1, 100, True], [100, -5000.0]], ['boundary control 2', ['C', 50, 1, 100, False], [0, 0.0]], ['normal control 1', ['C', 250, 2, 133, True], [266, -66500.0]], ['normal control 2', ['C', 42.5, -1, 50, True], [-50, 2125.0]]], [['regression put delivery direction 1', ['P', 10, 5, 50, True], [-250, 2500.0]], ['regression put delivery direction 2', ['P', 10, 2, 150, True], [-300, 3000.0]], ['partial repair probe 1', ['P', 250, -3, 133, True], [399, -99750.0]], ['partial repair probe 2', ['P', 101.25, -1, 150, True], [150, -15187.5]], ['boundary control 1', ['C', 50, 1, 100, False], [0, 0.0]], ['boundary control 2', ['C', 50, 1, 100, True], [100, -5000.0]], ['normal control 1', ['C', 42.5, -3, 150, False], [0, 0.0]], ['normal control 2', ['P', 10, 1, 100, False], [0, 0.0]]], [['regression put delivery direction 1', ['P', 42.5, 2, 150, True], [-300, 12750.0]], ['regression put delivery direction 2', ['P', 250, 2, 100, True], [-200, 50000.0]], ['partial repair probe 1', ['P', 42.5, -1, 50, True], [50, -2125.0]], ['partial repair probe 2', ['P', 250, -3, 50, True], [150, -37500.0]], ['boundary control 1', ['C', 50, 1, 100, True], [100, -5000.0]], ['boundary control 2', ['C', 50, 1, 100, False], [0, 0.0]], ['normal control 1', ['C', 250, 1, 133, True], [133, -33250.0]], ['normal control 2', ['C', 250, 2, 100, True], [200, -50000.0]]], [['regression put delivery direction 1', ['P', 10, -3, 150, True], [450, -4500.0]], ['regression put delivery direction 2', ['P', 42.5, -1, 133, True], [133, -5652.5]], ['partial repair probe 1', ['P', 250, -3, 100, True], [300, -75000.0]], ['partial repair probe 2', ['P', 101.25, -3, 50, True], [150, -15187.5]], ['boundary control 1', ['C', 50, 1, 100, False], [0, 0.0]], ['boundary control 2', ['C', 50, 1, 100, True], [100, -5000.0]], ['normal control 1', ['C', 42.5, -1, 100, True], [-100, 4250.0]], ['normal control 2', ['C', 101.25, 5, 100, True], [500, -50625.0]]], [['regression put delivery direction 1', ['P', 42.5, 1, 50, True], [-50, 2125.0]], ['regression put delivery direction 2', ['P', 42.5, -3, 100, True], [300, -12750.0]], ['partial repair probe 1', ['P', 42.5, -1, 100, True], [100, -4250.0]], ['partial repair probe 2', ['P', 101.25, -1, 133, True], [133, -13466.25]], ['boundary control 1', ['C', 50, 1, 100, False], [0, 0.0]], ['boundary control 2', ['C', 50, 1, 100, True], [100, -5000.0]], ['normal control 1', ['C', 250, -3, 100, True], [-300, 75000.0]], ['normal control 2', ['C', 10, -3, 150, True], [-450, 4500.0]]]]
for label, args, expected in fixtures[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 fixtureActualExpectedOutcome
regression put delivery direction 1[-500, 5000.0][-500, 5000.0]Passed
regression put delivery direction 2[300, -12750.0][300, -12750.0]Passed
partial repair probe 1[50, -12500.0][50, -12500.0]Passed
partial repair probe 2[399, -40398.75][399, -40398.75]Passed
boundary control 1[100, -5000.0][100, -5000.0]Passed
boundary control 2[0, 0.0][0, 0.0]Passed
normal control 1[266, -66500.0][266, -66500.0]Passed
normal control 2[-50, 2125.0][-50, 2125.0]Passed

SHA-256 / c5cf00e3c8a6b9ce4b24e7d5cecf34f57ec77b4a0a3e95f90da099b243d272bc

Verification & scope

A deterministic toy contract stated explicitly in the contract field; no claim of conformance to any exchange or clearing rulebook. 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:54.544301+00:00.

Case digest / 30296e80a705285fbb658ecea509eedb178be3beb047fcb1353294bcdf5fa5da