FA-61606 / Options payoff and settlement / Open access
Listed option expiration date calendar: quarterly expiries fall on weekend month ends · case 01
Quarter-end expiries on Saturdays or Sundays are not moved.
ROOT CAUSE
The quarterly branch returns the calendar month end before the business-day roll.
VERIFIED REPAIR
Apply the preceding business-day roll to quarterly dates as well.
Unsuccessful approach: Rolling only over weekends ignores quarter-end holidays.
Case contract
Inputs year, month, kind and holidays. Monthly expiry is the third Friday of the month; quarterly expiry is the last calendar day of the quarter-end month (Mar/Jun/Sep/Dec) containing the month. Either date rolls back to the preceding business day (weekday not in holidays) when it is not a business day. Return [y,m,d].
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 datetime
N = 1
observations = []
def solve(y, m, kind, holidays):
H = {datetime.date(*h) for h in holidays}
def biz(x):
return x.weekday() < 5 and x not in H
def mlen(yy, mm):
if mm == 2:
return 29 if (yy % 4 == 0 and yy % 100 != 0) or yy % 400 == 0 else 28
return 30 if mm in (4, 6, 9, 11) else 31
if kind == 'quarterly':
qm = ((m - 1) // 3 + 1) * 3
x = datetime.date(y, qm, mlen(y, qm))
return [x.year, x.month, x.day]
else:
first = datetime.date(y, m, 1)
offset = (4 - first.weekday()) % 7
x = first + datetime.timedelta(days=offset + 14)
while not biz(x):
x -= datetime.timedelta(days=1)
return [x.year, x.month, x.day]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression quarterly business day 1', [2021, 7, 'quarterly', [[2021, 9, 30]]], [2021, 9, 29]], ['regression quarterly business day 2', [2028, 10, 'quarterly', [[2028, 10, 20], [2028, 10, 19]]], [2028, 12, 29]], ['partial repair probe 1', [2030, 4, 'quarterly', [[2030, 6, 28]]], [2030, 6, 27]], ['partial repair probe 2', [2024, 1, 'quarterly', [[2024, 3, 29]]], [2024, 3, 28]], ['boundary control 1', [2024, 3, 'monthly', []], [2024, 3, 15]], ['boundary control 2', [2024, 6, 'monthly', []], [2024, 6, 21]], ['normal control 1', [2022, 12, 'monthly', []], [2022, 12, 16]], ['normal control 2', [2021, 4, 'monthly', []], [2021, 4, 16]]], [['regression quarterly business day 1', [2031, 4, 'quarterly', [[2031, 6, 30]]], [2031, 6, 27]], ['regression quarterly business day 2', [2027, 8, 'quarterly', [[2027, 9, 30]]], [2027, 9, 29]], ['partial repair probe 1', [2031, 6, 'quarterly', [[2031, 6, 30]]], [2031, 6, 27]], ['partial repair probe 2', [2027, 10, 'quarterly', [[2027, 10, 15], [2027, 10, 14], [2027, 12, 31]]], [2027, 12, 30]], ['boundary control 1', [2024, 6, 'monthly', []], [2024, 6, 21]], ['boundary control 2', [2024, 12, 'quarterly', []], [2024, 12, 31]], ['normal control 1', [2022, 1, 'monthly', [[2022, 1, 21]]], [2022, 1, 20]], ['normal control 2', [2023, 4, 'quarterly', [[2023, 4, 21]]], [2023, 6, 30]]], [['regression quarterly business day 1', [2028, 11, 'quarterly', [[2028, 12, 29]]], [2028, 12, 28]], ['regression quarterly business day 2', [2019, 5, 'quarterly', [[2019, 6, 27]]], [2019, 6, 28]], ['partial repair probe 1', [2021, 3, 'quarterly', [[2021, 3, 31]]], [2021, 3, 30]], ['partial repair probe 2', [2021, 9, 'quarterly', [[2021, 9, 17], [2021, 9, 16], [2021, 9, 30]]], [2021, 9, 29]], ['boundary control 1', [2024, 12, 'quarterly', []], [2024, 12, 31]], ['boundary control 2', [2024, 3, 'monthly', []], [2024, 3, 15]], ['normal control 1', [2024, 12, 'monthly', [[2024, 12, 20], [2024, 12, 19]]], [2024, 12, 18]], ['normal control 2', [2025, 11, 'monthly', []], [2025, 11, 21]]], [['regression quarterly business day 1', [2023, 7, 'quarterly', []], [2023, 9, 29]], ['regression quarterly business day 2', [2030, 6, 'quarterly', [[2030, 6, 21], [2030, 6, 20]]], [2030, 6, 28]], ['partial repair probe 1', [2019, 12, 'quarterly', [[2019, 12, 31]]], [2019, 12, 30]], ['partial repair probe 2', [2024, 6, 'quarterly', [[2024, 6, 28]]], [2024, 6, 27]], ['boundary control 1', [2024, 6, 'monthly', []], [2024, 6, 21]], ['boundary control 2', [2024, 12, 'quarterly', []], [2024, 12, 31]], ['normal control 1', [2020, 5, 'monthly', []], [2020, 5, 15]], ['normal control 2', [2023, 6, 'quarterly', [[2023, 6, 16]]], [2023, 6, 30]]], [['regression quarterly business day 1', [2029, 7, 'quarterly', [[2029, 7, 20], [2029, 7, 19]]], [2029, 9, 28]], ['regression quarterly business day 2', [2029, 4, 'quarterly', [[2029, 6, 29]]], [2029, 6, 28]], ['partial repair probe 1', [2031, 7, 'quarterly', [[2031, 9, 30]]], [2031, 9, 29]], ['partial repair probe 2', [2027, 5, 'quarterly', [[2027, 6, 30]]], [2027, 6, 29]], ['boundary control 1', [2024, 6, 'monthly', []], [2024, 6, 21]], ['boundary control 2', [2024, 3, 'monthly', []], [2024, 3, 15]], ['normal control 1', [2026, 10, 'monthly', [[2026, 10, 16], [2026, 10, 15]]], [2026, 10, 14]], ['normal control 2', [2028, 10, 'monthly', []], [2028, 10, 20]]]]
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 quarterly business day 1 | [2021, 9, 30] | [2021, 9, 29] | Failed |
| regression quarterly business day 2 | [2028, 12, 31] | [2028, 12, 29] | Failed |
| partial repair probe 1 | [2030, 6, 30] | [2030, 6, 27] | Failed |
| partial repair probe 2 | [2024, 3, 31] | [2024, 3, 28] | Failed |
| boundary control 1 | [2024, 3, 15] | [2024, 3, 15] | Passed |
| boundary control 2 | [2024, 6, 21] | [2024, 6, 21] | Passed |
| normal control 1 | [2022, 12, 16] | [2022, 12, 16] | Passed |
| normal control 2 | [2021, 4, 16] | [2021, 4, 16] | Passed |
SHA-256 / 91e1f3a8a7d14c0037a141e2470038142292e566cc8bc655157f07429c733a9d
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import datetime
N = 1
observations = []
def solve(y, m, kind, holidays):
H = {datetime.date(*h) for h in holidays}
def biz(x):
return x.weekday() < 5 and x not in H
def mlen(yy, mm):
if mm == 2:
return 29 if (yy % 4 == 0 and yy % 100 != 0) or yy % 400 == 0 else 28
return 30 if mm in (4, 6, 9, 11) else 31
if kind == 'quarterly':
qm = ((m - 1) // 3 + 1) * 3
x = datetime.date(y, qm, mlen(y, qm))
while x.weekday() >= 5:
x -= datetime.timedelta(days=1)
return [x.year, x.month, x.day]
else:
first = datetime.date(y, m, 1)
offset = (4 - first.weekday()) % 7
x = first + datetime.timedelta(days=offset + 14)
while not biz(x):
x -= datetime.timedelta(days=1)
return [x.year, x.month, x.day]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression quarterly business day 1', [2021, 7, 'quarterly', [[2021, 9, 30]]], [2021, 9, 29]], ['regression quarterly business day 2', [2028, 10, 'quarterly', [[2028, 10, 20], [2028, 10, 19]]], [2028, 12, 29]], ['partial repair probe 1', [2030, 4, 'quarterly', [[2030, 6, 28]]], [2030, 6, 27]], ['partial repair probe 2', [2024, 1, 'quarterly', [[2024, 3, 29]]], [2024, 3, 28]], ['boundary control 1', [2024, 3, 'monthly', []], [2024, 3, 15]], ['boundary control 2', [2024, 6, 'monthly', []], [2024, 6, 21]], ['normal control 1', [2022, 12, 'monthly', []], [2022, 12, 16]], ['normal control 2', [2021, 4, 'monthly', []], [2021, 4, 16]]], [['regression quarterly business day 1', [2031, 4, 'quarterly', [[2031, 6, 30]]], [2031, 6, 27]], ['regression quarterly business day 2', [2027, 8, 'quarterly', [[2027, 9, 30]]], [2027, 9, 29]], ['partial repair probe 1', [2031, 6, 'quarterly', [[2031, 6, 30]]], [2031, 6, 27]], ['partial repair probe 2', [2027, 10, 'quarterly', [[2027, 10, 15], [2027, 10, 14], [2027, 12, 31]]], [2027, 12, 30]], ['boundary control 1', [2024, 6, 'monthly', []], [2024, 6, 21]], ['boundary control 2', [2024, 12, 'quarterly', []], [2024, 12, 31]], ['normal control 1', [2022, 1, 'monthly', [[2022, 1, 21]]], [2022, 1, 20]], ['normal control 2', [2023, 4, 'quarterly', [[2023, 4, 21]]], [2023, 6, 30]]], [['regression quarterly business day 1', [2028, 11, 'quarterly', [[2028, 12, 29]]], [2028, 12, 28]], ['regression quarterly business day 2', [2019, 5, 'quarterly', [[2019, 6, 27]]], [2019, 6, 28]], ['partial repair probe 1', [2021, 3, 'quarterly', [[2021, 3, 31]]], [2021, 3, 30]], ['partial repair probe 2', [2021, 9, 'quarterly', [[2021, 9, 17], [2021, 9, 16], [2021, 9, 30]]], [2021, 9, 29]], ['boundary control 1', [2024, 12, 'quarterly', []], [2024, 12, 31]], ['boundary control 2', [2024, 3, 'monthly', []], [2024, 3, 15]], ['normal control 1', [2024, 12, 'monthly', [[2024, 12, 20], [2024, 12, 19]]], [2024, 12, 18]], ['normal control 2', [2025, 11, 'monthly', []], [2025, 11, 21]]], [['regression quarterly business day 1', [2023, 7, 'quarterly', []], [2023, 9, 29]], ['regression quarterly business day 2', [2030, 6, 'quarterly', [[2030, 6, 21], [2030, 6, 20]]], [2030, 6, 28]], ['partial repair probe 1', [2019, 12, 'quarterly', [[2019, 12, 31]]], [2019, 12, 30]], ['partial repair probe 2', [2024, 6, 'quarterly', [[2024, 6, 28]]], [2024, 6, 27]], ['boundary control 1', [2024, 6, 'monthly', []], [2024, 6, 21]], ['boundary control 2', [2024, 12, 'quarterly', []], [2024, 12, 31]], ['normal control 1', [2020, 5, 'monthly', []], [2020, 5, 15]], ['normal control 2', [2023, 6, 'quarterly', [[2023, 6, 16]]], [2023, 6, 30]]], [['regression quarterly business day 1', [2029, 7, 'quarterly', [[2029, 7, 20], [2029, 7, 19]]], [2029, 9, 28]], ['regression quarterly business day 2', [2029, 4, 'quarterly', [[2029, 6, 29]]], [2029, 6, 28]], ['partial repair probe 1', [2031, 7, 'quarterly', [[2031, 9, 30]]], [2031, 9, 29]], ['partial repair probe 2', [2027, 5, 'quarterly', [[2027, 6, 30]]], [2027, 6, 29]], ['boundary control 1', [2024, 6, 'monthly', []], [2024, 6, 21]], ['boundary control 2', [2024, 3, 'monthly', []], [2024, 3, 15]], ['normal control 1', [2026, 10, 'monthly', [[2026, 10, 16], [2026, 10, 15]]], [2026, 10, 14]], ['normal control 2', [2028, 10, 'monthly', []], [2028, 10, 20]]]]
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 quarterly business day 1 | [2021, 9, 30] | [2021, 9, 29] | Failed |
| regression quarterly business day 2 | [2028, 12, 29] | [2028, 12, 29] | Passed |
| partial repair probe 1 | [2030, 6, 28] | [2030, 6, 27] | Failed |
| partial repair probe 2 | [2024, 3, 29] | [2024, 3, 28] | Failed |
| boundary control 1 | [2024, 3, 15] | [2024, 3, 15] | Passed |
| boundary control 2 | [2024, 6, 21] | [2024, 6, 21] | Passed |
| normal control 1 | [2022, 12, 16] | [2022, 12, 16] | Passed |
| normal control 2 | [2021, 4, 16] | [2021, 4, 16] | Passed |
SHA-256 / fd56d1267e4f0efbeb5dbec5693cb8e09feec88f6c711121e0a15cc4eeeed903
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import datetime
N = 1
observations = []
def solve(y, m, kind, holidays):
H = {datetime.date(*h) for h in holidays}
def biz(x):
return x.weekday() < 5 and x not in H
def mlen(yy, mm):
if mm == 2:
return 29 if (yy % 4 == 0 and yy % 100 != 0) or yy % 400 == 0 else 28
return 30 if mm in (4, 6, 9, 11) else 31
if kind == 'quarterly':
qm = ((m - 1) // 3 + 1) * 3
x = datetime.date(y, qm, mlen(y, qm))
else:
first = datetime.date(y, m, 1)
offset = (4 - first.weekday()) % 7
x = first + datetime.timedelta(days=offset + 14)
while not biz(x):
x -= datetime.timedelta(days=1)
return [x.year, x.month, x.day]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression quarterly business day 1', [2021, 7, 'quarterly', [[2021, 9, 30]]], [2021, 9, 29]], ['regression quarterly business day 2', [2028, 10, 'quarterly', [[2028, 10, 20], [2028, 10, 19]]], [2028, 12, 29]], ['partial repair probe 1', [2030, 4, 'quarterly', [[2030, 6, 28]]], [2030, 6, 27]], ['partial repair probe 2', [2024, 1, 'quarterly', [[2024, 3, 29]]], [2024, 3, 28]], ['boundary control 1', [2024, 3, 'monthly', []], [2024, 3, 15]], ['boundary control 2', [2024, 6, 'monthly', []], [2024, 6, 21]], ['normal control 1', [2022, 12, 'monthly', []], [2022, 12, 16]], ['normal control 2', [2021, 4, 'monthly', []], [2021, 4, 16]]], [['regression quarterly business day 1', [2031, 4, 'quarterly', [[2031, 6, 30]]], [2031, 6, 27]], ['regression quarterly business day 2', [2027, 8, 'quarterly', [[2027, 9, 30]]], [2027, 9, 29]], ['partial repair probe 1', [2031, 6, 'quarterly', [[2031, 6, 30]]], [2031, 6, 27]], ['partial repair probe 2', [2027, 10, 'quarterly', [[2027, 10, 15], [2027, 10, 14], [2027, 12, 31]]], [2027, 12, 30]], ['boundary control 1', [2024, 6, 'monthly', []], [2024, 6, 21]], ['boundary control 2', [2024, 12, 'quarterly', []], [2024, 12, 31]], ['normal control 1', [2022, 1, 'monthly', [[2022, 1, 21]]], [2022, 1, 20]], ['normal control 2', [2023, 4, 'quarterly', [[2023, 4, 21]]], [2023, 6, 30]]], [['regression quarterly business day 1', [2028, 11, 'quarterly', [[2028, 12, 29]]], [2028, 12, 28]], ['regression quarterly business day 2', [2019, 5, 'quarterly', [[2019, 6, 27]]], [2019, 6, 28]], ['partial repair probe 1', [2021, 3, 'quarterly', [[2021, 3, 31]]], [2021, 3, 30]], ['partial repair probe 2', [2021, 9, 'quarterly', [[2021, 9, 17], [2021, 9, 16], [2021, 9, 30]]], [2021, 9, 29]], ['boundary control 1', [2024, 12, 'quarterly', []], [2024, 12, 31]], ['boundary control 2', [2024, 3, 'monthly', []], [2024, 3, 15]], ['normal control 1', [2024, 12, 'monthly', [[2024, 12, 20], [2024, 12, 19]]], [2024, 12, 18]], ['normal control 2', [2025, 11, 'monthly', []], [2025, 11, 21]]], [['regression quarterly business day 1', [2023, 7, 'quarterly', []], [2023, 9, 29]], ['regression quarterly business day 2', [2030, 6, 'quarterly', [[2030, 6, 21], [2030, 6, 20]]], [2030, 6, 28]], ['partial repair probe 1', [2019, 12, 'quarterly', [[2019, 12, 31]]], [2019, 12, 30]], ['partial repair probe 2', [2024, 6, 'quarterly', [[2024, 6, 28]]], [2024, 6, 27]], ['boundary control 1', [2024, 6, 'monthly', []], [2024, 6, 21]], ['boundary control 2', [2024, 12, 'quarterly', []], [2024, 12, 31]], ['normal control 1', [2020, 5, 'monthly', []], [2020, 5, 15]], ['normal control 2', [2023, 6, 'quarterly', [[2023, 6, 16]]], [2023, 6, 30]]], [['regression quarterly business day 1', [2029, 7, 'quarterly', [[2029, 7, 20], [2029, 7, 19]]], [2029, 9, 28]], ['regression quarterly business day 2', [2029, 4, 'quarterly', [[2029, 6, 29]]], [2029, 6, 28]], ['partial repair probe 1', [2031, 7, 'quarterly', [[2031, 9, 30]]], [2031, 9, 29]], ['partial repair probe 2', [2027, 5, 'quarterly', [[2027, 6, 30]]], [2027, 6, 29]], ['boundary control 1', [2024, 6, 'monthly', []], [2024, 6, 21]], ['boundary control 2', [2024, 3, 'monthly', []], [2024, 3, 15]], ['normal control 1', [2026, 10, 'monthly', [[2026, 10, 16], [2026, 10, 15]]], [2026, 10, 14]], ['normal control 2', [2028, 10, 'monthly', []], [2028, 10, 20]]]]
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 quarterly business day 1 | [2021, 9, 29] | [2021, 9, 29] | Passed |
| regression quarterly business day 2 | [2028, 12, 29] | [2028, 12, 29] | Passed |
| partial repair probe 1 | [2030, 6, 27] | [2030, 6, 27] | Passed |
| partial repair probe 2 | [2024, 3, 28] | [2024, 3, 28] | Passed |
| boundary control 1 | [2024, 3, 15] | [2024, 3, 15] | Passed |
| boundary control 2 | [2024, 6, 21] | [2024, 6, 21] | Passed |
| normal control 1 | [2022, 12, 16] | [2022, 12, 16] | Passed |
| normal control 2 | [2021, 4, 16] | [2021, 4, 16] | Passed |
SHA-256 / 2671a80121d347f8773b8cd14c31313bddd5a78c309b675c7244d54bcefcf7fa
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.788463+00:00.
Case digest / 2a75416f97e221cdb976d5304e3d985e3193356fb5927f7e2cedfcbdf35b21f6