FAILURE MAP
← Case archive

FA-61616 / Options payoff and settlement / Open access

Uncovered short option margin requirement: puts use the call out-of-the-money amount · case 01

Deep out-of-the-money puts get no margin relief while in-the-money puts get relief.

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

ROOT CAUSE

OTM amount for puts is computed as max(K-S,0).

VERIFIED REPAIR

For puts the OTM amount is max(S-K,0).

Unsuccessful approach: Using |S-K| for both kinds gives relief to in-the-money options.

Case contract

Inputs kind, underlying price, strike, premium, contracts and multiplier. Out-of-the-money amount is max(K-S,0) for calls and max(S-K,0) for puts. Per-unit requirement = premium + max(20% of underlying - OTM amount, 10% of floor base) where the floor base is the underlying for calls and the strike for puts. Return requirement*multiplier*contracts rounded to cents.

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
from fractions import Fraction
N = 1
observations = []
def solve(kind, underlying, strike, premium, contracts, multiplier):
    S = Fraction(str(underlying))
    K = Fraction(str(strike))
    P = Fraction(str(premium))
    otm = max(K - S, 0)
    floor_base = S if kind == 'C' else K
    req = P + max(S * Fraction(20, 100) - otm, floor_base * Fraction(10, 100))
    return float(round(req * multiplier * contracts, 2))
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression put out-of-money amount 1', ['P', 120.0, 90, 8.0, 1, 100], 1700.0], ['regression put out-of-money amount 2', ['P', 80.0, 110, 15.1, 10, 10], 3110.0], ['partial repair probe 1', ['C', 120.0, 110, 0.5, 2, 100], 4900.0], ['partial repair probe 2', ['C', 120.0, 90, 0.5, 10, 10], 2450.0], ['boundary control 1', ['C', 100.0, 100, 2.0, 1, 100], 2200.0], ['normal control 1', ['C', 92.5, 105, 8.0, 2, 10], 345.0], ['normal control 2', ['C', 100.0, 105, 8.0, 1, 100], 2300.0], ['normal control 3', ['C', 104.25, 105, 8.0, 10, 10], 2810.0]], [['regression put out-of-money amount 1', ['P', 104.25, 100, 0.5, 2, 10], 342.0], ['regression put out-of-money amount 2', ['P', 80.0, 110, 1.25, 1, 10], 172.5], ['partial repair probe 1', ['C', 104.25, 100, 8.0, 1, 100], 2885.0], ['partial repair probe 2', ['C', 120.0, 100, 0.5, 10, 100], 24500.0], ['boundary control 1', ['C', 100.0, 100, 2.0, 1, 100], 2200.0], ['normal control 1', ['C', 104.25, 110, 8.0, 10, 10], 2310.0], ['normal control 2', ['C', 80.0, 90, 8.0, 1, 100], 1600.0], ['normal control 3', ['C', 80.0, 95, 15.1, 1, 100], 2310.0]], [['regression put out-of-money amount 1', ['P', 120.0, 95, 1.25, 1, 10], 107.5], ['regression put out-of-money amount 2', ['P', 92.5, 90, 8.0, 2, 100], 4800.0], ['partial repair probe 1', ['C', 120.0, 110, 0.5, 2, 100], 4900.0], ['partial repair probe 2', ['C', 104.25, 90, 3.4, 10, 100], 24250.0], ['boundary control 1', ['C', 100.0, 100, 2.0, 1, 100], 2200.0], ['normal control 1', ['C', 100.0, 100, 0.5, 1, 100], 2050.0], ['normal control 2', ['P', 100.0, 100, 3.4, 2, 100], 4680.0], ['normal control 3', ['C', 80.0, 110, 1.25, 2, 10], 185.0]], [['regression put out-of-money amount 1', ['P', 100.0, 90, 8.0, 2, 10], 360.0], ['regression put out-of-money amount 2', ['P', 100.0, 90, 1.25, 1, 100], 1125.0], ['partial repair probe 1', ['C', 120.0, 90, 15.1, 2, 10], 782.0], ['partial repair probe 2', ['C', 104.25, 90, 0.5, 1, 100], 2135.0], ['boundary control 1', ['C', 100.0, 100, 2.0, 1, 100], 2200.0], ['normal control 1', ['C', 92.5, 105, 8.0, 10, 10], 1725.0], ['normal control 2', ['C', 92.5, 95, 15.1, 1, 100], 3110.0], ['normal control 3', ['C', 80.0, 110, 1.25, 2, 100], 1850.0]], [['regression put out-of-money amount 1', ['P', 100.0, 95, 8.0, 10, 10], 2300.0], ['regression put out-of-money amount 2', ['P', 92.5, 110, 3.4, 2, 10], 438.0], ['partial repair probe 1', ['C', 100.0, 90, 0.5, 1, 10], 205.0], ['partial repair probe 2', ['C', 92.5, 90, 8.0, 2, 100], 5300.0], ['boundary control 1', ['C', 100.0, 100, 2.0, 1, 100], 2200.0], ['normal control 1', ['C', 92.5, 95, 3.4, 1, 10], 194.0], ['normal control 2', ['C', 92.5, 95, 8.0, 10, 100], 24000.0], ['normal control 3', ['C', 100.0, 100, 3.4, 10, 10], 2340.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 out-of-money amount 13200.01700.0Failed
regression put out-of-money amount 22610.03110.0Failed
partial repair probe 14900.04900.0Passed
partial repair probe 22450.02450.0Passed
boundary control 12200.02200.0Passed
normal control 1345.0345.0Passed
normal control 22300.02300.0Passed
normal control 32810.02810.0Passed

SHA-256 / 64790fa0d3df7cebab426551a3c36752732679358b5e523a40b56704607d9772

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
N = 1
observations = []
def solve(kind, underlying, strike, premium, contracts, multiplier):
    S = Fraction(str(underlying))
    K = Fraction(str(strike))
    P = Fraction(str(premium))
    otm = abs(S - K)
    floor_base = S if kind == 'C' else K
    req = P + max(S * Fraction(20, 100) - otm, floor_base * Fraction(10, 100))
    return float(round(req * multiplier * contracts, 2))
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression put out-of-money amount 1', ['P', 120.0, 90, 8.0, 1, 100], 1700.0], ['regression put out-of-money amount 2', ['P', 80.0, 110, 15.1, 10, 10], 3110.0], ['partial repair probe 1', ['C', 120.0, 110, 0.5, 2, 100], 4900.0], ['partial repair probe 2', ['C', 120.0, 90, 0.5, 10, 10], 2450.0], ['boundary control 1', ['C', 100.0, 100, 2.0, 1, 100], 2200.0], ['normal control 1', ['C', 92.5, 105, 8.0, 2, 10], 345.0], ['normal control 2', ['C', 100.0, 105, 8.0, 1, 100], 2300.0], ['normal control 3', ['C', 104.25, 105, 8.0, 10, 10], 2810.0]], [['regression put out-of-money amount 1', ['P', 104.25, 100, 0.5, 2, 10], 342.0], ['regression put out-of-money amount 2', ['P', 80.0, 110, 1.25, 1, 10], 172.5], ['partial repair probe 1', ['C', 104.25, 100, 8.0, 1, 100], 2885.0], ['partial repair probe 2', ['C', 120.0, 100, 0.5, 10, 100], 24500.0], ['boundary control 1', ['C', 100.0, 100, 2.0, 1, 100], 2200.0], ['normal control 1', ['C', 104.25, 110, 8.0, 10, 10], 2310.0], ['normal control 2', ['C', 80.0, 90, 8.0, 1, 100], 1600.0], ['normal control 3', ['C', 80.0, 95, 15.1, 1, 100], 2310.0]], [['regression put out-of-money amount 1', ['P', 120.0, 95, 1.25, 1, 10], 107.5], ['regression put out-of-money amount 2', ['P', 92.5, 90, 8.0, 2, 100], 4800.0], ['partial repair probe 1', ['C', 120.0, 110, 0.5, 2, 100], 4900.0], ['partial repair probe 2', ['C', 104.25, 90, 3.4, 10, 100], 24250.0], ['boundary control 1', ['C', 100.0, 100, 2.0, 1, 100], 2200.0], ['normal control 1', ['C', 100.0, 100, 0.5, 1, 100], 2050.0], ['normal control 2', ['P', 100.0, 100, 3.4, 2, 100], 4680.0], ['normal control 3', ['C', 80.0, 110, 1.25, 2, 10], 185.0]], [['regression put out-of-money amount 1', ['P', 100.0, 90, 8.0, 2, 10], 360.0], ['regression put out-of-money amount 2', ['P', 100.0, 90, 1.25, 1, 100], 1125.0], ['partial repair probe 1', ['C', 120.0, 90, 15.1, 2, 10], 782.0], ['partial repair probe 2', ['C', 104.25, 90, 0.5, 1, 100], 2135.0], ['boundary control 1', ['C', 100.0, 100, 2.0, 1, 100], 2200.0], ['normal control 1', ['C', 92.5, 105, 8.0, 10, 10], 1725.0], ['normal control 2', ['C', 92.5, 95, 15.1, 1, 100], 3110.0], ['normal control 3', ['C', 80.0, 110, 1.25, 2, 100], 1850.0]], [['regression put out-of-money amount 1', ['P', 100.0, 95, 8.0, 10, 10], 2300.0], ['regression put out-of-money amount 2', ['P', 92.5, 110, 3.4, 2, 10], 438.0], ['partial repair probe 1', ['C', 100.0, 90, 0.5, 1, 10], 205.0], ['partial repair probe 2', ['C', 92.5, 90, 8.0, 2, 100], 5300.0], ['boundary control 1', ['C', 100.0, 100, 2.0, 1, 100], 2200.0], ['normal control 1', ['C', 92.5, 95, 3.4, 1, 10], 194.0], ['normal control 2', ['C', 92.5, 95, 8.0, 10, 100], 24000.0], ['normal control 3', ['C', 100.0, 100, 3.4, 10, 10], 2340.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 out-of-money amount 11700.01700.0Passed
regression put out-of-money amount 22610.03110.0Failed
partial repair probe 12900.04900.0Failed
partial repair probe 21250.02450.0Failed
boundary control 12200.02200.0Passed
normal control 1345.0345.0Passed
normal control 22300.02300.0Passed
normal control 32810.02810.0Passed

SHA-256 / 6585334b701c25d6122add94f40018b6b2ca7a16e818399a364164812ff078a6

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
N = 1
observations = []
def solve(kind, underlying, strike, premium, contracts, multiplier):
    S = Fraction(str(underlying))
    K = Fraction(str(strike))
    P = Fraction(str(premium))
    otm = max(K - S, 0) if kind == 'C' else max(S - K, 0)
    floor_base = S if kind == 'C' else K
    req = P + max(S * Fraction(20, 100) - otm, floor_base * Fraction(10, 100))
    return float(round(req * multiplier * contracts, 2))
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression put out-of-money amount 1', ['P', 120.0, 90, 8.0, 1, 100], 1700.0], ['regression put out-of-money amount 2', ['P', 80.0, 110, 15.1, 10, 10], 3110.0], ['partial repair probe 1', ['C', 120.0, 110, 0.5, 2, 100], 4900.0], ['partial repair probe 2', ['C', 120.0, 90, 0.5, 10, 10], 2450.0], ['boundary control 1', ['C', 100.0, 100, 2.0, 1, 100], 2200.0], ['normal control 1', ['C', 92.5, 105, 8.0, 2, 10], 345.0], ['normal control 2', ['C', 100.0, 105, 8.0, 1, 100], 2300.0], ['normal control 3', ['C', 104.25, 105, 8.0, 10, 10], 2810.0]], [['regression put out-of-money amount 1', ['P', 104.25, 100, 0.5, 2, 10], 342.0], ['regression put out-of-money amount 2', ['P', 80.0, 110, 1.25, 1, 10], 172.5], ['partial repair probe 1', ['C', 104.25, 100, 8.0, 1, 100], 2885.0], ['partial repair probe 2', ['C', 120.0, 100, 0.5, 10, 100], 24500.0], ['boundary control 1', ['C', 100.0, 100, 2.0, 1, 100], 2200.0], ['normal control 1', ['C', 104.25, 110, 8.0, 10, 10], 2310.0], ['normal control 2', ['C', 80.0, 90, 8.0, 1, 100], 1600.0], ['normal control 3', ['C', 80.0, 95, 15.1, 1, 100], 2310.0]], [['regression put out-of-money amount 1', ['P', 120.0, 95, 1.25, 1, 10], 107.5], ['regression put out-of-money amount 2', ['P', 92.5, 90, 8.0, 2, 100], 4800.0], ['partial repair probe 1', ['C', 120.0, 110, 0.5, 2, 100], 4900.0], ['partial repair probe 2', ['C', 104.25, 90, 3.4, 10, 100], 24250.0], ['boundary control 1', ['C', 100.0, 100, 2.0, 1, 100], 2200.0], ['normal control 1', ['C', 100.0, 100, 0.5, 1, 100], 2050.0], ['normal control 2', ['P', 100.0, 100, 3.4, 2, 100], 4680.0], ['normal control 3', ['C', 80.0, 110, 1.25, 2, 10], 185.0]], [['regression put out-of-money amount 1', ['P', 100.0, 90, 8.0, 2, 10], 360.0], ['regression put out-of-money amount 2', ['P', 100.0, 90, 1.25, 1, 100], 1125.0], ['partial repair probe 1', ['C', 120.0, 90, 15.1, 2, 10], 782.0], ['partial repair probe 2', ['C', 104.25, 90, 0.5, 1, 100], 2135.0], ['boundary control 1', ['C', 100.0, 100, 2.0, 1, 100], 2200.0], ['normal control 1', ['C', 92.5, 105, 8.0, 10, 10], 1725.0], ['normal control 2', ['C', 92.5, 95, 15.1, 1, 100], 3110.0], ['normal control 3', ['C', 80.0, 110, 1.25, 2, 100], 1850.0]], [['regression put out-of-money amount 1', ['P', 100.0, 95, 8.0, 10, 10], 2300.0], ['regression put out-of-money amount 2', ['P', 92.5, 110, 3.4, 2, 10], 438.0], ['partial repair probe 1', ['C', 100.0, 90, 0.5, 1, 10], 205.0], ['partial repair probe 2', ['C', 92.5, 90, 8.0, 2, 100], 5300.0], ['boundary control 1', ['C', 100.0, 100, 2.0, 1, 100], 2200.0], ['normal control 1', ['C', 92.5, 95, 3.4, 1, 10], 194.0], ['normal control 2', ['C', 92.5, 95, 8.0, 10, 100], 24000.0], ['normal control 3', ['C', 100.0, 100, 3.4, 10, 10], 2340.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 out-of-money amount 11700.01700.0Passed
regression put out-of-money amount 23110.03110.0Passed
partial repair probe 14900.04900.0Passed
partial repair probe 22450.02450.0Passed
boundary control 12200.02200.0Passed
normal control 1345.0345.0Passed
normal control 22300.02300.0Passed
normal control 32810.02810.0Passed

SHA-256 / 661aa47eda9df43a9fce9e6bbd585d49bd87a49a5f73be7f869a0091d438f02a

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:56.832362+00:00.

Case digest / e732d9290215638b2d56dd185e10c3656709b3673567aacef19aad76ad24a949