みなさん、こんにちは!
「ALPHA FORGE 開発秘話」の第23話です。
AIの比較役は、1日に300回以上も呼ばれていました。なのに、記録に残っていたのは1日4〜8件だけ👻
「失敗してるのかな?」と調べてもらったら、答えは「失敗していません。消えていました」。犯人は、16日前に自分たちで入れた“お片づけ”でした。
日本株のAI銘柄スクリーニング&継続学習端末「ALPHA FORGE(アルファフォージ)」を、Claude Code と二人三脚で個人開発しています。今回は【事件簿】回。画面をきれいにする修正が、あとで別の目的の邪魔をした話です🧩
【要約:この記事で伝えたいこと】
- 保有銘柄の判定が5分ごとに承認待ちへ積み上がるので、「同じ銘柄は最新の1件だけ残す」重複排除を入れた。比較役(シャドウ)の判定も一緒に消える作りだった
- 16日後、安いモデルと一致率を比べる計画を立てたとき、比較役の記録が1日4〜8件しか残っておらず、計画が成り立たないとAI自身が判断した
- 対処:表示用(最新1件)と評価用(追記専用・失敗も状態つき)にテーブルを分けた。表示のための削除処理は、評価用のテーブルに触らない
※本記事はnote連載[ALPHA FORGE 開発秘話 #23] の技術的な部分を、エンジニア向けに再構成したものです。
📥 5分ごとに増える「承認待ち」
ALPHA FORGE は、保有している銘柄を場中に5分ごとに見直して、「持ち続ける」「手放す」などの判定を出します。ただし、自動では何もしません。判定は「承認待ち」として並び、決めるのは人間です(アプリはブローカーへの発注を一切しません)。
困ったのは、同じ銘柄の判定が5分ごとに1件ずつ増えていくこと。古い判定を承認しても意味がないのに、一覧は古い判定だらけになります📜
9月18日、別の機能の依頼のついでに、AI(Claude Code)にこう頼みました。
ポートフォリオに、承認待の表示がたまってしまうため、重複するような場合は最新のみ残すようにする
AIは、新しい判定を入れる直前に、同じ銘柄のまだ承認されていない判定を消す処理を入れました。比較役(シャドウ)の判定も含めて、です。承認待ちはスッキリ✨
🔍 16日後、「なぜ失敗してる?」
10月4日の朝、AIのコストを見直していました。ポートフォリオの判定は、アプリのLLM費用の約75%を占める大食いさんです🍔 今のモデルと安いモデルを並べて走らせ、判定がどれだけ一致するかを比べる計画を立てていました。
そこで、気になっていたことを聞きました。
Geminiシャドウはなぜ失敗しているか調べて
AIの答え(要旨)はこうでした。
- APIは正常。キーも有効で、試しに2回呼ぶと、どちらもちゃんと答えが返ってきた
- 前回のクレジット切れは、チャージで解消済み
- 記録の数は1日4〜8件。主の判定は1日に約300〜470回あるのに、残っているのは保有銘柄の数と同じくらいだけ
原因は、9月18日の重複排除でした。5分ごとに全部の判定が入れ替わるたびに、比較役の判定も一緒に消していた。だから、最後の1件しか残らなかったんです🫠
ハマりどころ
「表示を整える」ための削除(いわゆる supersede)と、「あとで評価する」ための記録が同じテーブルに同居していると、表示の都合で評価用のデータが消えます。エラーも出ないし画面も普通に動くので、件数を数えるまで気づけません。
さらにAIは「前回提案した計画は成り立ちません」と続けました。1日4〜8件では、1〜2週間ためても数十件。一致率を測るには足りません。自分の出した計画に、自分でダメ出し👏
🛠️ 表示用と評価用を分ける

承認待ちは最新1件のまま。比べる記録は、別の帳面に追記だけする
修正案は、比べるための専用テーブルを新しく作ることでした。「その方向で進めて」と返して、約20分で実装完了。
| 用途 | テーブル | 書き方 |
|---|---|---|
| 表示用(承認待ち) |
portfolio_signal_shadows ほか |
同じ銘柄は最新1件だけ。古い未承認は消す |
| 評価用(モデル比較) |
portfolio_signal_model_trials(新設) |
追記専用。消さない |
評価用テーブルには、主の判定と並走させたモデルの判定を1行に並べて残します(抜粋)。
sa.Column("primary_model", sa.String(64), nullable=False),
sa.Column("primary_action", sa.String(16), nullable=False),
sa.Column("challenger_model", sa.String(64), nullable=False),
sa.Column("challenger_status", sa.String(24), nullable=False),
sa.Column("challenger_action", sa.String(16), nullable=True),
設計で決めたことは次の3つです。
- 失敗(エラー・答えの形の崩れ・3つの価格の矛盾)も
challenger_statusつきで残す。失敗を黙って母数から外すと、一致率が実際より良く見えるから - 並走で想定外の例外が起きても、本番の判定と監視ループは止めない(フェイルソフト)
- 並走は設定で指定したときだけ動かす(既定は無効)
並走させるぶん、費用は1日あたり約1.1ドル増えます。そこで1日の上限を8ドルに上げると、人間が決めました💰
⚖️ やったこと/やらなかったこと
- やったこと:表示用(最新1件)と評価用(追記だけ)に記録を分けた
- やらなかったこと:重複排除をやめて承認待ちの画面を元に戻す案。人間が見る画面は、最新の1件だけのほうが正しいから
- やらなかったこと:消える比較役の記録のまま、比べる計画を進める案。数十件では判断の材料にならないから
🧰 今回のハーネス術:「なぜ失敗?」を、決めつけずに聞く
今回は「なぜ失敗しているか調べて」という、前提つきの聞き方から始まりました。でもAIは前提をうのみにせず、APIを実際に呼び、日別の件数を数え、主の判定の回数と比べて、「そもそも失敗していない」と前提ごとひっくり返しました🔄
- 異変は「症状」で伝える。「件数が少ない」は事実、「失敗している」は推測
- AIには、前提が違っていたら違うと言ってもらう
- 件数の話は、比べる相手(今回は主の判定の回数)と並べて見る
📌 保存用チェックリスト
- 画面をきれいにする削除は、ほかの目的でその記録を使っていないか確かめてから入れる
- あとで比べる・学ぶための記録は、追記専用の場所に分ける
- 失敗も状態つきで残し、母数から黙って外さない
- 件数が少ないときは、呼ばれた回数と並べて「消えていないか」を見る
☕ note.comで開発秘話と毎朝の検証ログを連載中
note.comでは、「ALPHA FORGE」の開発秘話と、毎朝のアルゴリズム検証ログを公開しています。
👉 元記事(note連載第23話):
https://note.com/featured_stocks/n/nabdaefe259bc
同じ比較役(シャドウ)が、前払いクレジット切れで13日間黙っていた話は第22話です。
エンジニアでない方向けに「AIへの仕事の頼み方」をまとめた連載(メンバーシップ「AIとつくるラボ」)もやっています。第0話は無料で読めます。
免責事項
本記事は個人開発およびAIエージェントを活用したシステム開発の技術記録です。特定の銘柄の売買推奨や投資助言を行うものではありません。本ツールは証券会社等への発注機能を持たず、判定はすべて人間の承認を前提としています。記事中の件数・回数・費用は、開発時の記録と変更履歴にもとづく値です。AIの発言は要旨です。
⚠️ 【システム検証記録に関する免責事項・注意事項】
- 本記事は、独自開発アルゴリズム「ALPHA FORGE」の動作検証およびデータ分析過程を公開する技術・運用の個人的な記録ログです。
- 掲載されているすべてのデータ(各スコア、基準観測値、統計的変動上限、シナリオ無効化水準など)は、過去の市場データに基づき数式(ATR等)により機械的に算出されたバックテスト・シミュレーション用のパラメータであり、特定の有価証券の売買勧誘、取引の推奨、投資助言・代理行為を目的としたものではありません。
- また、将来の株価変動や運用成果を保証するものではありません。実際の投資判断および最終決定は、必ずご自身の責任と判断において行っていただけますようお願いいたします。



