同じ満期のオプション建玉から、満期時の本源的価値の合計が最小になる候補価格を求める、小さな検証用コードです。AIの支援で下書きし、掲載コードはローカルで実行検証しています。本番アプリの実装そのものではありません。
価格を S、行使価格を K とすると、コール側は max(S−K, 0)、プット側は max(K−S, 0)。それぞれに建玉を掛けて合計し、候補価格を比較します。
ここでは同一銘柄・同一満期・同一受渡条件の標準契約を入力前提とし、共通の正の契約倍率は最小点を変えないため省略します。調整契約や異なる倍率を混ぜる用途には使いません。満期・受渡条件を絞ったつもりでも、重複行があると二重計上になります。欠損OIをゼロに変換してから計算する処理も避けます。
from decimal import Decimal
def max_pain(rows):
"""One expiry, standard unadjusted contracts, identical multiplier.
Synthetic normalized input only; unknown OI is an error.
"""
if not rows:
raise ValueError("empty chain")
normalized = []
seen = set()
series = set()
for r in rows:
k = Decimal(str(r["strike"]))
if not k.is_finite() or k <= 0:
raise ValueError("bad strike")
if r["right"] not in ("C", "P"):
raise ValueError("bad right")
oi = r["oi"]
if type(oi) is not int or oi < 0:
raise ValueError("unknown or bad OI")
group = (r["symbol"], r["expiry"], r["deliverable"])
series.add(group)
contract = group + (r["right"], k)
if contract in seen:
raise ValueError("duplicate contract")
seen.add(contract)
normalized.append((k, r["right"], oi))
if len(series) != 1:
raise ValueError("mixed chains")
if sum(oi for _, _, oi in normalized) == 0:
raise ValueError("no open interest")
losses = {}
for s in sorted({k for k, _, _ in normalized}):
losses[s] = sum(
(max(s-k, Decimal(0)) if right == "C"
else max(k-s, Decimal(0))) * oi
for k, right, oi in normalized
)
minimum = min(losses.values())
return [s for s, loss in losses.items() if loss == minimum]
# All values below are invented fixtures, not market observations.
base = dict(symbol="TEST", expiry="2099-01-01", deliverable="standard")
rows = [dict(base, strike="100", right="C", oi=1),
dict(base, strike="100", right="P", oi=1)]
assert max_pain(rows) == [Decimal("100")]
print(max_pain(rows))
候補は入力に含まれる行使価格です。最小値が同じ候補はすべて返します。行使価格の間で合計が平らになる場合は、その区間全体が最小になり得ます。このコードは区間推定をせず、同点の候補を返すだけです。
計算量は候補数×契約数。まず正しい入力と同点の扱いを確認するための単純な実装です。高速化するなら区分線形関数の傾きを更新する方法もありますが、ここでは検証しやすさを優先しました。
これは建玉を固定した集計であり、価格がそこへ向かう確率や利益を計算するモデルではありません。建玉から参加者の保有方向やヘッジも確定できません。
制作している米国株データアプリ:SIGNUM HQ
https://www.signumhq.com/app?from=qiita_1017
参考
- OCC/OIC:オプション価格の基礎(本源的価値) https://www.optionseducation.org/optionsoverview/options-pricing
- OCC/OIC:建玉(OI)の定義 https://www.optionseducation.org/referencelibrary/faq/general-information