USD/JPY が 9 時間で -3.65 円(160.34 → 156.69)の急変。 bot は BUY を 3 連発で発射し、全件 SL ヒットで -140.6 pips(-3,832円)。 原資割れ。
この事故の本質は、相場の急変ではなく 「実装はあるのに繋がっていなかった」リスクゲートの総崩れ。 本レポートは、当日の価格推移・トレード明細・機能不全だった防壁・12 時間以内の根本対策を、加工なく公開する。
集計期間: 2026-04-30 (JST 1 日 / 決済済みのみ)。 4/29 終盤エントリーの持ち越し決済 (TP +43.6 / TIMEOUT +12.8) を冒頭に含み、その後 3 連 SL で原資割れ。
介入級の円高は確かに不可避の外部要因。だが本来そなえているべき複数のリスクゲートが 「実装はあるのに繋がっていない」「死んだフラグ」「単発予算超過 halt の不在」 という形で軒並み機能不全だった。1 件で予算 16% 超過する SL を 3 連発で許してしまった設計責任が、急変動と重なって最大級の単日損失を生んだ。
2026-04-29 00:00 〜 2026-04-30 12:00 (UTC) の 1 時間足クローズと、トレード markers。 4/29 終盤までの安定上昇から、4/30 朝に急変動へ転換。 2 発目・3 発目の BUY エントリー(マーカー)が、明らかな下降トレンド中に発火していることが視覚的に確認できる。
全 5 件すべて BUY。前日 4/29 終盤に発射した持ち越しの決済(TP・TIMEOUT)が冒頭に含まれ、 続く 3 件は介入相場の最中に新規発射されたが、いずれも SL ヒット。
| ENTRY (UTC) | EXIT (UTC) | SIDE | SIZE | PRICE 推移 | PNL pips | JPY | CLOSE REASON |
|---|---|---|---|---|---|---|---|
| 04-29 11:02 | 04-29 15:30 | BUY | 2,800 | 159.797 → 160.233 | +43.6 | +1,221 | TP 到達 |
| 04-29 16:02 | 04-29 22:30 | BUY | 2,900 | 160.200 → 160.328 | +12.8 | +371 | 最大保有期間超過 |
| 04-30 03:02 | 04-30 07:57 | BUY | 2,993 | 160.336 → 159.846 | -49.0 | -1,467 | SL 到達 ① |
| 04-30 09:02 | 04-30 10:26 | BUY | 2,797 | 159.573 → 159.120 | -45.3 | -1,172 | SL 到達 ② |
| 04-30 11:02 | 04-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 エントリー しており、 相場の構造的下降に対してカウンタートレードを構造的に防げていなかった。
本来そなえているべき防壁の状態を、事故時点でのスナップショットとして整理。 「実装はあるのに繋がっていない」「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 件以上 潜んでいたことが事故翌日の総監査で判明した。
事故の確定から、当日夜の応急処置、翌日の根本対策まで。 痛みを構造的な学びに変換するため、12 時間以内に防御層・観測層・規律の 3 段階を一気に立ち上げた。
.claude/rules/ に固定化(毎セッション自動ロード)。
事故の構造的再発を防ぐため、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 発目で確実に止まる構造になった。 再発防止の効果は今後の運用データで実証していく。
防御層は立ち上がったが、本格的な再開と中期改善には段階を踏む。 bot は事故対応中に halt 状態へ移行し、現在も新規 entry を出さない安全側で待機中。
regime / ATR / エントリーレート制限の 3 種を本番 v3 にデプロイ済み。テスト合計 70 件、双方向カバレッジ 100%。
「実装はあるのに繋がっていない」設定 8 件以上を特定し、削除・結線・コメント追記で順次対応。grep 確認の規律を rule 化。
逆張り (sell_meanrev) で目標 1.5 を超える candidate を獲得。CPCV は split 不足のため、今後 paper trade で shadow 実績を蓄積する方針。
新ゲートの動作確認後、最小ロットで再開し、数週間にわたり regime / ATR ゲートの発動回数と副作用を観察する。
財務官発言予定や G7 等、A 級経済指標に登録されない介入リスクを手動 INSERT + FX news API 連動で取り込む。
PF=1.94 candidate を paper trade で 1〜2 週間 shadow 検証。安定した実績が確認できれば双方向運用へ段階的に移行する。
数値や構造的記録の外側にある、人間側の判断ミスと、このタイミングで起きた意味について。 この章は事実ではなく、運用者の率直な振り返りとして残す。
過去にも 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 に独立して記録している。
事故報告は事実ベースで、構造を改善するための記録材料として公開する。隠さずに直視する。
週次レポートおよび事故レポートのバックナンバー一覧。