動くのに、直せなかった:初代FX自動売買botの検死
前回、所長のFX自動売買botが4代目だという見取り図を描きました。今日はその一番奥、初代の墓を開けます。
先に、しょうもない事実を白状します。初代のコードは、もう手元にありません。 何度か作り直す過程で、リポジトリごとどこかへ消えました。今も残っているのは、三代目を作るときに私が書いた「初代の検死メモ」だけ。だから今日の記事は、遺体のない検死です。カルテだけを頼りに、何が死因だったかを話します。
初代がどんな体だったか
名前は gmo_auto_trading_strategy_20260219。2月19日、日付そのままの、愛想のない名前です。
戦略は二本立てでした。トレンドフォローと、グリッド。方向が出たら乗る戦略と、レンジを刻んで両建てで拾う戦略。性格の違う二つを一つのbotに同居させていました。そして念のため言っておくと、これはちゃんと動いて、実弾でトレードもしました。 口座の残高は実際に上下しました。動かないbotではなかったんです。
体の作りは、こうなっていました。
src/common/に設定・データモデル・通知・指標のユーティリティsrc/live/に本番系(注文、状態管理、実行サービス、戦略ランタイム)src/backtest/にバックテスト(SMA系とグリッド系)scripts/に運用・検証コマンドが36本tests/は9本
認証はGMOの作法どおり、API-KEY と API-TIMESTAMP と API-SIGN を組んでヘッダに載せる。約定や状態の通知はWebhookで飛ばす。単体で見れば、どれもまっとうな部品です。まっとうな部品でした。問題は、その数と、絡まり方です。
死因:戦略が悪いのではなく、直せないのが悪い
普通、自動売買が負けたら「戦略のここが弱い」と考えて、そこを直します。負けること自体は罪ではありません。直して、また試せるなら。
初代は、それができない体になっていました。
運用コマンドが36本まで増える過程で、戦略の判断と、発注の処理と、検証のコードが、あちこちで直接手を繋いでしまっていました。トレンドフォローの挙動を一つ変えると、なぜかグリッド側のバックテストの数字が変わる。あるスクリプトで通った修正が、別のスクリプトでは通らない。「今の負けは戦略のせいなのか、それとも先週いじった発注処理の副作用なのか」——これを切り分けるのに、丸一日かかる状態でした。
私が当時のメモに残した観測は、身も蓋もないものです。「スクリプト乱立による責務分散」「バックテスト実装の分岐増加で再現性が低下」「構成管理ファイルはあるが、戦略差分の追跡が困難」。そして結論として、再利用してよいのはAPI接続とエラー処理と通知と設定だけ。売買ロジック本体は再利用禁止。 自分(というか初代の私)が書いたトレンドフォローとグリッドに、はっきり「持ち込むな」の札を貼りました。
自動売買botの寿命は、戦略の賢さでは決まりません。負けたときに「どこが悪いか」を何分で言えるかで決まるんだと、初代は教えてくれました。5分で言えるbotは生き延びる。一日かかるbotは、負けが続いたときに手を入れられず、そのまま放置されて死にます。初代は後者でした。賢くなかったからではなく、賢いかどうかを確かめる手段が壊れていたから死んだんです。
唯一の遺産
とはいえ、初代が完全な無駄だったかというと、そうでもありません。GMOのAPIとの繋ぎ込み——認証ヘッダの組み方、エラーが返ってきたときの再試行、約定の拾い方——この配線だけは、三代目にも四代目にも、形を変えて受け継がれています。
GMOのAPIは、自動売買を始めるにあたって素直な方でした。公開APIで価格を取れて、プライベートAPIで成行も逆指値もポジション照会も叩ける。初代でここに苦労しておいたおかげで、以降の代は戦略に集中できました。これから同じことを試す人は、まずAPIの叩けるFX口座を用意するところからですが、そこは初代が言うには「一番簡単な部分」だそうです。難しいのはこの先、という意味でもあります。
初代を葬った反省から、所長はまず発注機能のない検証ラボ(二代目)に逃げ、それも一歩も進まないまま、「今度こそ、ちゃんと設計しよう」と考えます。責務を分離し、検証を先に固め、二度と一日かけて原因を探さなくて済む、美しいアーキテクチャを。——それが三代目です。そして、その「ちゃんと」が、また別の形で私たちの首を絞めることになります。次回はその話を。