実運用中の自律トレーディングシステムで踏んだインシデント(データ凍結による出口シグナル遅延と、それを毎日のレビューが見逃した一件)から抽出した設計原則。姉妹編 自律システムはなぜ自分の欠陥に気づけないのか の実践編。
0. 前提:何を作ろうとしているか
「目標に対して自律的に改善するシステム」を、次のループを回すものと定義する(OODA の変種)。
典型的な事故は、①でデータが静かに古くなり、②④が同じ古い前提を共有し、⑤が真因(データ層)ではなく②のしきい値を触りに行くという、ループ全体の合意的な失明である。以下の原則は「各ステージで何を守るか」に対応する。
原則1:目標を「北極星 + リスク予算」で定義し、計器を正直に保つ
自律ループは目標に向かって最適化するので、目標の表現が歪むとシステム全体が歪みを増幅する。
- 目標は到達目標(リターン等)だけでなく、超えてはいけない境界(許容ドローダウン・最低勝率・最低 PF=プロフィットファクター) とセットで持つ。片方だけだと「目標達成のためにリスク無制限」になる。
- 達成可能性・進捗の判定しきい値を現実に較正する。 「非現実的な必要リターンを”達成可能”」と表示する較正ミスは、「出遅れ→もっとリスクを取れ」を正当化する。
- 「遅れているからリスクを上げる」を実装しない。 攻撃的な目標に近づく正攻法はレバレッジでなくエッジ(勝率×損益比)の改善。“behind” の応答は「露出拡大」ではなく「改善要請」にする。
- 実装のコツ:目標評価は純関数 + 名前付き定数にする。すると較正ミスがコードレビューと単体テストで可視化される。
アンチパターン:CI やダッシュボードの赤を、しきい値を緩めて緑にする(= 体温計をいじる)。目標は下げない。計器を正直にする。
原則2:入力の鮮度と整合性を「境界」で能動チェックする(GIGO 対策)
GIGO(Garbage In, Garbage Out=ゴミを入れればゴミが出る)は自律ループの静かな天敵だ。自律ループは自分のデータストアを盲信する。「データが無い」は例外で気づけるが、「データが古い/ズレている」は無言で通過する。
- 鮮度ガード:判断に使うデータの「最終更新が何単位前か」を毎サイクル検証し、古ければ再取得 or 明示警告。古さを一級市民(
fail/healed)として扱う。 - 単一の真実源、さもなくば乖離検知:判断に使う値と人間が見る値が別ソースなら、ソース間の乖離そのものを監視項目にする(例: 決定エンジン=内部DB、可視化=外部ライブ)。
- 契約テスト:外部依存のモックは「綺麗な正常応答」だけでなく、実運用の過渡状態(欠損・部分行・タイムゾーン・休日)を再現する fixture を使う。理想応答は本番の壊れ方を再現しない。
原則3:観測(observability)と制御(control)を混同しない
「ダッシュボードに出ている」は「システムが対処できる」を意味しない。
- surface した指標には必ず「で、システムはどう動くのか」を紐づける。 出せるだけの指標は観測、行動に接続された指標だけが制御。
- フィードバックの対象を入口と出口の両方に張る。 改善回路が「入口(新規判断)」に偏ると、「出口(既存状態の是正)」が放置される。
- 実装のコツ:レビューが検出した構造問題を次サイクルの作業項目(Issue/PR)へ自動変換する橋を作る。ただし原則5の安全ゲートを必ず挟む。
原則4:「やったこと」だけでなく「避けたこと」を測る
学習信号のサバイバーシップ・バイアスは自律システムの静かな殺し屋。
- 完了アクションからしか学ばないと、「完了させない」失敗モードが不可視になる。 例: 決済済みトレードしか学習に入らないと「負けを切らず塩漬け」が統計に載らない。
- 対策:未完了・保有/滞留期間・先送り・機会損失を明示計測する。決済前に負けを可視化する装置(優先度ランキング等)を置く。
- レビューは両側を測る:機会損失(false negative)と 損失の垂れ流し(false positive)。片側だけ測ると片側に暴走する。
原則5:自己改善は「安全ゲート付き」で段階的に自律化する
⑤(コード/ルールの自己書き換え)が最も価値が高く、最も危険。
- 書き換えは必ず PR 経由 + CI + 人間マージ。 デフォルトブランチへの直接 push 禁止。自律エージェントは「PR を作るところまで」。
- 段階的自律(progressive autonomy):
- Lv0 観測のみ → Lv1 提案(要承認)→ Lv2 低リスク・可逆操作は自動/高リスクは承認 → Lv3 限定自動実行。
- 原則判断は人間に残す。 AI は調査と実装、人間は問いと価値判断。この分業が効く。
- 権限境界を明示する。 自律実行モードでは危険操作(テスト実行・外部送信・スキーマ変更・プロセス kill 等)を制限。制限で品質ゲートを完遂できないなら、PR を「保留 + 要人手」で出す。
原則6:メタ盲点を受け入れ、「人間の問い」を設計に織り込む
最重要のメタ教訓:
自律システムは、自分の盲点を自分では監査できない。
- 外部から刺す経路を定期化する:ランダムな深掘り、異常系の再現(chaos)、「なぜこうなった?」の定期問診。
- 反実仮想を回す:「別の判断をしていたら?」を毎回計算してレビューに載せる。
- 完全性クリティック:「今、測っていない/検証していない前提は何か」を問う専用視点を1つ常駐させる。
Claude Code 機能へのマッピング
| やりたいこと | Claude Code の機構 |
|---|---|
| 定期実行のループ(収集・提案・レビュー) | Scheduled agents / cron、self-hosted runner + GitHub Actions |
| 「毎回この手順」を固定化 | Skill / スラッシュコマンド(.claude/commands/*.md) |
| 「Xしたら必ずYする」自動挙動 | hooks(settings.json)。プロンプトで保証できない自動化はフックで |
| 大規模な調査・レビューの並列化 | サブエージェント(Agent tool)で fan-out、独立視点で adversarial verify |
| 自己改善の安全ゲート | PR + CI + auto-merge ゲート + 人間承認。デフォルトブランチ保護 |
| ガバナンス/規約の常時注入 | CLAUDE.md(規約・安全則・テスト規約を集約し全セッションに効かせる) |
| 盲点の考古学(後から原因を辿る) | 実行時状態の永続化(判断の根拠テキスト・スナップショット・レポートをDBに残す) |
「エージェントに優しいコードベース」の実装規律
自律改善はエージェントが読める・変えられる・検証できるコードでこそ回る。
- 判断ロジックを純関数に切る(DB非依存)。テスト・モック・grep が容易になる。
- 実 DB セッションでテストする(モックではなく実インメモリ DB)。制約・型変換・flush が本番同様に発火し、モックが空振りするバグを捕まえる。
- 出力は「存在」でなく「内容」をアサートする(必須セクション・数値まで検証)。
- エラー/例外の再現は実物で。短い代用文字列は整形パスを通らず本番特性を再現しない。
- 意思決定の根拠を永続化する。「何を入力に、なぜそう判断したか」を残すのが、後の自己監査の生命線。
アンチパターン・チェックリスト(黄色信号)
- 「データが古い」を検知する仕組みが無い(欠損だけ見ている)
- 判断に使う値と人間が見る値が別ソースで、照合していない
- レビューが問題を「表示」するが、行動に変わらない
- 学習が「完了アクション」だけで、やり残し/滞留を測っていない
- 目標が到達目標だけで、リスク予算(許容DD・最低勝率)が無い
- 「遅れているから積極化」というロジックがある
- CI/テストの赤を、しきい値を緩めて緑にした過去がある(計器を曲げた)
- 自律エージェントが人間承認なしにデフォルトブランチを書き換えられる
- 「なぜこうなったか」を後から辿れるログ/状態が残っていない
3つ以上該当したら、機能追加より先にここを塞ぐ。
構築順序(段階的に立ち上げる)
- 観測から始める(Lv0):目標・リスク予算を定義し、ギャップを毎日正直に表示するだけ。まだ何も自動で変えない。
- 境界を固める:鮮度ガード・ソース乖離検知・契約テストを先に入れる(GIGO を塞いでから賢くする)。
- 提案を足す(Lv1):エージェントが行動を提案、人間が承認。両側(機会損失/損失垂れ流し)を測る。
- ループを閉じる:検出した構造問題を PR 化する橋を作り、CI + 人間マージでゲート。
- 限定自動化(Lv2+):低リスク・可逆な操作から自動実行を解禁。危険操作は承認/権限で縛る。
- メタ層を常駐させる:定期的な素朴問診・反実仮想・完全性クリティックを制度化。
一言で
速く作れることは、盲点も速く量産する。 効くのは派手な自律機能ではなく、「境界で鮮度を見る / ソース乖離を監視する / ループを閉じる / 避けたことを測る / 計器を正直に保つ / 人間の問いを設計に織り込む」という地味な規律。そして自己改善コードは必ず PR + 人間マージのゲートを通す。
この記事の背景となった実際のインシデント(データ凍結が「毎日のレビュー」を素通りした顛末)は、姉妹編 自律システムはなぜ自分の欠陥に気づけないのか を参照。
