FAILURE MAP
← Case archive

FA-61766 / Options payoff and settlement / Open access

Delta hedge order sized in lots: the hedge buys the exposure instead of offsetting it · case 01

Hedging doubles the delta instead of neutralizing it.

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

ROOT CAUSE

The target is +exposure.

VERIFIED REPAIR

Target the negative of the option delta exposure.

Unsuccessful approach: Forcing the target negative only works for net long delta books.

Case contract

Inputs positions [kind, signed contracts, absolute delta], multiplier, lot size and existing shares. Put delta is negative. Exposure = sum(sign*delta*contracts*multiplier); target shares = -exposure; the order is target - existing, rounded to whole lots with halves away from zero. Return the signed share quantity.

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
import math
from fractions import Fraction
N = 1
observations = []
def solve(positions, multiplier, lot, existing):
    exposure = Fraction(0)
    for kind, c, d in positions:
        sgn = -1 if kind == 'P' else 1
        exposure += sgn * Fraction(str(d)) * c * multiplier
    target = exposure
    trade = target - existing
    lots = trade / lot
    n = math.floor(abs(lots) + Fraction(1, 2))
    return int((n if lots >= 0 else -n) * lot)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression hedge direction 1', [[['C', 2, 0.5], ['P', 1, 0.25], ['P', 1, 0.35], ['C', 2, 0.6]], 10, 25, 100], -125], ['regression hedge direction 2', [[['P', 1, 0.25], ['C', 2, 0.6], ['P', -1, 0.5]], 100, 25, -250], 100], ['partial repair probe 1', [[['C', 2, 0.35], ['C', -3, 0.75], ['P', 10, 0.35]], 100, 100, -250], 800], ['partial repair probe 2', [[['P', 5, 0.35], ['P', 2, 0.5], ['C', 5, 0.25], ['P', 1, 0.75]], 100, 25, 0], 225], ['normal control 1', [[['P', 5, 0.75]], 10, 100, 100], -100], ['normal control 2', [[['C', 1, 0.25], ['C', 1, 0.6]], 10, 25, 0], 0], ['normal control 3', [[['P', 1, 0.5], ['P', -1, 0.35], ['C', 1, 0.35]], 10, 100, 100], -100], ['normal control 4', [[['P', -3, 0.75], ['C', -1, 0.05], ['C', -3, 0.6]], 10, 50, 0], 0]], [['regression hedge direction 1', [[['P', 1, 0.35]], 100, 50, 100], -50], ['regression hedge direction 2', [[['C', -3, 0.6], ['C', 5, 0.5], ['P', 5, 0.5]], 100, 100, 100], 100], ['partial repair probe 1', [[['P', 10, 0.6], ['C', 5, 0.05]], 100, 50, 75], 500], ['partial repair probe 2', [[['P', 5, 0.5], ['P', -3, 0.6], ['P', -1, 0.05]], 100, 100, 0], 100], ['normal control 1', [[['C', 5, 0.75]], 10, 100, 100], -100], ['normal control 2', [[['C', 2, 0.25]], 10, 100, 75], -100], ['normal control 3', [[['P', 1, 0.05], ['C', 10, 0.05]], 10, 25, 75], -75], ['normal control 4', [[['C', 5, 0.25], ['C', 5, 0.35]], 10, 100, 0], 0]], [['regression hedge direction 1', [[['C', 1, 0.35], ['C', -1, 0.35], ['C', -1, 0.35]], 100, 25, -250], 275], ['regression hedge direction 2', [[['C', 1, 0.5]], 100, 100, 0], -100], ['partial repair probe 1', [[['C', 5, 0.75], ['P', 5, 0.05], ['P', 5, 0.75]], 100, 50, 100], -100], ['partial repair probe 2', [[['P', 2, 0.75], ['P', 10, 0.35], ['P', 1, 0.05]], 100, 50, 75], 450], ['normal control 1', [[['C', 2, 0.5]], 10, 25, 0], 0], ['normal control 2', [[['P', 5, 0.05], ['C', -1, 0.6], ['P', 1, 0.75]], 10, 100, 75], -100], ['normal control 3', [[['P', 5, 0.05], ['P', -3, 0.25]], 10, 25, 0], 0], ['normal control 4', [[['C', 2, 0.05], ['P', 1, 0.75], ['P', 2, 0.75]], 10, 50, 100], -100]], [['regression hedge direction 1', [[['C', 1, 0.5], ['P', -1, 0.5], ['P', 5, 0.75], ['C', -3, 0.25]], 100, 25, 75], 275], ['regression hedge direction 2', [[['C', 1, 0.6], ['C', 2, 0.25]], 100, 100, 75], -200], ['partial repair probe 1', [[['P', 2, 0.25], ['P', -3, 0.75], ['C', 1, 0.6], ['P', 10, 0.75]], 100, 100, 0], 500], ['partial repair probe 2', [[['P', 1, 0.6], ['P', 5, 0.75], ['P', 5, 0.75], ['P', 10, 0.35]], 100, 50, -250], 1400], ['normal control 1', [[['C', 5, 0.35]], 10, 100, 75], -100], ['normal control 2', [[['C', -3, 0.35], ['C', 1, 0.5], ['P', 1, 0.35]], 10, 50, 0], 0], ['normal control 3', [[['C', 10, 0.05]], 10, 100, 0], 0], ['normal control 4', [[['C', 2, 0.5]], 10, 100, 100], -100]], [['regression hedge direction 1', [[['P', -3, 0.05]], 100, 25, -250], 225], ['regression hedge direction 2', [[['C', 5, 0.6], ['P', -3, 0.35], ['P', 2, 0.6]], 10, 25, -250], 225], ['partial repair probe 1', [[['P', 5, 0.6], ['C', -1, 0.05], ['C', 1, 0.25]], 10, 50, 0], 50], ['partial repair probe 2', [[['C', 1, 0.25], ['C', 1, 0.5], ['C', -1, 0.75], ['P', 10, 0.6]], 100, 100, 100], 500], ['normal control 1', [[['C', 5, 0.75], ['P', 10, 0.05]], 10, 100, 100], -100], ['normal control 2', [[['P', -3, 0.5]], 10, 100, 0], 0], ['normal control 3', [[['C', 1, 0.75], ['C', 1, 0.05], ['C', 2, 0.05], ['C', -1, 0.25]], 10, 100, 0], 0], ['normal control 4', [[['C', -3, 0.5], ['C', 2, 0.5], ['C', 2, 0.75]], 10, 25, 75], -75]]]
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 hedge direction 1-75-125Failed
regression hedge direction 2400100Failed
partial repair probe 1-300800Failed
partial repair probe 2-225225Failed
normal control 1-100-100Passed
normal control 200Passed
normal control 3-100-100Passed
normal control 400Passed

SHA-256 / 0d6daedfde58fff789b847d9ab7558ad3ba41797709aae38f4d87752c0c6c4f1

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(positions, multiplier, lot, existing):
    exposure = Fraction(0)
    for kind, c, d in positions:
        sgn = -1 if kind == 'P' else 1
        exposure += sgn * Fraction(str(d)) * c * multiplier
    target = -abs(exposure)
    trade = target - existing
    lots = trade / lot
    n = math.floor(abs(lots) + Fraction(1, 2))
    return int((n if lots >= 0 else -n) * lot)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression hedge direction 1', [[['C', 2, 0.5], ['P', 1, 0.25], ['P', 1, 0.35], ['C', 2, 0.6]], 10, 25, 100], -125], ['regression hedge direction 2', [[['P', 1, 0.25], ['C', 2, 0.6], ['P', -1, 0.5]], 100, 25, -250], 100], ['partial repair probe 1', [[['C', 2, 0.35], ['C', -3, 0.75], ['P', 10, 0.35]], 100, 100, -250], 800], ['partial repair probe 2', [[['P', 5, 0.35], ['P', 2, 0.5], ['C', 5, 0.25], ['P', 1, 0.75]], 100, 25, 0], 225], ['normal control 1', [[['P', 5, 0.75]], 10, 100, 100], -100], ['normal control 2', [[['C', 1, 0.25], ['C', 1, 0.6]], 10, 25, 0], 0], ['normal control 3', [[['P', 1, 0.5], ['P', -1, 0.35], ['C', 1, 0.35]], 10, 100, 100], -100], ['normal control 4', [[['P', -3, 0.75], ['C', -1, 0.05], ['C', -3, 0.6]], 10, 50, 0], 0]], [['regression hedge direction 1', [[['P', 1, 0.35]], 100, 50, 100], -50], ['regression hedge direction 2', [[['C', -3, 0.6], ['C', 5, 0.5], ['P', 5, 0.5]], 100, 100, 100], 100], ['partial repair probe 1', [[['P', 10, 0.6], ['C', 5, 0.05]], 100, 50, 75], 500], ['partial repair probe 2', [[['P', 5, 0.5], ['P', -3, 0.6], ['P', -1, 0.05]], 100, 100, 0], 100], ['normal control 1', [[['C', 5, 0.75]], 10, 100, 100], -100], ['normal control 2', [[['C', 2, 0.25]], 10, 100, 75], -100], ['normal control 3', [[['P', 1, 0.05], ['C', 10, 0.05]], 10, 25, 75], -75], ['normal control 4', [[['C', 5, 0.25], ['C', 5, 0.35]], 10, 100, 0], 0]], [['regression hedge direction 1', [[['C', 1, 0.35], ['C', -1, 0.35], ['C', -1, 0.35]], 100, 25, -250], 275], ['regression hedge direction 2', [[['C', 1, 0.5]], 100, 100, 0], -100], ['partial repair probe 1', [[['C', 5, 0.75], ['P', 5, 0.05], ['P', 5, 0.75]], 100, 50, 100], -100], ['partial repair probe 2', [[['P', 2, 0.75], ['P', 10, 0.35], ['P', 1, 0.05]], 100, 50, 75], 450], ['normal control 1', [[['C', 2, 0.5]], 10, 25, 0], 0], ['normal control 2', [[['P', 5, 0.05], ['C', -1, 0.6], ['P', 1, 0.75]], 10, 100, 75], -100], ['normal control 3', [[['P', 5, 0.05], ['P', -3, 0.25]], 10, 25, 0], 0], ['normal control 4', [[['C', 2, 0.05], ['P', 1, 0.75], ['P', 2, 0.75]], 10, 50, 100], -100]], [['regression hedge direction 1', [[['C', 1, 0.5], ['P', -1, 0.5], ['P', 5, 0.75], ['C', -3, 0.25]], 100, 25, 75], 275], ['regression hedge direction 2', [[['C', 1, 0.6], ['C', 2, 0.25]], 100, 100, 75], -200], ['partial repair probe 1', [[['P', 2, 0.25], ['P', -3, 0.75], ['C', 1, 0.6], ['P', 10, 0.75]], 100, 100, 0], 500], ['partial repair probe 2', [[['P', 1, 0.6], ['P', 5, 0.75], ['P', 5, 0.75], ['P', 10, 0.35]], 100, 50, -250], 1400], ['normal control 1', [[['C', 5, 0.35]], 10, 100, 75], -100], ['normal control 2', [[['C', -3, 0.35], ['C', 1, 0.5], ['P', 1, 0.35]], 10, 50, 0], 0], ['normal control 3', [[['C', 10, 0.05]], 10, 100, 0], 0], ['normal control 4', [[['C', 2, 0.5]], 10, 100, 100], -100]], [['regression hedge direction 1', [[['P', -3, 0.05]], 100, 25, -250], 225], ['regression hedge direction 2', [[['C', 5, 0.6], ['P', -3, 0.35], ['P', 2, 0.6]], 10, 25, -250], 225], ['partial repair probe 1', [[['P', 5, 0.6], ['C', -1, 0.05], ['C', 1, 0.25]], 10, 50, 0], 50], ['partial repair probe 2', [[['C', 1, 0.25], ['C', 1, 0.5], ['C', -1, 0.75], ['P', 10, 0.6]], 100, 100, 100], 500], ['normal control 1', [[['C', 5, 0.75], ['P', 10, 0.05]], 10, 100, 100], -100], ['normal control 2', [[['P', -3, 0.5]], 10, 100, 0], 0], ['normal control 3', [[['C', 1, 0.75], ['C', 1, 0.05], ['C', 2, 0.05], ['C', -1, 0.25]], 10, 100, 0], 0], ['normal control 4', [[['C', -3, 0.5], ['C', 2, 0.5], ['C', 2, 0.75]], 10, 25, 75], -75]]]
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 hedge direction 1-125-125Passed
regression hedge direction 2100100Passed
partial repair probe 1-300800Failed
partial repair probe 2-225225Failed
normal control 1-100-100Passed
normal control 200Passed
normal control 3-100-100Passed
normal control 400Passed

SHA-256 / d68a6f6ad8478bf5e0f94683bfb165db146f22a3479b060f29029bbbbd1a06c8

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(positions, multiplier, lot, existing):
    exposure = Fraction(0)
    for kind, c, d in positions:
        sgn = -1 if kind == 'P' else 1
        exposure += sgn * Fraction(str(d)) * c * multiplier
    target = -exposure
    trade = target - existing
    lots = trade / lot
    n = math.floor(abs(lots) + Fraction(1, 2))
    return int((n if lots >= 0 else -n) * lot)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression hedge direction 1', [[['C', 2, 0.5], ['P', 1, 0.25], ['P', 1, 0.35], ['C', 2, 0.6]], 10, 25, 100], -125], ['regression hedge direction 2', [[['P', 1, 0.25], ['C', 2, 0.6], ['P', -1, 0.5]], 100, 25, -250], 100], ['partial repair probe 1', [[['C', 2, 0.35], ['C', -3, 0.75], ['P', 10, 0.35]], 100, 100, -250], 800], ['partial repair probe 2', [[['P', 5, 0.35], ['P', 2, 0.5], ['C', 5, 0.25], ['P', 1, 0.75]], 100, 25, 0], 225], ['normal control 1', [[['P', 5, 0.75]], 10, 100, 100], -100], ['normal control 2', [[['C', 1, 0.25], ['C', 1, 0.6]], 10, 25, 0], 0], ['normal control 3', [[['P', 1, 0.5], ['P', -1, 0.35], ['C', 1, 0.35]], 10, 100, 100], -100], ['normal control 4', [[['P', -3, 0.75], ['C', -1, 0.05], ['C', -3, 0.6]], 10, 50, 0], 0]], [['regression hedge direction 1', [[['P', 1, 0.35]], 100, 50, 100], -50], ['regression hedge direction 2', [[['C', -3, 0.6], ['C', 5, 0.5], ['P', 5, 0.5]], 100, 100, 100], 100], ['partial repair probe 1', [[['P', 10, 0.6], ['C', 5, 0.05]], 100, 50, 75], 500], ['partial repair probe 2', [[['P', 5, 0.5], ['P', -3, 0.6], ['P', -1, 0.05]], 100, 100, 0], 100], ['normal control 1', [[['C', 5, 0.75]], 10, 100, 100], -100], ['normal control 2', [[['C', 2, 0.25]], 10, 100, 75], -100], ['normal control 3', [[['P', 1, 0.05], ['C', 10, 0.05]], 10, 25, 75], -75], ['normal control 4', [[['C', 5, 0.25], ['C', 5, 0.35]], 10, 100, 0], 0]], [['regression hedge direction 1', [[['C', 1, 0.35], ['C', -1, 0.35], ['C', -1, 0.35]], 100, 25, -250], 275], ['regression hedge direction 2', [[['C', 1, 0.5]], 100, 100, 0], -100], ['partial repair probe 1', [[['C', 5, 0.75], ['P', 5, 0.05], ['P', 5, 0.75]], 100, 50, 100], -100], ['partial repair probe 2', [[['P', 2, 0.75], ['P', 10, 0.35], ['P', 1, 0.05]], 100, 50, 75], 450], ['normal control 1', [[['C', 2, 0.5]], 10, 25, 0], 0], ['normal control 2', [[['P', 5, 0.05], ['C', -1, 0.6], ['P', 1, 0.75]], 10, 100, 75], -100], ['normal control 3', [[['P', 5, 0.05], ['P', -3, 0.25]], 10, 25, 0], 0], ['normal control 4', [[['C', 2, 0.05], ['P', 1, 0.75], ['P', 2, 0.75]], 10, 50, 100], -100]], [['regression hedge direction 1', [[['C', 1, 0.5], ['P', -1, 0.5], ['P', 5, 0.75], ['C', -3, 0.25]], 100, 25, 75], 275], ['regression hedge direction 2', [[['C', 1, 0.6], ['C', 2, 0.25]], 100, 100, 75], -200], ['partial repair probe 1', [[['P', 2, 0.25], ['P', -3, 0.75], ['C', 1, 0.6], ['P', 10, 0.75]], 100, 100, 0], 500], ['partial repair probe 2', [[['P', 1, 0.6], ['P', 5, 0.75], ['P', 5, 0.75], ['P', 10, 0.35]], 100, 50, -250], 1400], ['normal control 1', [[['C', 5, 0.35]], 10, 100, 75], -100], ['normal control 2', [[['C', -3, 0.35], ['C', 1, 0.5], ['P', 1, 0.35]], 10, 50, 0], 0], ['normal control 3', [[['C', 10, 0.05]], 10, 100, 0], 0], ['normal control 4', [[['C', 2, 0.5]], 10, 100, 100], -100]], [['regression hedge direction 1', [[['P', -3, 0.05]], 100, 25, -250], 225], ['regression hedge direction 2', [[['C', 5, 0.6], ['P', -3, 0.35], ['P', 2, 0.6]], 10, 25, -250], 225], ['partial repair probe 1', [[['P', 5, 0.6], ['C', -1, 0.05], ['C', 1, 0.25]], 10, 50, 0], 50], ['partial repair probe 2', [[['C', 1, 0.25], ['C', 1, 0.5], ['C', -1, 0.75], ['P', 10, 0.6]], 100, 100, 100], 500], ['normal control 1', [[['C', 5, 0.75], ['P', 10, 0.05]], 10, 100, 100], -100], ['normal control 2', [[['P', -3, 0.5]], 10, 100, 0], 0], ['normal control 3', [[['C', 1, 0.75], ['C', 1, 0.05], ['C', 2, 0.05], ['C', -1, 0.25]], 10, 100, 0], 0], ['normal control 4', [[['C', -3, 0.5], ['C', 2, 0.5], ['C', 2, 0.75]], 10, 25, 75], -75]]]
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 hedge direction 1-125-125Passed
regression hedge direction 2100100Passed
partial repair probe 1800800Passed
partial repair probe 2225225Passed
normal control 1-100-100Passed
normal control 200Passed
normal control 3-100-100Passed
normal control 400Passed

SHA-256 / e4c5b017e8fed535041fca13ed6d9b9b5c3dffc723c68a4b1c6e39426863d600

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

Case digest / 760f18af54d9bd4cf8728e9da42d10ec2f50f70be1ff2d511880e7f561c7961c