FA-61566 / Options payoff and settlement / Open access
European option value with continuous dividend yield: an option at expiry returns zero · case 01
Expiring in-the-money options are valued at zero.
ROOT CAUSE
The days == 0 guard returns 0.0 instead of intrinsic.
VERIFIED REPAIR
Return intrinsic value at expiry.
Unsuccessful approach: Returning call intrinsic for every kind misvalues expiring puts.
Case contract
Inputs kind, spot S, strike K, rate r, dividend yield q, volatility sigma and calendar days to expiry. T = days/365. At days == 0 return intrinsic value. Otherwise d1 = (ln(S/K) + (r - q + sigma^2/2)T)/(sigma sqrt T), d2 = d1 - sigma sqrt T, call = S e^{-qT} N(d1) - K e^{-rT} N(d2), put = K e^{-rT} N(-d2) - S e^{-qT} N(-d1). Round to 6.
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, S, K, r, q, sigma, days):
def N(x):
return 0.5 * (1 + math.erf(x / math.sqrt(2)))
T = days / 365
if days == 0:
return 0.0
d1 = (math.log(S / K) + (r - q + 0.5 * sigma ** 2) * T) / (sigma * math.sqrt(T))
d2 = d1 - sigma * math.sqrt(T)
if kind == 'C':
v = S * math.exp(-q * T) * N(d1) - K * math.exp(-r * T) * N(d2)
else:
v = K * math.exp(-r * T) * N(-d2) - S * math.exp(-q * T) * N(-d1)
return round(v, 6)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression expiry intrinsic 1', ['C', 100.0, 95.0, 0.0, 0.0, 0.2, 0], 5.0], ['regression expiry intrinsic 2', ['P', 90.0, 105.0, 0.05, 0.0, 0.35, 0], 15.0], ['partial repair probe 1', ['P', 110.0, 100.0, 0.02, 0.0, 0.2, 0], 0.0], ['partial repair probe 2', ['P', 110.0, 105.0, 0.02, 0.0, 0.35, 0], 0.0], ['normal control 1', ['C', 90.0, 105.0, 0.02, 0.015, 0.35, 730], 12.381799], ['normal control 2', ['P', 110.0, 100.0, 0.0, 0.015, 0.1, 365], 1.243579], ['normal control 3', ['P', 110.0, 105.0, 0.0, 0.0, 0.1, 7], 0.000151], ['normal control 4', ['C', 100.0, 100.0, 0.0, 0.015, 0.1, 365], 3.25808]], [['regression expiry intrinsic 1', ['C', 100.0, 95.0, 0.02, 0.015, 0.2, 0], 5.0], ['regression expiry intrinsic 2', ['P', 90.0, 95.0, 0.02, 0.015, 0.2, 0], 5.0], ['partial repair probe 1', ['P', 100.0, 95.0, 0.05, 0.03, 0.35, 0], 0.0], ['partial repair probe 2', ['P', 100.0, 95.0, 0.0, 0.03, 0.1, 0], 0.0], ['normal control 1', ['P', 90.0, 95.0, 0.0, 0.0, 0.2, 30], 5.491714], ['normal control 2', ['P', 110.0, 100.0, 0.02, 0.03, 0.2, 91], 0.989366], ['normal control 3', ['P', 110.0, 95.0, 0.02, 0.03, 0.2, 7], 0.0], ['normal control 4', ['P', 90.0, 95.0, 0.02, 0.0, 0.35, 182], 11.222351]], [['regression expiry intrinsic 1', ['P', 90.0, 100.0, 0.02, 0.0, 0.2, 0], 10.0], ['regression expiry intrinsic 2', ['P', 100.0, 105.0, 0.05, 0.0, 0.35, 0], 5.0], ['partial repair probe 1', ['P', 100.0, 95.0, 0.05, 0.0, 0.2, 0], 0.0], ['partial repair probe 2', ['P', 110.0, 100.0, 0.0, 0.0, 0.2, 0], 0.0], ['normal control 1', ['C', 90.0, 105.0, 0.02, 0.0, 0.2, 91], 0.287643], ['normal control 2', ['P', 110.0, 105.0, 0.02, 0.0, 0.35, 91], 5.027049], ['normal control 3', ['C', 90.0, 105.0, 0.02, 0.03, 0.1, 730], 0.68644], ['normal control 4', ['P', 110.0, 105.0, 0.05, 0.015, 0.1, 365], 1.21651]], [['regression expiry intrinsic 1', ['P', 90.0, 100.0, 0.05, 0.0, 0.2, 0], 10.0], ['regression expiry intrinsic 2', ['C', 110.0, 105.0, 0.05, 0.0, 0.2, 0], 5.0], ['partial repair probe 1', ['P', 100.0, 95.0, 0.0, 0.0, 0.1, 0], 0.0], ['partial repair probe 2', ['P', 110.0, 100.0, 0.05, 0.015, 0.2, 0], 0.0], ['normal control 1', ['C', 90.0, 105.0, 0.05, 0.03, 0.35, 7], 0.000965], ['normal control 2', ['P', 110.0, 100.0, 0.05, 0.03, 0.1, 1], 0.0], ['normal control 3', ['P', 100.0, 95.0, 0.05, 0.03, 0.1, 7], 3.1e-05], ['normal control 4', ['P', 90.0, 105.0, 0.0, 0.015, 0.2, 365], 18.471878]], [['regression expiry intrinsic 1', ['P', 90.0, 95.0, 0.02, 0.03, 0.2, 0], 5.0], ['regression expiry intrinsic 2', ['C', 110.0, 100.0, 0.0, 0.015, 0.2, 0], 10.0], ['partial repair probe 1', ['P', 110.0, 105.0, 0.0, 0.0, 0.1, 0], 0.0], ['partial repair probe 2', ['P', 110.0, 100.0, 0.05, 0.0, 0.2, 0], 0.0], ['normal control 1', ['C', 110.0, 105.0, 0.0, 0.03, 0.1, 1], 4.990959], ['normal control 2', ['P', 100.0, 100.0, 0.02, 0.03, 0.2, 7], 1.113996], ['normal control 3', ['P', 110.0, 105.0, 0.05, 0.015, 0.2, 7], 0.053891], ['normal control 4', ['C', 100.0, 95.0, 0.02, 0.0, 0.1, 30], 5.191459]]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression expiry intrinsic 1 | 0.0 | 5.0 | Failed |
| regression expiry intrinsic 2 | 0.0 | 15.0 | Failed |
| partial repair probe 1 | 0.0 | 0.0 | Passed |
| partial repair probe 2 | 0.0 | 0.0 | Passed |
| normal control 1 | 12.381799 | 12.381799 | Passed |
| normal control 2 | 1.243579 | 1.243579 | Passed |
| normal control 3 | 0.000151 | 0.000151 | Passed |
| normal control 4 | 3.25808 | 3.25808 | Passed |
SHA-256 / d04f134fb94a6340636cf352c0ae6dd025ac7ab45405169779a3d097a2ee8ce5
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(kind, S, K, r, q, sigma, days):
def N(x):
return 0.5 * (1 + math.erf(x / math.sqrt(2)))
T = days / 365
if days == 0:
return round(max(S - K, 0.0), 6)
d1 = (math.log(S / K) + (r - q + 0.5 * sigma ** 2) * T) / (sigma * math.sqrt(T))
d2 = d1 - sigma * math.sqrt(T)
if kind == 'C':
v = S * math.exp(-q * T) * N(d1) - K * math.exp(-r * T) * N(d2)
else:
v = K * math.exp(-r * T) * N(-d2) - S * math.exp(-q * T) * N(-d1)
return round(v, 6)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression expiry intrinsic 1', ['C', 100.0, 95.0, 0.0, 0.0, 0.2, 0], 5.0], ['regression expiry intrinsic 2', ['P', 90.0, 105.0, 0.05, 0.0, 0.35, 0], 15.0], ['partial repair probe 1', ['P', 110.0, 100.0, 0.02, 0.0, 0.2, 0], 0.0], ['partial repair probe 2', ['P', 110.0, 105.0, 0.02, 0.0, 0.35, 0], 0.0], ['normal control 1', ['C', 90.0, 105.0, 0.02, 0.015, 0.35, 730], 12.381799], ['normal control 2', ['P', 110.0, 100.0, 0.0, 0.015, 0.1, 365], 1.243579], ['normal control 3', ['P', 110.0, 105.0, 0.0, 0.0, 0.1, 7], 0.000151], ['normal control 4', ['C', 100.0, 100.0, 0.0, 0.015, 0.1, 365], 3.25808]], [['regression expiry intrinsic 1', ['C', 100.0, 95.0, 0.02, 0.015, 0.2, 0], 5.0], ['regression expiry intrinsic 2', ['P', 90.0, 95.0, 0.02, 0.015, 0.2, 0], 5.0], ['partial repair probe 1', ['P', 100.0, 95.0, 0.05, 0.03, 0.35, 0], 0.0], ['partial repair probe 2', ['P', 100.0, 95.0, 0.0, 0.03, 0.1, 0], 0.0], ['normal control 1', ['P', 90.0, 95.0, 0.0, 0.0, 0.2, 30], 5.491714], ['normal control 2', ['P', 110.0, 100.0, 0.02, 0.03, 0.2, 91], 0.989366], ['normal control 3', ['P', 110.0, 95.0, 0.02, 0.03, 0.2, 7], 0.0], ['normal control 4', ['P', 90.0, 95.0, 0.02, 0.0, 0.35, 182], 11.222351]], [['regression expiry intrinsic 1', ['P', 90.0, 100.0, 0.02, 0.0, 0.2, 0], 10.0], ['regression expiry intrinsic 2', ['P', 100.0, 105.0, 0.05, 0.0, 0.35, 0], 5.0], ['partial repair probe 1', ['P', 100.0, 95.0, 0.05, 0.0, 0.2, 0], 0.0], ['partial repair probe 2', ['P', 110.0, 100.0, 0.0, 0.0, 0.2, 0], 0.0], ['normal control 1', ['C', 90.0, 105.0, 0.02, 0.0, 0.2, 91], 0.287643], ['normal control 2', ['P', 110.0, 105.0, 0.02, 0.0, 0.35, 91], 5.027049], ['normal control 3', ['C', 90.0, 105.0, 0.02, 0.03, 0.1, 730], 0.68644], ['normal control 4', ['P', 110.0, 105.0, 0.05, 0.015, 0.1, 365], 1.21651]], [['regression expiry intrinsic 1', ['P', 90.0, 100.0, 0.05, 0.0, 0.2, 0], 10.0], ['regression expiry intrinsic 2', ['C', 110.0, 105.0, 0.05, 0.0, 0.2, 0], 5.0], ['partial repair probe 1', ['P', 100.0, 95.0, 0.0, 0.0, 0.1, 0], 0.0], ['partial repair probe 2', ['P', 110.0, 100.0, 0.05, 0.015, 0.2, 0], 0.0], ['normal control 1', ['C', 90.0, 105.0, 0.05, 0.03, 0.35, 7], 0.000965], ['normal control 2', ['P', 110.0, 100.0, 0.05, 0.03, 0.1, 1], 0.0], ['normal control 3', ['P', 100.0, 95.0, 0.05, 0.03, 0.1, 7], 3.1e-05], ['normal control 4', ['P', 90.0, 105.0, 0.0, 0.015, 0.2, 365], 18.471878]], [['regression expiry intrinsic 1', ['P', 90.0, 95.0, 0.02, 0.03, 0.2, 0], 5.0], ['regression expiry intrinsic 2', ['C', 110.0, 100.0, 0.0, 0.015, 0.2, 0], 10.0], ['partial repair probe 1', ['P', 110.0, 105.0, 0.0, 0.0, 0.1, 0], 0.0], ['partial repair probe 2', ['P', 110.0, 100.0, 0.05, 0.0, 0.2, 0], 0.0], ['normal control 1', ['C', 110.0, 105.0, 0.0, 0.03, 0.1, 1], 4.990959], ['normal control 2', ['P', 100.0, 100.0, 0.02, 0.03, 0.2, 7], 1.113996], ['normal control 3', ['P', 110.0, 105.0, 0.05, 0.015, 0.2, 7], 0.053891], ['normal control 4', ['C', 100.0, 95.0, 0.02, 0.0, 0.1, 30], 5.191459]]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression expiry intrinsic 1 | 5.0 | 5.0 | Passed |
| regression expiry intrinsic 2 | 0.0 | 15.0 | Failed |
| partial repair probe 1 | 10.0 | 0.0 | Failed |
| partial repair probe 2 | 5.0 | 0.0 | Failed |
| normal control 1 | 12.381799 | 12.381799 | Passed |
| normal control 2 | 1.243579 | 1.243579 | Passed |
| normal control 3 | 0.000151 | 0.000151 | Passed |
| normal control 4 | 3.25808 | 3.25808 | Passed |
SHA-256 / 39a55c780c59b74bbe561053c892c7342f02b41bd0707cf6efc57a288dc10c5f
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(kind, S, K, r, q, sigma, days):
def N(x):
return 0.5 * (1 + math.erf(x / math.sqrt(2)))
T = days / 365
if days == 0:
return round(max(S - K, 0.0) if kind == 'C' else max(K - S, 0.0), 6)
d1 = (math.log(S / K) + (r - q + 0.5 * sigma ** 2) * T) / (sigma * math.sqrt(T))
d2 = d1 - sigma * math.sqrt(T)
if kind == 'C':
v = S * math.exp(-q * T) * N(d1) - K * math.exp(-r * T) * N(d2)
else:
v = K * math.exp(-r * T) * N(-d2) - S * math.exp(-q * T) * N(-d1)
return round(v, 6)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression expiry intrinsic 1', ['C', 100.0, 95.0, 0.0, 0.0, 0.2, 0], 5.0], ['regression expiry intrinsic 2', ['P', 90.0, 105.0, 0.05, 0.0, 0.35, 0], 15.0], ['partial repair probe 1', ['P', 110.0, 100.0, 0.02, 0.0, 0.2, 0], 0.0], ['partial repair probe 2', ['P', 110.0, 105.0, 0.02, 0.0, 0.35, 0], 0.0], ['normal control 1', ['C', 90.0, 105.0, 0.02, 0.015, 0.35, 730], 12.381799], ['normal control 2', ['P', 110.0, 100.0, 0.0, 0.015, 0.1, 365], 1.243579], ['normal control 3', ['P', 110.0, 105.0, 0.0, 0.0, 0.1, 7], 0.000151], ['normal control 4', ['C', 100.0, 100.0, 0.0, 0.015, 0.1, 365], 3.25808]], [['regression expiry intrinsic 1', ['C', 100.0, 95.0, 0.02, 0.015, 0.2, 0], 5.0], ['regression expiry intrinsic 2', ['P', 90.0, 95.0, 0.02, 0.015, 0.2, 0], 5.0], ['partial repair probe 1', ['P', 100.0, 95.0, 0.05, 0.03, 0.35, 0], 0.0], ['partial repair probe 2', ['P', 100.0, 95.0, 0.0, 0.03, 0.1, 0], 0.0], ['normal control 1', ['P', 90.0, 95.0, 0.0, 0.0, 0.2, 30], 5.491714], ['normal control 2', ['P', 110.0, 100.0, 0.02, 0.03, 0.2, 91], 0.989366], ['normal control 3', ['P', 110.0, 95.0, 0.02, 0.03, 0.2, 7], 0.0], ['normal control 4', ['P', 90.0, 95.0, 0.02, 0.0, 0.35, 182], 11.222351]], [['regression expiry intrinsic 1', ['P', 90.0, 100.0, 0.02, 0.0, 0.2, 0], 10.0], ['regression expiry intrinsic 2', ['P', 100.0, 105.0, 0.05, 0.0, 0.35, 0], 5.0], ['partial repair probe 1', ['P', 100.0, 95.0, 0.05, 0.0, 0.2, 0], 0.0], ['partial repair probe 2', ['P', 110.0, 100.0, 0.0, 0.0, 0.2, 0], 0.0], ['normal control 1', ['C', 90.0, 105.0, 0.02, 0.0, 0.2, 91], 0.287643], ['normal control 2', ['P', 110.0, 105.0, 0.02, 0.0, 0.35, 91], 5.027049], ['normal control 3', ['C', 90.0, 105.0, 0.02, 0.03, 0.1, 730], 0.68644], ['normal control 4', ['P', 110.0, 105.0, 0.05, 0.015, 0.1, 365], 1.21651]], [['regression expiry intrinsic 1', ['P', 90.0, 100.0, 0.05, 0.0, 0.2, 0], 10.0], ['regression expiry intrinsic 2', ['C', 110.0, 105.0, 0.05, 0.0, 0.2, 0], 5.0], ['partial repair probe 1', ['P', 100.0, 95.0, 0.0, 0.0, 0.1, 0], 0.0], ['partial repair probe 2', ['P', 110.0, 100.0, 0.05, 0.015, 0.2, 0], 0.0], ['normal control 1', ['C', 90.0, 105.0, 0.05, 0.03, 0.35, 7], 0.000965], ['normal control 2', ['P', 110.0, 100.0, 0.05, 0.03, 0.1, 1], 0.0], ['normal control 3', ['P', 100.0, 95.0, 0.05, 0.03, 0.1, 7], 3.1e-05], ['normal control 4', ['P', 90.0, 105.0, 0.0, 0.015, 0.2, 365], 18.471878]], [['regression expiry intrinsic 1', ['P', 90.0, 95.0, 0.02, 0.03, 0.2, 0], 5.0], ['regression expiry intrinsic 2', ['C', 110.0, 100.0, 0.0, 0.015, 0.2, 0], 10.0], ['partial repair probe 1', ['P', 110.0, 105.0, 0.0, 0.0, 0.1, 0], 0.0], ['partial repair probe 2', ['P', 110.0, 100.0, 0.05, 0.0, 0.2, 0], 0.0], ['normal control 1', ['C', 110.0, 105.0, 0.0, 0.03, 0.1, 1], 4.990959], ['normal control 2', ['P', 100.0, 100.0, 0.02, 0.03, 0.2, 7], 1.113996], ['normal control 3', ['P', 110.0, 105.0, 0.05, 0.015, 0.2, 7], 0.053891], ['normal control 4', ['C', 100.0, 95.0, 0.02, 0.0, 0.1, 30], 5.191459]]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression expiry intrinsic 1 | 5.0 | 5.0 | Passed |
| regression expiry intrinsic 2 | 15.0 | 15.0 | Passed |
| partial repair probe 1 | 0.0 | 0.0 | Passed |
| partial repair probe 2 | 0.0 | 0.0 | Passed |
| normal control 1 | 12.381799 | 12.381799 | Passed |
| normal control 2 | 1.243579 | 1.243579 | Passed |
| normal control 3 | 0.000151 | 0.000151 | Passed |
| normal control 4 | 3.25808 | 3.25808 | Passed |
SHA-256 / 042b3ac074b38e50ad4a965a851356e9009490d4595dc18f8d89a45431a7e166
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.437175+00:00.
Case digest / a509c32280af81e857535e92812883c0442020fe28b46cb5e46fd23c142cdf87