FAILURE MAP
← Case archive

FA-61441 / Options payoff and settlement / Open access

Discretely monitored barrier option payoff: an observation exactly at the barrier is not a hit · case 01

Paths that touch the barrier level exactly are treated as never touching it.

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

ROOT CAUSE

Both barrier comparisons are strict.

VERIFIED REPAIR

Treat an observation equal to the barrier as a hit.

Unsuccessful approach: Fixing only the up-barrier comparison leaves down barriers strict.

Case contract

Inputs kind (up/down, in/out, call/put), observed path including initial and final price, strike, barrier and rebate. The barrier is hit if any observation is >= barrier (up) or <= barrier (down). Knock-out: rebate if hit else vanilla on the final price. Knock-in: vanilla if hit else rebate. 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

N = 1
observations = []
def solve(kind, path, strike, barrier, rebate):
    up = kind.startswith('up')
    hit = any(p > barrier for p in path) if up else any(p < barrier for p in path)
    final = path[-1]
    vanilla = max(final - strike, 0) if kind.endswith('call') else max(strike - final, 0)
    if '-out-' in kind:
        pay = rebate if hit else vanilla
    else:
        pay = vanilla if hit else rebate
    return round(pay, 6)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression touch inclusivity 1', ['down-in-put', [100.0, 90.0, 90.0, 90.0, 94.5], 95, 90.0, 1.5], 0.5], ['regression touch inclusivity 2', ['up-out-call', [100.0, 90.0, 94.5], 95, 100.0, 1.5], 1.5], ['partial repair probe 1', ['down-in-call', [100.0, 110.0, 115.5, 115.5, 115.5], 105, 100.0, 0.0], 10.5], ['partial repair probe 2', ['down-in-put', [100.0, 93.0, 102.3, 97.18, 87.46, 96.21], 105, 87.46, 0.0], 8.79], ['boundary control 1', ['down-in-put', [100.0, 95.0], 100, 90.0, 1.0], 1.0], ['normal control 1', ['up-in-call', [100.0, 105.0, 113.4, 124.74], 105, 113.4, 3.0], 19.74], ['normal control 2', ['down-in-call', [100.0, 105.0, 105.0, 110.25], 100, 80.0, 0.0], 0.0], ['normal control 3', ['up-in-call', [100.0, 100.0, 100.0, 93.0], 105, 115.0, 0.0], 0.0]], [['regression touch inclusivity 1', ['up-out-put', [100.0, 110.0, 104.5, 97.19, 90.39, 84.06, 79.86], 105, 110.0, 1.5], 1.5], ['regression touch inclusivity 2', ['up-out-put', [100.0, 90.0, 99.0, 89.1, 84.64, 76.18, 70.85, 67.31], 105, 100.0, 0.0], 0.0], ['partial repair probe 1', ['down-out-put', [100.0, 90.0, 81.0, 76.95, 71.56, 77.28, 69.55, 73.03], 100, 69.55, 1.5], 1.5], ['partial repair probe 2', ['down-out-put', [100.0, 108.0, 100.44, 110.48, 119.32], 105, 100.0, 1.5], 1.5], ['boundary control 1', ['down-in-put', [100.0, 95.0], 100, 90.0, 1.0], 1.0], ['normal control 1', ['down-out-put', [100.0, 100.0, 100.0, 90.0, 94.5, 102.06, 112.27, 123.5], 100, 80.0, 1.5], 0], ['normal control 2', ['up-out-call', [100.0, 110.0, 121.0, 130.68], 100, 95.0, 3.0], 3.0], ['normal control 3', ['down-in-put', [100.0, 108.0, 118.8], 95, 80.0, 3.0], 3.0]], [['regression touch inclusivity 1', ['down-in-put', [100.0, 108.0, 116.64, 125.97, 138.57, 124.71], 100, 100.0, 3.0], 0], ['regression touch inclusivity 2', ['down-in-call', [100.0, 105.0, 115.5, 109.72, 98.75, 93.81, 93.81], 95, 93.81, 1.5], 0], ['partial repair probe 1', ['down-in-put', [100.0, 90.0, 83.7, 79.52, 75.54, 75.54], 105, 75.54, 1.5], 29.46], ['partial repair probe 2', ['down-in-put', [100.0, 95.0, 88.35], 95, 88.35, 0.0], 6.65], ['boundary control 1', ['down-in-put', [100.0, 95.0], 100, 90.0, 1.0], 1.0], ['normal control 1', ['down-out-put', [100.0, 110.0, 115.5, 124.74, 130.98, 117.88], 105, 90.0, 0.0], 0], ['normal control 2', ['up-in-call', [100.0, 95.0, 95.0, 102.6, 97.47, 105.27, 97.9], 105, 115.0, 1.5], 1.5], ['normal control 3', ['up-out-call', [100.0, 93.0, 93.0, 102.3, 107.42], 95, 110.0, 0.0], 12.42]], [['regression touch inclusivity 1', ['up-out-call', [100.0, 110.0, 110.0, 99.0], 105, 110.0, 3.0], 3.0], ['regression touch inclusivity 2', ['up-in-call', [100.0, 90.0, 81.0], 95, 100.0, 3.0], 0], ['partial repair probe 1', ['down-out-put', [100.0, 100.0, 93.0], 95, 93.0, 3.0], 3.0], ['partial repair probe 2', ['down-in-call', [100.0, 90.0, 99.0, 99.0, 99.0, 92.07, 92.07], 105, 90.0, 3.0], 0], ['boundary control 1', ['down-in-put', [100.0, 95.0], 100, 90.0, 1.0], 1.0], ['normal control 1', ['up-out-call', [100.0, 93.0, 93.0, 83.7, 87.89], 105, 120.0, 1.5], 0], ['normal control 2', ['down-in-call', [100.0, 93.0, 83.7, 83.7, 77.84, 77.84, 72.39], 100, 105.0, 0.0], 0], ['normal control 3', ['down-out-put', [100.0, 100.0, 95.0, 95.0, 88.35], 100, 95.0, 0.0], 0.0]], [['regression touch inclusivity 1', ['down-out-put', [100.0, 93.0, 83.7], 105, 83.7, 3.0], 3.0], ['regression touch inclusivity 2', ['down-in-call', [100.0, 110.0, 121.0], 95, 100.0, 0.0], 26.0], ['partial repair probe 1', ['down-in-put', [100.0, 108.0, 102.6, 112.86, 107.22, 115.8, 125.06], 105, 100.0, 3.0], 0], ['partial repair probe 2', ['down-out-put', [100.0, 90.0, 94.5, 102.06, 102.06, 107.16, 117.88], 95, 90.0, 3.0], 3.0], ['boundary control 1', ['down-in-put', [100.0, 95.0], 100, 90.0, 1.0], 1.0], ['normal control 1', ['down-out-put', [100.0, 90.0, 99.0, 89.1, 89.1], 105, 105.0, 3.0], 3.0], ['normal control 2', ['up-out-call', [100.0, 108.0, 100.44], 100, 100.0, 1.5], 1.5], ['normal control 3', ['up-out-put', [100.0, 90.0, 97.2, 92.34, 85.88, 77.29], 105, 120.0, 3.0], 27.71]]]
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 touch inclusivity 11.50.5Failed
regression touch inclusivity 201.5Failed
partial repair probe 10.010.5Failed
partial repair probe 20.08.79Failed
boundary control 11.01.0Passed
normal control 119.7419.74Passed
normal control 20.00.0Passed
normal control 30.00.0Passed

SHA-256 / 9354b5346f9841d9687b0dcadc2523166de40f60a529af6aeacf71e084435bfc

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(kind, path, strike, barrier, rebate):
    up = kind.startswith('up')
    hit = any(p >= barrier for p in path) if up else any(p < barrier for p in path)
    final = path[-1]
    vanilla = max(final - strike, 0) if kind.endswith('call') else max(strike - final, 0)
    if '-out-' in kind:
        pay = rebate if hit else vanilla
    else:
        pay = vanilla if hit else rebate
    return round(pay, 6)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression touch inclusivity 1', ['down-in-put', [100.0, 90.0, 90.0, 90.0, 94.5], 95, 90.0, 1.5], 0.5], ['regression touch inclusivity 2', ['up-out-call', [100.0, 90.0, 94.5], 95, 100.0, 1.5], 1.5], ['partial repair probe 1', ['down-in-call', [100.0, 110.0, 115.5, 115.5, 115.5], 105, 100.0, 0.0], 10.5], ['partial repair probe 2', ['down-in-put', [100.0, 93.0, 102.3, 97.18, 87.46, 96.21], 105, 87.46, 0.0], 8.79], ['boundary control 1', ['down-in-put', [100.0, 95.0], 100, 90.0, 1.0], 1.0], ['normal control 1', ['up-in-call', [100.0, 105.0, 113.4, 124.74], 105, 113.4, 3.0], 19.74], ['normal control 2', ['down-in-call', [100.0, 105.0, 105.0, 110.25], 100, 80.0, 0.0], 0.0], ['normal control 3', ['up-in-call', [100.0, 100.0, 100.0, 93.0], 105, 115.0, 0.0], 0.0]], [['regression touch inclusivity 1', ['up-out-put', [100.0, 110.0, 104.5, 97.19, 90.39, 84.06, 79.86], 105, 110.0, 1.5], 1.5], ['regression touch inclusivity 2', ['up-out-put', [100.0, 90.0, 99.0, 89.1, 84.64, 76.18, 70.85, 67.31], 105, 100.0, 0.0], 0.0], ['partial repair probe 1', ['down-out-put', [100.0, 90.0, 81.0, 76.95, 71.56, 77.28, 69.55, 73.03], 100, 69.55, 1.5], 1.5], ['partial repair probe 2', ['down-out-put', [100.0, 108.0, 100.44, 110.48, 119.32], 105, 100.0, 1.5], 1.5], ['boundary control 1', ['down-in-put', [100.0, 95.0], 100, 90.0, 1.0], 1.0], ['normal control 1', ['down-out-put', [100.0, 100.0, 100.0, 90.0, 94.5, 102.06, 112.27, 123.5], 100, 80.0, 1.5], 0], ['normal control 2', ['up-out-call', [100.0, 110.0, 121.0, 130.68], 100, 95.0, 3.0], 3.0], ['normal control 3', ['down-in-put', [100.0, 108.0, 118.8], 95, 80.0, 3.0], 3.0]], [['regression touch inclusivity 1', ['down-in-put', [100.0, 108.0, 116.64, 125.97, 138.57, 124.71], 100, 100.0, 3.0], 0], ['regression touch inclusivity 2', ['down-in-call', [100.0, 105.0, 115.5, 109.72, 98.75, 93.81, 93.81], 95, 93.81, 1.5], 0], ['partial repair probe 1', ['down-in-put', [100.0, 90.0, 83.7, 79.52, 75.54, 75.54], 105, 75.54, 1.5], 29.46], ['partial repair probe 2', ['down-in-put', [100.0, 95.0, 88.35], 95, 88.35, 0.0], 6.65], ['boundary control 1', ['down-in-put', [100.0, 95.0], 100, 90.0, 1.0], 1.0], ['normal control 1', ['down-out-put', [100.0, 110.0, 115.5, 124.74, 130.98, 117.88], 105, 90.0, 0.0], 0], ['normal control 2', ['up-in-call', [100.0, 95.0, 95.0, 102.6, 97.47, 105.27, 97.9], 105, 115.0, 1.5], 1.5], ['normal control 3', ['up-out-call', [100.0, 93.0, 93.0, 102.3, 107.42], 95, 110.0, 0.0], 12.42]], [['regression touch inclusivity 1', ['up-out-call', [100.0, 110.0, 110.0, 99.0], 105, 110.0, 3.0], 3.0], ['regression touch inclusivity 2', ['up-in-call', [100.0, 90.0, 81.0], 95, 100.0, 3.0], 0], ['partial repair probe 1', ['down-out-put', [100.0, 100.0, 93.0], 95, 93.0, 3.0], 3.0], ['partial repair probe 2', ['down-in-call', [100.0, 90.0, 99.0, 99.0, 99.0, 92.07, 92.07], 105, 90.0, 3.0], 0], ['boundary control 1', ['down-in-put', [100.0, 95.0], 100, 90.0, 1.0], 1.0], ['normal control 1', ['up-out-call', [100.0, 93.0, 93.0, 83.7, 87.89], 105, 120.0, 1.5], 0], ['normal control 2', ['down-in-call', [100.0, 93.0, 83.7, 83.7, 77.84, 77.84, 72.39], 100, 105.0, 0.0], 0], ['normal control 3', ['down-out-put', [100.0, 100.0, 95.0, 95.0, 88.35], 100, 95.0, 0.0], 0.0]], [['regression touch inclusivity 1', ['down-out-put', [100.0, 93.0, 83.7], 105, 83.7, 3.0], 3.0], ['regression touch inclusivity 2', ['down-in-call', [100.0, 110.0, 121.0], 95, 100.0, 0.0], 26.0], ['partial repair probe 1', ['down-in-put', [100.0, 108.0, 102.6, 112.86, 107.22, 115.8, 125.06], 105, 100.0, 3.0], 0], ['partial repair probe 2', ['down-out-put', [100.0, 90.0, 94.5, 102.06, 102.06, 107.16, 117.88], 95, 90.0, 3.0], 3.0], ['boundary control 1', ['down-in-put', [100.0, 95.0], 100, 90.0, 1.0], 1.0], ['normal control 1', ['down-out-put', [100.0, 90.0, 99.0, 89.1, 89.1], 105, 105.0, 3.0], 3.0], ['normal control 2', ['up-out-call', [100.0, 108.0, 100.44], 100, 100.0, 1.5], 1.5], ['normal control 3', ['up-out-put', [100.0, 90.0, 97.2, 92.34, 85.88, 77.29], 105, 120.0, 3.0], 27.71]]]
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 touch inclusivity 11.50.5Failed
regression touch inclusivity 21.51.5Passed
partial repair probe 10.010.5Failed
partial repair probe 20.08.79Failed
boundary control 11.01.0Passed
normal control 119.7419.74Passed
normal control 20.00.0Passed
normal control 30.00.0Passed

SHA-256 / fb52f5b3dc57612878fbd464108e547e27beaccf8cd949a73fa9eb425c307495

3 / The verified repair

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

N = 1
observations = []
def solve(kind, path, strike, barrier, rebate):
    up = kind.startswith('up')
    hit = any(p >= barrier for p in path) if up else any(p <= barrier for p in path)
    final = path[-1]
    vanilla = max(final - strike, 0) if kind.endswith('call') else max(strike - final, 0)
    if '-out-' in kind:
        pay = rebate if hit else vanilla
    else:
        pay = vanilla if hit else rebate
    return round(pay, 6)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression touch inclusivity 1', ['down-in-put', [100.0, 90.0, 90.0, 90.0, 94.5], 95, 90.0, 1.5], 0.5], ['regression touch inclusivity 2', ['up-out-call', [100.0, 90.0, 94.5], 95, 100.0, 1.5], 1.5], ['partial repair probe 1', ['down-in-call', [100.0, 110.0, 115.5, 115.5, 115.5], 105, 100.0, 0.0], 10.5], ['partial repair probe 2', ['down-in-put', [100.0, 93.0, 102.3, 97.18, 87.46, 96.21], 105, 87.46, 0.0], 8.79], ['boundary control 1', ['down-in-put', [100.0, 95.0], 100, 90.0, 1.0], 1.0], ['normal control 1', ['up-in-call', [100.0, 105.0, 113.4, 124.74], 105, 113.4, 3.0], 19.74], ['normal control 2', ['down-in-call', [100.0, 105.0, 105.0, 110.25], 100, 80.0, 0.0], 0.0], ['normal control 3', ['up-in-call', [100.0, 100.0, 100.0, 93.0], 105, 115.0, 0.0], 0.0]], [['regression touch inclusivity 1', ['up-out-put', [100.0, 110.0, 104.5, 97.19, 90.39, 84.06, 79.86], 105, 110.0, 1.5], 1.5], ['regression touch inclusivity 2', ['up-out-put', [100.0, 90.0, 99.0, 89.1, 84.64, 76.18, 70.85, 67.31], 105, 100.0, 0.0], 0.0], ['partial repair probe 1', ['down-out-put', [100.0, 90.0, 81.0, 76.95, 71.56, 77.28, 69.55, 73.03], 100, 69.55, 1.5], 1.5], ['partial repair probe 2', ['down-out-put', [100.0, 108.0, 100.44, 110.48, 119.32], 105, 100.0, 1.5], 1.5], ['boundary control 1', ['down-in-put', [100.0, 95.0], 100, 90.0, 1.0], 1.0], ['normal control 1', ['down-out-put', [100.0, 100.0, 100.0, 90.0, 94.5, 102.06, 112.27, 123.5], 100, 80.0, 1.5], 0], ['normal control 2', ['up-out-call', [100.0, 110.0, 121.0, 130.68], 100, 95.0, 3.0], 3.0], ['normal control 3', ['down-in-put', [100.0, 108.0, 118.8], 95, 80.0, 3.0], 3.0]], [['regression touch inclusivity 1', ['down-in-put', [100.0, 108.0, 116.64, 125.97, 138.57, 124.71], 100, 100.0, 3.0], 0], ['regression touch inclusivity 2', ['down-in-call', [100.0, 105.0, 115.5, 109.72, 98.75, 93.81, 93.81], 95, 93.81, 1.5], 0], ['partial repair probe 1', ['down-in-put', [100.0, 90.0, 83.7, 79.52, 75.54, 75.54], 105, 75.54, 1.5], 29.46], ['partial repair probe 2', ['down-in-put', [100.0, 95.0, 88.35], 95, 88.35, 0.0], 6.65], ['boundary control 1', ['down-in-put', [100.0, 95.0], 100, 90.0, 1.0], 1.0], ['normal control 1', ['down-out-put', [100.0, 110.0, 115.5, 124.74, 130.98, 117.88], 105, 90.0, 0.0], 0], ['normal control 2', ['up-in-call', [100.0, 95.0, 95.0, 102.6, 97.47, 105.27, 97.9], 105, 115.0, 1.5], 1.5], ['normal control 3', ['up-out-call', [100.0, 93.0, 93.0, 102.3, 107.42], 95, 110.0, 0.0], 12.42]], [['regression touch inclusivity 1', ['up-out-call', [100.0, 110.0, 110.0, 99.0], 105, 110.0, 3.0], 3.0], ['regression touch inclusivity 2', ['up-in-call', [100.0, 90.0, 81.0], 95, 100.0, 3.0], 0], ['partial repair probe 1', ['down-out-put', [100.0, 100.0, 93.0], 95, 93.0, 3.0], 3.0], ['partial repair probe 2', ['down-in-call', [100.0, 90.0, 99.0, 99.0, 99.0, 92.07, 92.07], 105, 90.0, 3.0], 0], ['boundary control 1', ['down-in-put', [100.0, 95.0], 100, 90.0, 1.0], 1.0], ['normal control 1', ['up-out-call', [100.0, 93.0, 93.0, 83.7, 87.89], 105, 120.0, 1.5], 0], ['normal control 2', ['down-in-call', [100.0, 93.0, 83.7, 83.7, 77.84, 77.84, 72.39], 100, 105.0, 0.0], 0], ['normal control 3', ['down-out-put', [100.0, 100.0, 95.0, 95.0, 88.35], 100, 95.0, 0.0], 0.0]], [['regression touch inclusivity 1', ['down-out-put', [100.0, 93.0, 83.7], 105, 83.7, 3.0], 3.0], ['regression touch inclusivity 2', ['down-in-call', [100.0, 110.0, 121.0], 95, 100.0, 0.0], 26.0], ['partial repair probe 1', ['down-in-put', [100.0, 108.0, 102.6, 112.86, 107.22, 115.8, 125.06], 105, 100.0, 3.0], 0], ['partial repair probe 2', ['down-out-put', [100.0, 90.0, 94.5, 102.06, 102.06, 107.16, 117.88], 95, 90.0, 3.0], 3.0], ['boundary control 1', ['down-in-put', [100.0, 95.0], 100, 90.0, 1.0], 1.0], ['normal control 1', ['down-out-put', [100.0, 90.0, 99.0, 89.1, 89.1], 105, 105.0, 3.0], 3.0], ['normal control 2', ['up-out-call', [100.0, 108.0, 100.44], 100, 100.0, 1.5], 1.5], ['normal control 3', ['up-out-put', [100.0, 90.0, 97.2, 92.34, 85.88, 77.29], 105, 120.0, 3.0], 27.71]]]
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 touch inclusivity 10.50.5Passed
regression touch inclusivity 21.51.5Passed
partial repair probe 110.510.5Passed
partial repair probe 28.798.79Passed
boundary control 11.01.0Passed
normal control 119.7419.74Passed
normal control 20.00.0Passed
normal control 30.00.0Passed

SHA-256 / e0247e08ec622d09bd24781b1737498a4ae20a555a5c6264ba1052c21ecfa584

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

Case digest / f3ecbf06fc738b5cf0ffe3a245c5b4f2cd0a2ce8c3fce3c33b73a62dee98bd27