米国株のオプション分析アプリ「SIGNUM HQ」を個人で作っています。銘柄画面に出している「予想変動(Implied Move)」の数字が、実は画面ごとに別の計算になっていたことに気づき、定義を1つに集約しました。その経緯と実装の要点を書きます。
何が起きたか
ある日、半導体株の予想変動が画面で「±9.0%」と出ていました。同じ時刻に、満期の近いATMストラドルの中値から手計算すると次の値でした。
ストラドル中値 83.42 ÷ 株価 1,053.98 = 7.9%
9.0%と7.9%で食い違います。原因を追うと、impliedMovePct という同じ名前のフィールドに、定義が3種類混ざっていました。
| どこで使っていたか | 実際の計算 |
|---|---|
| バッチ(ウォッチリスト・ポートフォリオ)とレポート生成 | (コールウォール − プットフロア) ÷ 株価。OI(建玉)の壁の間の「幅」 |
| 収集用Lambda・ダッシュボード | コールとプットで別々に選んだ最寄りの行使価格の「前日終値」の和 |
| スコア計算 | 株価±2%の窓の中で最初に見つかった契約。約定がなければ前日終値 |
画面もAIに渡すプロンプトも、これを全部「±x% 予想変動」として読んでいました。
一本化した定義
impliedMovePct = (ATMコール中値 + ATMプット中値) ÷ 現物 × 100
決めたルールは4つです。
- 満期は、基準日以上で最も近いもの。決算を見たいときは「決算後の最初の満期」を指定する(引け後発表なら翌日以降、寄り前発表なら当日以降)。
- ATMは、現物に最も近い行使価格を「1つ」選び、コールもプットも同じ行使価格にする。
- 価格は中値(bidとaskの真ん中)。リアルタイムの中値があればそれ(
basis: 'live')、なければ終値時点の中値(basis: 'eod')。 - 直近の約定価格(
day.close)は使わない。流動性の薄い行使価格では、中値と数十%ずれることがある。実測では、あるコールの前日の約定価格が62.5、中値が41.5でした。
実装の骨子
実際のコードはもう少し防御的ですが、考え方はこの程度です(簡略版)。
type Leg = { strike: number; mid: number | null };
export function atmStraddlePct(spot: number, calls: Leg[], puts: Leg[]) {
// 現物に近い順に行使価格を並べ、コールとプットの両方に中値がある最初の1つを使う
const strikes = [...new Set(calls.map((c) => c.strike))]
.sort((a, b) => Math.abs(a - spot) - Math.abs(b - spot))
.slice(0, 3);
for (const k of strikes) {
const c = calls.find((x) => x.strike === k)?.mid;
const p = puts.find((x) => x.strike === k)?.mid;
if (c != null && p != null) {
return { strike: k, straddle: +(c + p).toFixed(2), pct: +(((c + p) / spot) * 100).toFixed(1) };
}
}
return null; // 無ければ無し。前日の値などで埋めない
}
ポイントは最後の return null です。値が取れないときに別の基準の数字で穴埋めすると、また定義が混ざります。
名前で区別する
OIの壁の間の幅も有用な数字ですが、予想変動ではありません。そこで別名にしました。
wallRangePct = (コールウォール − プットフロア) ÷ 現物 × 100
こちらには「±」を付けず、「予想変動」「implied move」とも呼ばない、というルールにしています。定義が2つあること自体は問題ではなく、同じ名前で2つ呼ぶことが問題でした。
「いつの値か」を持ち回る
市場が閉まっている間はリアルタイムの中値がありません。以前の設計では終値時点の値を画面に載せず、予想変動の欄が全部「—」になっていました。今は終値時点の値も載せ、値の基準(liveかeod)とその値のセッション日付を一緒に返し、画面では「10/2終値」のような添え書きを付けます。数字には、いつの値かを持たせるのが基本だと考えています。
検証
- 定義の関数は副作用のない純関数にして、サーバーとクライアントの両方から同じものを呼ぶ
- 単体テストを付ける
- 手計算の値(冒頭の7.9%)と突き合わせて確認する
- 読み取り専用のAPIも用意して、外部のベンダー呼び出しやキャッシュ書き込みは行わない(保存済みの値がなければnullを返す)
アプリについて
SIGNUM HQ は、米国株のオプション(マックスペイン、ガンマエクスポージャー、コールウォールなど)とダークプール比率を、銘柄ごとにまとめて見られる無料アプリです。iPhoneとAndroidがあり、日本語・英語・韓国語に対応しています。投資の助言ではなく、公開データの整理です。
この記事を読んだ方向けのPRO 1か月無料クーポンもあります(広告なし+マイ銘柄100件。無料プランは5件)。PRO 1か月無料、以降は月額¥1,280で自動更新(いつでも解約可)・先着500名・10/30まで・iPhone。このリンクを開くとクーポンが適用されます(Qiita読者専用)。
Androidは同じリンクを開くと個人用コードが発行されます(30日間無料、以降は月額¥1,280で自動更新・30日以内に解約すれば0円・先着200名・10/30まで。Googleのお支払い方法の登録が必要)。