INCIDENT REPORT · 2026-04-30 (JST 1日)

介入級円高に飲まれた、
9 時間と -140.6 pips。

USD/JPY が 9 時間で -3.65 円(160.34 → 156.69)の急変。 bot は BUY を 3 連発で発射し、全件 SL ヒットで -140.6 pips(-3,832円)。 原資割れ。

この事故の本質は、相場の急変ではなく 「実装はあるのに繋がっていなかった」リスクゲートの総崩れ。 本レポートは、当日の価格推移・トレード明細・機能不全だった防壁・12 時間以内の根本対策を、加工なく公開する。

01 · INCIDENT IMPACT

事故のインパクト

集計期間: 2026-04-30 (JST 1 日 / 決済済みのみ)。 4/29 終盤エントリーの持ち越し決済 (TP +43.6 / TIMEOUT +12.8) を冒頭に含み、その後 3 連 SL で原資割れ。

CLOSED TRADES 5 勝 2 / 負 3
WIN RATE 40.0% 運用開始以来の最低水準
PIPS -84.2 3 連 SL で -140.6、冒頭の TP/TIMEOUT で +56.4 を確保
PNL JPY -2,242 残高 32,619 円 → 28,476 円 (-12.7%)
事故の構造

原因は 急変動そのもの ではなく、 防壁の総崩れ だった。

介入級の円高は確かに不可避の外部要因。だが本来そなえているべき複数のリスクゲートが 「実装はあるのに繋がっていない」「死んだフラグ」「単発予算超過 halt の不在」 という形で軒並み機能不全だった。1 件で予算 16% 超過する SL を 3 連発で許してしまった設計責任が、急変動と重なって最大級の単日損失を生んだ。

02 · PRICE COLLAPSE

価格チャート — 9 時間で -3.65 円

2026-04-29 00:00 〜 2026-04-30 12:00 (UTC) の 1 時間足クローズと、トレード markers。 4/29 終盤までの安定上昇から、4/30 朝に急変動へ転換。 2 発目・3 発目の BUY エントリー(マーカー)が、明らかな下降トレンド中に発火していることが視覚的に確認できる。

USD/JPY · 1H Close · UTC
161.0 160.0 159.0 158.0 157.0 156.0 04-29 00 06 12 18 04-30 00 06 12 (UTC) 介入級急変 TP +43.6 TIMEOUT +12.8 BUY entry SL① -49.0 SL② -45.3 SL③ -46.3 -3.65円 / 9h
TP 到達
TIMEOUT
SL 到達
BUY エントリー
03 · TRADES

トレード明細

全 5 件すべて BUY。前日 4/29 終盤に発射した持ち越しの決済(TP・TIMEOUT)が冒頭に含まれ、 続く 3 件は介入相場の最中に新規発射されたが、いずれも SL ヒット。

ENTRY (UTC) EXIT (UTC) SIDE SIZE PRICE 推移 PNL pips JPY CLOSE REASON
04-29 11:0204-29 15:30 BUY 2,800 159.797 → 160.233 +43.6 +1,221 TP 到達
04-29 16:0204-29 22:30 BUY 2,900 160.200 → 160.328 +12.8 +371 最大保有期間超過
04-30 03:0204-30 07:57 BUY 2,993 160.336 → 159.846 -49.0 -1,467 SL 到達 ①
04-30 09:0204-30 10:26 BUY 2,797 159.573 → 159.120 -45.3 -1,172 SL 到達 ②
04-30 11:0204-30 12:07 BUY 2,582 157.153 → 156.690 -46.3 -1,195 SL 到達 ③

3 連 SL の合計は -140.6 pips(-3,832 円)。 特に 3 発目は前回 SL から 2.4 円も下落した位置で BUY エントリー しており、 相場の構造的下降に対してカウンタートレードを構造的に防げていなかった。

04 · RISK GATES — WHAT WAS BROKEN

機能不全だったリスクゲート

本来そなえているべき防壁の状態を、事故時点でのスナップショットとして整理。 「実装はあるのに繋がっていない」「default 値が効いていない」「単発予算超過 halt の不在」が並んだ結果、 防御が積層しているはずのリスク管理は実際にはほぼ素通しだった。

防壁 事故時点 実態
1 取引予算超過 halt 不在 max_risk_per_trade はサイジング入力のみで使われ、実損失が予算を破っても halt しない設計。1 件で予算 16% 超過しても通過してしまった。
regime ゲート(円高/円安バイアス) 未接続 compute_yen_bias() は実装済み・Slack アラートと管理画面表示には繋がっていたが、bot の本番判定経路(runner.py)には未接続。介入ゾーン (-60 以下) でも BUY が通った。
ATR レジームゲート 未実装 ATR_14 は特徴量として計算済みだが、シグナル抑制条件に未使用。長期平均 ATR の N 倍を超える急変動でも entry が通る。
連続エントリー間隔・1 日上限 未実装 「6 時間で 3 連 BUY」を構造的に止める仕組みなし。同方向 N 本以上での抑制ロジックが存在しなかった。
連敗 halt 死設定 MAX_CONSECUTIVE_LOSSES の値はあったが、結線に問題があり実際には 4 本目を発射してしまった。後日の総監査で他にも 8 件以上の死設定が発覚。
介入警戒カレンダー 未実装 為替介入はカレンダー登録されにくく、A 級経済指標ゲート(FOMC, BOJ)にもヒットしない盲点。
対称 RR モデルの promote ガード 欠如 当時の本番モデルは tp=2.5/sl=2.5 の対称 RR で、SL 距離が浅く介入で簡単に刈られた。元設計の非対称 RR (tp<sl) から外れていた。
最大の教訓

「実装はあるのに繋がっていない」が、最も気付きにくく、最も危険。

regime.py は事故の 2 日前 に追加されており、円高スコアを正しく計算していた。 だが Slack 通知と管理画面表示には繋がっていたものの、bot の本番フローには未接続だった。 コードレビューで「呼び出し元の grep」を必ず行う規律を `.claude/rules/grep-call-sites.md` として制定し、 同型の死設定が他に 8 件以上 潜んでいたことが事故翌日の総監査で判明した。

05 · RESPONSE TIMELINE

事故から 12 時間の対応タイムライン

事故の確定から、当日夜の応急処置、翌日の根本対策まで。 痛みを構造的な学びに変換するため、12 時間以内に防御層・観測層・規律の 3 段階を一気に立ち上げた。

04-30 12:02
BUY 1 発目発射 @ 160.336(介入の兆しは未顕在化)。
04-30 16:57
1 発目 SL -49.0pips。5 時間で -50 銭の円高、すでに介入の兆候。
04-30 18:02
BUY 2 発目発射 @ 159.573(前回 SL から -25 銭、それでも BUY)。連敗 1 件の段階で止めるべきだった。
04-30 19:26
2 発目 SL -45.3pips。1.5 時間で -45 銭の急変。
04-30 20:02
BUY 3 発目発射 @ 157.153(前回 SL から -1.97 円、暴落の最中)。
04-30 20:51
緊急 commit 投入: 単発トレード予算超過 halt + OCO SL 誤分類修正 + リスク上限デフォルト厳格化(4/30 事故への直接対応)。
04-30 21:07
3 発目 SL -46.3pips。3 連 SL 合計 -140.6pips、原資割れ。
05-01 00:00 〜 02:00
緊急対応セッション開始: 全リスクゲート総監査、死設定 8 件以上を特定、incident 4 件を構造記録。
05-01 01:00 〜 03:00
サーキットブレーカー 3 ゲート実装: regime / ATR / エントリーレート制限。テスト 70 件追加、カバレッジ 100%。
05-01 03:00 〜 04:00
SELL 学習根本診断 + PF=1.94 達成。逆張り SELL モデルの自動学習で目標値超過、candidate 保存。
05-01 終日
規律仕組み化: grep 確認・設定の一本道・並行 subagent worktree 分離・dashboard env 取扱の 4 つを .claude/rules/ に固定化(毎セッション自動ロード)。
06 · NEW GATES INSTALLED

事故対応で実装した防壁

事故の構造的再発を防ぐため、bot の _tick_try_execute_entry 冒頭に 3 ゲートを順次追加。 halt.flag → regime → ATR → レート制限 → 既存リスクチェック → 発注、という多層防御チェーンに再構成した。

新ゲート 状態 発火条件と効果
halt.flag キルスイッチ NEW data/halt.flag 存在で全 entry 即時停止。SSH 1 行で発動可能、再起動不要。緊急時の最終手段として定着。
regime ゲート NEW compute_yen_bias() を runner に結線。強い円高 (score < -60) で BUY 抑制、強い円安 (> +60) で SELL 抑制。介入ゾーンを構造的に検知。
ATR レジームゲート NEW 直近 ATR / 長期平均 ATR (72bars=3 日) > 2.0 倍で entry スキップ。介入級の急変動を ATR スパイクで検出。
エントリーレート制限 NEW 直近 6h 以内に同方向 2 本以上で抑制、1 日 (JST) 4 本上限。「6h で BUY 3 連発」を構造的に防止。
NaN / 極端値ガード NEW meta_prob が NaN/inf/範囲外 (default [0.0001, 0.9999]) で signal=0 fallback。モデル予測異常時の誤発注防止。
stale data ガード NEW 最終バーが 90 分超古い場合 tick スキップ(既存ポジ管理は継続)。データ取得失敗時の判定停止。
単発予算超過 halt FIXED 1 取引で予算 × tolerance を超えた損失を確定したら、当日の追加 entry を halt。事故当日 20:51 commit で実装。
連敗 halt(再結線) FIXED 結線見直し + デフォルト厳格化(3 → 2)。連敗カウントの計算ロジックも、過去のバグ(進行中 trade を連敗として誤カウント)を含めて再点検。
対称 RR モデルから元設計に切替 FIXED tp=2.5/sl=2.5 → tp=1.5/sl=3.0(元設計)に切替。SL 距離が +20% 厚くなり、同様の急変動でもより耐えられる構造に。

4/30 の 12:02 / 18:02 / 20:02 の 3 連 BUY は、これらのゲートが効いていれば 2 発目で確実に止まる構造になった。 再発防止の効果は今後の運用データで実証していく。

07 · NEXT STEPS

残課題と継続観察

防御層は立ち上がったが、本格的な再開と中期改善には段階を踏む。 bot は事故対応中に halt 状態へ移行し、現在も新規 entry を出さない安全側で待機中。

DONE

サーキットブレーカー 3 ゲート実装

regime / ATR / エントリーレート制限の 3 種を本番 v3 にデプロイ済み。テスト合計 70 件、双方向カバレッジ 100%。

DONE

死設定の総監査と解消

「実装はあるのに繋がっていない」設定 8 件以上を特定し、削除・結線・コメント追記で順次対応。grep 確認の規律を rule 化。

DONE

SELL モデル PF=1.94 達成

逆張り (sell_meanrev) で目標 1.5 を超える candidate を獲得。CPCV は split 不足のため、今後 paper trade で shadow 実績を蓄積する方針。

NEXT

段階的な運用再開

新ゲートの動作確認後、最小ロットで再開し、数週間にわたり regime / ATR ゲートの発動回数と副作用を観察する。

NEXT

介入警戒カレンダーの設計

財務官発言予定や G7 等、A 級経済指標に登録されない介入リスクを手動 INSERT + FX news API 連動で取り込む。

NEXT

SELL 本格運用への shadow 検証

PF=1.94 candidate を paper trade で 1〜2 週間 shadow 検証。安定した実績が確認できれば双方向運用へ段階的に移行する。

08 · OPERATOR'S REFLECTION

運用者所感 — 過信が招いた事故

数値や構造的記録の外側にある、人間側の判断ミスと、このタイミングで起きた意味について。 この章は事実ではなく、運用者の率直な振り返りとして残す。

過信と思い込み

サーキットブレーカーの赤が出ている = bot 側も認識している」という思い込みが、事故を招いた。

過去にも SL を出した日には、管理画面でサーキットブレーカーのインジケーターが赤く点灯していた。 毎週の note 記事でも「リスクコントロールが機能している」と書いていたし、ダッシュボードの表示も そう示していた。だから今回の介入相場でも、「3 連敗の段階で bot 側も止まっているはず」 と 心のどこかで信じていた。
しかし実態は、過去の赤表示は連敗カウントバグの誤発動由来 で、 bot の発注ロジックそのものは止まっていなかった可能性が高い(後日の検証で `2026-05-01_4_17_risk_control_claim_was_misattribution.md` に独立して記録)。 人間側がダッシュボードの表示を一次ソースとして信じ込み、bot 内部の実装と整合性をとっていなかった—— これが今回の介入相場で構造的な防御の総崩れにつながった。

タイミングと授業料

本格的な資産運用に進む直前の、いい授業料として受け入れる。

「まだ本格的な資産運用には進めない」と思っていた矢先のインシデントだった。 資金規模 30K 円台、損失額 -3,832 円というスケールが小さい段階で 構造的欠陥が炙り出されたことは、結果としては救いだった。同じ防御の総崩れが 資金 10 倍・100 倍のフェーズで起きていたら、損失額は二桁三桁違ったはず。
決して安くはないが、構造改善のためのいい授業料として受け入れるしかない。 痛みを「実装はあるのに繋がっていない」「呼び出し元の grep 確認」「設定値の一本道」「並行 subagent の worktree 分離」 「dashboard env の取扱」という 4 つの開発規律として固定化し、毎セッション自動ロードされる仕組みに刻み込んだ。 この事故が無ければ、これらは全て「なんとなく注意する」レベルで放置されていた可能性が高い。

注意: 本レポートのトレード集計は本番 SQLite DB から取得した、 JST 2026-04-30 範囲・exit_time 確定済みのデータに基づく。 価格チャートは GMO コイン 1h 足 OHLC(UTC ベース)。 事故タイムラインは git commit 時刻と incident docs(docs/incidents/2026-04-30_* および docs/incidents/2026-05-01_*)の記録から構築。
過去の note 記事に「リスクコントロールが効いた」と記載した箇所が、後日の検証で連敗カウントバグの誤発動由来と判明した件も docs/incidents/2026-05-01_4_17_risk_control_claim_was_misattribution.md に独立して記録している。
事故報告は事実ベースで、構造を改善するための記録材料として公開する。隠さずに直視する。

ARCHIVE

過去のレポート

週次レポートおよび事故レポートのバックナンバー一覧。