FAILURE MAP
← Case archive

FA-61736 / Options payoff and settlement / Open access

Implied volatility by bisection with arbitrage bounds: the lower bound uses the undiscounted intrinsic value · case 01

Prices between discounted and undiscounted intrinsic are rejected or solved inconsistently.

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

ROOT CAUSE

The lower bound uses max(S-K,0) or max(K-S,0) instead of the discounted strike.

VERIFIED REPAIR

Discount the strike in the lower bound.

Unsuccessful approach: Applying the call bound formula to puts leaves put bounds wrong.

Case contract

Inputs kind, option price, S, K, r, T (no dividends). If price <= lower bound (call max(S - K e^{-rT},0), put max(K e^{-rT} - S,0)) or price >= upper bound (call S, put K e^{-rT}) return None. Otherwise bisect sigma in [1e-6, 5] for 100 iterations on the Black-Scholes price and return the midpoint rounded to 4.

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
N = 1
observations = []
def solve(kind, price, S, K, r, T):
    def N(x):
        return 0.5 * (1 + math.erf(x / math.sqrt(2)))
    def bs(v):
        d1 = (math.log(S / K) + (r + 0.5 * v * v) * T) / (v * math.sqrt(T))
        d2 = d1 - v * math.sqrt(T)
        if kind == 'C':
            return S * N(d1) - K * math.exp(-r * T) * N(d2)
        return K * math.exp(-r * T) * N(-d2) - S * N(-d1)
    disc_k = K * math.exp(-r * T)
    lower = max(S - K, 0) if kind == 'C' else max(K - S, 0)
    upper = S if kind == 'C' else disc_k
    if price <= lower or price >= upper:
        return None
    lo, hi = 1e-6, 5.0
    for _ in range(100):
        mid = (lo + hi) / 2
        if bs(mid) > price:
            hi = mid
        else:
            lo = mid
    return round((lo + hi) / 2, 4)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression lower arbitrage bound 1', ['P', 6.9002, 100.0, 120.0, 0.08, 2.0], 0.1], ['regression lower arbitrage bound 2', ['C', 22.0232, 110.0, 95.0, 0.08, 2.0], None], ['partial repair probe 1', ['P', 0.01, 100.0, 95.0, 0.03, 2.0], 0.0321], ['partial repair probe 2', ['P', 0.0713, 110.0, 95.0, 0.08, 2.0], 0.1], ['normal control 1', ['C', 32.8627, 100.0, 100.0, 0.0, 2.0], 0.6], ['normal control 2', ['C', 0.0, 100.0, 100.0, 0.0, 0.25], None], ['normal control 3', ['C', 100.0, 100.0, 100.0, 0.03, 2.0], None], ['normal control 4', ['C', 47.0024, 100.0, 100.0, 0.03, 0.25], 2.5]], [['regression lower arbitrage bound 1', ['P', 6.1558, 90.0, 100.0, 0.08, 1.0], 0.1352], ['regression lower arbitrage bound 2', ['C', 12.2939, 100.0, 95.0, 0.08, 1.0], None], ['partial repair probe 1', ['P', 1.1273, 100.0, 95.0, 0.03, 1.0], 0.1], ['partial repair probe 2', ['P', 2.2473, 100.0, 120.0, 0.08, 2.0], None], ['normal control 1', ['C', 19.4236, 100.0, 95.0, 0.08, 2.0], 0.1], ['normal control 2', ['C', 32.8627, 100.0, 100.0, 0.0, 2.0], 0.6], ['normal control 3', ['P', 12.0217, 90.0, 100.0, 0.0, 0.25], 0.3], ['normal control 4', ['C', 43.9475, 110.0, 95.0, 0.03, 2.0], 0.6]], [['regression lower arbitrage bound 1', ['C', 22.0232, 110.0, 95.0, 0.08, 2.0], None], ['regression lower arbitrage bound 2', ['C', 10.9901, 110.0, 100.0, 0.08, 0.25], None], ['partial repair probe 1', ['P', 2.2473, 100.0, 120.0, 0.08, 2.0], None], ['partial repair probe 2', ['P', 5.01, 90.0, 95.0, 0.08, 2.0], 0.1832], ['normal control 1', ['C', 91.9882, 100.0, 100.0, 0.0, 1.0], 3.5], ['normal control 2', ['C', 68.1279, 90.0, 120.0, 0.0, 1.0], 2.5], ['normal control 3', ['P', 104.819, 100.0, 120.0, 0.03, 2.0], 2.5], ['normal control 4', ['P', 120.0, 100.0, 120.0, 0.0, 2.0], None]], [['regression lower arbitrage bound 1', ['C', 0.01, 100.0, 100.0, 0.08, 2.0], None], ['regression lower arbitrage bound 2', ['C', 9.0363, 90.0, 95.0, 0.08, 2.0], None], ['partial repair probe 1', ['P', 0.01, 110.0, 100.0, 0.08, 0.25], 0.0927], ['partial repair probe 2', ['P', 0.2861, 100.0, 95.0, 0.03, 0.25], 0.1], ['normal control 1', ['C', 89.2978, 110.0, 95.0, 0.08, 1.0], 2.5], ['normal control 2', ['C', 22.3436, 110.0, 95.0, 0.08, 1.0], 0.1], ['normal control 3', ['C', 28.1884, 100.0, 95.0, 0.08, 0.25], 1.3], ['normal control 4', ['C', 100.0, 100.0, 95.0, 0.08, 1.0], None]], [['regression lower arbitrage bound 1', ['P', 19.1037, 100.0, 120.0, 0.03, 0.25], 0.1002], ['regression lower arbitrage bound 2', ['P', 2.8891, 110.0, 120.0, 0.08, 2.0], 0.1], ['partial repair probe 1', ['P', 7.4876, 100.0, 95.0, 0.08, 2.0], 0.3], ['partial repair probe 2', ['P', 9.99, 90.0, 100.0, 0.0, 1.0], None], ['normal control 1', ['P', 92.5421, 110.0, 120.0, 0.03, 1.0], 2.5], ['normal control 2', ['P', 100.0, 90.0, 100.0, 0.0, 2.0], None], ['normal control 3', ['P', 0.0, 100.0, 95.0, 0.03, 2.0], None], ['normal control 4', ['C', 0, 90.0, 100.0, 0.03, 0.25], None]]]
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 lower arbitrage bound 1None0.1Failed
regression lower arbitrage bound 20.0NoneFailed
partial repair probe 10.03210.0321Passed
partial repair probe 20.10.1Passed
normal control 10.60.6Passed
normal control 2NoneNonePassed
normal control 3NoneNonePassed
normal control 42.52.5Passed

SHA-256 / 3d9e2d424dec85492539075f11f37422b058e03e095ab9b08d0c27940a86c606

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(kind, price, S, K, r, T):
    def N(x):
        return 0.5 * (1 + math.erf(x / math.sqrt(2)))
    def bs(v):
        d1 = (math.log(S / K) + (r + 0.5 * v * v) * T) / (v * math.sqrt(T))
        d2 = d1 - v * math.sqrt(T)
        if kind == 'C':
            return S * N(d1) - K * math.exp(-r * T) * N(d2)
        return K * math.exp(-r * T) * N(-d2) - S * N(-d1)
    disc_k = K * math.exp(-r * T)
    lower = max(S - disc_k, 0)
    upper = S if kind == 'C' else disc_k
    if price <= lower or price >= upper:
        return None
    lo, hi = 1e-6, 5.0
    for _ in range(100):
        mid = (lo + hi) / 2
        if bs(mid) > price:
            hi = mid
        else:
            lo = mid
    return round((lo + hi) / 2, 4)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression lower arbitrage bound 1', ['P', 6.9002, 100.0, 120.0, 0.08, 2.0], 0.1], ['regression lower arbitrage bound 2', ['C', 22.0232, 110.0, 95.0, 0.08, 2.0], None], ['partial repair probe 1', ['P', 0.01, 100.0, 95.0, 0.03, 2.0], 0.0321], ['partial repair probe 2', ['P', 0.0713, 110.0, 95.0, 0.08, 2.0], 0.1], ['normal control 1', ['C', 32.8627, 100.0, 100.0, 0.0, 2.0], 0.6], ['normal control 2', ['C', 0.0, 100.0, 100.0, 0.0, 0.25], None], ['normal control 3', ['C', 100.0, 100.0, 100.0, 0.03, 2.0], None], ['normal control 4', ['C', 47.0024, 100.0, 100.0, 0.03, 0.25], 2.5]], [['regression lower arbitrage bound 1', ['P', 6.1558, 90.0, 100.0, 0.08, 1.0], 0.1352], ['regression lower arbitrage bound 2', ['C', 12.2939, 100.0, 95.0, 0.08, 1.0], None], ['partial repair probe 1', ['P', 1.1273, 100.0, 95.0, 0.03, 1.0], 0.1], ['partial repair probe 2', ['P', 2.2473, 100.0, 120.0, 0.08, 2.0], None], ['normal control 1', ['C', 19.4236, 100.0, 95.0, 0.08, 2.0], 0.1], ['normal control 2', ['C', 32.8627, 100.0, 100.0, 0.0, 2.0], 0.6], ['normal control 3', ['P', 12.0217, 90.0, 100.0, 0.0, 0.25], 0.3], ['normal control 4', ['C', 43.9475, 110.0, 95.0, 0.03, 2.0], 0.6]], [['regression lower arbitrage bound 1', ['C', 22.0232, 110.0, 95.0, 0.08, 2.0], None], ['regression lower arbitrage bound 2', ['C', 10.9901, 110.0, 100.0, 0.08, 0.25], None], ['partial repair probe 1', ['P', 2.2473, 100.0, 120.0, 0.08, 2.0], None], ['partial repair probe 2', ['P', 5.01, 90.0, 95.0, 0.08, 2.0], 0.1832], ['normal control 1', ['C', 91.9882, 100.0, 100.0, 0.0, 1.0], 3.5], ['normal control 2', ['C', 68.1279, 90.0, 120.0, 0.0, 1.0], 2.5], ['normal control 3', ['P', 104.819, 100.0, 120.0, 0.03, 2.0], 2.5], ['normal control 4', ['P', 120.0, 100.0, 120.0, 0.0, 2.0], None]], [['regression lower arbitrage bound 1', ['C', 0.01, 100.0, 100.0, 0.08, 2.0], None], ['regression lower arbitrage bound 2', ['C', 9.0363, 90.0, 95.0, 0.08, 2.0], None], ['partial repair probe 1', ['P', 0.01, 110.0, 100.0, 0.08, 0.25], 0.0927], ['partial repair probe 2', ['P', 0.2861, 100.0, 95.0, 0.03, 0.25], 0.1], ['normal control 1', ['C', 89.2978, 110.0, 95.0, 0.08, 1.0], 2.5], ['normal control 2', ['C', 22.3436, 110.0, 95.0, 0.08, 1.0], 0.1], ['normal control 3', ['C', 28.1884, 100.0, 95.0, 0.08, 0.25], 1.3], ['normal control 4', ['C', 100.0, 100.0, 95.0, 0.08, 1.0], None]], [['regression lower arbitrage bound 1', ['P', 19.1037, 100.0, 120.0, 0.03, 0.25], 0.1002], ['regression lower arbitrage bound 2', ['P', 2.8891, 110.0, 120.0, 0.08, 2.0], 0.1], ['partial repair probe 1', ['P', 7.4876, 100.0, 95.0, 0.08, 2.0], 0.3], ['partial repair probe 2', ['P', 9.99, 90.0, 100.0, 0.0, 1.0], None], ['normal control 1', ['P', 92.5421, 110.0, 120.0, 0.03, 1.0], 2.5], ['normal control 2', ['P', 100.0, 90.0, 100.0, 0.0, 2.0], None], ['normal control 3', ['P', 0.0, 100.0, 95.0, 0.03, 2.0], None], ['normal control 4', ['C', 0, 90.0, 100.0, 0.03, 0.25], None]]]
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 lower arbitrage bound 10.10.1Passed
regression lower arbitrage bound 2NoneNonePassed
partial repair probe 1None0.0321Failed
partial repair probe 2None0.1Failed
normal control 10.60.6Passed
normal control 2NoneNonePassed
normal control 3NoneNonePassed
normal control 42.52.5Passed

SHA-256 / 19f9537c3523452fbf74451497be916656b2385faf1d7c0e8e9b89767a305d45

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(kind, price, S, K, r, T):
    def N(x):
        return 0.5 * (1 + math.erf(x / math.sqrt(2)))
    def bs(v):
        d1 = (math.log(S / K) + (r + 0.5 * v * v) * T) / (v * math.sqrt(T))
        d2 = d1 - v * math.sqrt(T)
        if kind == 'C':
            return S * N(d1) - K * math.exp(-r * T) * N(d2)
        return K * math.exp(-r * T) * N(-d2) - S * N(-d1)
    disc_k = K * math.exp(-r * T)
    lower = max(S - disc_k, 0) if kind == 'C' else max(disc_k - S, 0)
    upper = S if kind == 'C' else disc_k
    if price <= lower or price >= upper:
        return None
    lo, hi = 1e-6, 5.0
    for _ in range(100):
        mid = (lo + hi) / 2
        if bs(mid) > price:
            hi = mid
        else:
            lo = mid
    return round((lo + hi) / 2, 4)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression lower arbitrage bound 1', ['P', 6.9002, 100.0, 120.0, 0.08, 2.0], 0.1], ['regression lower arbitrage bound 2', ['C', 22.0232, 110.0, 95.0, 0.08, 2.0], None], ['partial repair probe 1', ['P', 0.01, 100.0, 95.0, 0.03, 2.0], 0.0321], ['partial repair probe 2', ['P', 0.0713, 110.0, 95.0, 0.08, 2.0], 0.1], ['normal control 1', ['C', 32.8627, 100.0, 100.0, 0.0, 2.0], 0.6], ['normal control 2', ['C', 0.0, 100.0, 100.0, 0.0, 0.25], None], ['normal control 3', ['C', 100.0, 100.0, 100.0, 0.03, 2.0], None], ['normal control 4', ['C', 47.0024, 100.0, 100.0, 0.03, 0.25], 2.5]], [['regression lower arbitrage bound 1', ['P', 6.1558, 90.0, 100.0, 0.08, 1.0], 0.1352], ['regression lower arbitrage bound 2', ['C', 12.2939, 100.0, 95.0, 0.08, 1.0], None], ['partial repair probe 1', ['P', 1.1273, 100.0, 95.0, 0.03, 1.0], 0.1], ['partial repair probe 2', ['P', 2.2473, 100.0, 120.0, 0.08, 2.0], None], ['normal control 1', ['C', 19.4236, 100.0, 95.0, 0.08, 2.0], 0.1], ['normal control 2', ['C', 32.8627, 100.0, 100.0, 0.0, 2.0], 0.6], ['normal control 3', ['P', 12.0217, 90.0, 100.0, 0.0, 0.25], 0.3], ['normal control 4', ['C', 43.9475, 110.0, 95.0, 0.03, 2.0], 0.6]], [['regression lower arbitrage bound 1', ['C', 22.0232, 110.0, 95.0, 0.08, 2.0], None], ['regression lower arbitrage bound 2', ['C', 10.9901, 110.0, 100.0, 0.08, 0.25], None], ['partial repair probe 1', ['P', 2.2473, 100.0, 120.0, 0.08, 2.0], None], ['partial repair probe 2', ['P', 5.01, 90.0, 95.0, 0.08, 2.0], 0.1832], ['normal control 1', ['C', 91.9882, 100.0, 100.0, 0.0, 1.0], 3.5], ['normal control 2', ['C', 68.1279, 90.0, 120.0, 0.0, 1.0], 2.5], ['normal control 3', ['P', 104.819, 100.0, 120.0, 0.03, 2.0], 2.5], ['normal control 4', ['P', 120.0, 100.0, 120.0, 0.0, 2.0], None]], [['regression lower arbitrage bound 1', ['C', 0.01, 100.0, 100.0, 0.08, 2.0], None], ['regression lower arbitrage bound 2', ['C', 9.0363, 90.0, 95.0, 0.08, 2.0], None], ['partial repair probe 1', ['P', 0.01, 110.0, 100.0, 0.08, 0.25], 0.0927], ['partial repair probe 2', ['P', 0.2861, 100.0, 95.0, 0.03, 0.25], 0.1], ['normal control 1', ['C', 89.2978, 110.0, 95.0, 0.08, 1.0], 2.5], ['normal control 2', ['C', 22.3436, 110.0, 95.0, 0.08, 1.0], 0.1], ['normal control 3', ['C', 28.1884, 100.0, 95.0, 0.08, 0.25], 1.3], ['normal control 4', ['C', 100.0, 100.0, 95.0, 0.08, 1.0], None]], [['regression lower arbitrage bound 1', ['P', 19.1037, 100.0, 120.0, 0.03, 0.25], 0.1002], ['regression lower arbitrage bound 2', ['P', 2.8891, 110.0, 120.0, 0.08, 2.0], 0.1], ['partial repair probe 1', ['P', 7.4876, 100.0, 95.0, 0.08, 2.0], 0.3], ['partial repair probe 2', ['P', 9.99, 90.0, 100.0, 0.0, 1.0], None], ['normal control 1', ['P', 92.5421, 110.0, 120.0, 0.03, 1.0], 2.5], ['normal control 2', ['P', 100.0, 90.0, 100.0, 0.0, 2.0], None], ['normal control 3', ['P', 0.0, 100.0, 95.0, 0.03, 2.0], None], ['normal control 4', ['C', 0, 90.0, 100.0, 0.03, 0.25], None]]]
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 lower arbitrage bound 10.10.1Passed
regression lower arbitrage bound 2NoneNonePassed
partial repair probe 10.03210.0321Passed
partial repair probe 20.10.1Passed
normal control 10.60.6Passed
normal control 2NoneNonePassed
normal control 3NoneNonePassed
normal control 42.52.5Passed

SHA-256 / 03b929b79d1c31085957d072a23a9410b54f47c940c7b2cbaa6c539acdb4f9a0

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

Case digest / c2a027235805a8b161446cd18937bfa927bca9dd735822b199789187afe03b47