美味しそうな饅頭の中に、毒が入っている

前回、完成したシステムの全貌をお見せしました。Pythonバッチが毎日動いて、Discordに通知が届く。買付候補は承認・棄却に分かれて理由付きで表示される。

今回は、あの仕組みの中で一番「人間の知恵」が問われる場所に踏み込みます。定性フィルターです。

定量スクリーニングは「良い銘柄を見つける」作業でした。乖離率・RSI・出来高——数字の条件を満たした銘柄を、大量の全銘柄の中から拾い上げる。

定性スクリーニングは、その逆です。拾い上げた「良い銘柄」の中に紛れ込んでいる「隠れ毒饅頭」を探す作業です。数字の上では完璧に条件を満たしている。チャートも美しい。でも中身を開けると、業績が崩壊している、上場廃止が迫っている、TOBで株価がアンカーされている——見た目は美味しそうなのに、食べたら死ぬ饅頭。それを弾く。

特に本手法は逆張りです。株価が大きく下がった銘柄を拾う戦略なので、「下がるべくして下がっている銘柄」——業績崩壊、上場廃止リスク、希薄化——が定量スクリーニングをすり抜けてくる確率が、順張りよりも構造的に高い。毒饅頭の混入率が高い戦略だからこそ、定性フィルターの重要度も高くなります。

定量スクリーニングの条件設計と、この定性フィルターの棄却条件。この2つが、あなたの投資経験から来る「暗黙知」をふんだんに発揮する場所です。そしてここだけは、AIに丸投げできませんでした。


3重チェック——そしてAPIの正直な評価

前回のフロー図で見たとおり、定性フィルターは3層構造です。

  1. Gemini Flash API(自動)——Pythonバッチに組み込まれた1次フィルター
  2. Gemini Proチャット(半手動)——人間がプロンプトを投げる2次チェック
  3. 本人(手動)——自分の目で最終確認する3次チェック

元々は全自動を目指していました。だからGemini APIを組み込んだ。いずれAPIの精度が上がれば、人間のチェックは減らせるはず、と。

正直に言います。現時点でのGemini APIは、期待外れでした。

フォローしておくと、従量課金制のため軽量のモデル(Gemini Flash)を使っていたことも影響しています。重いモデルを使えば精度は上がるかもしれませんが、毎日数十銘柄を処理するコストとのバランスを考えると、現実的ではなかった。

言い方は悪いですが、とてもじゃないけど任せられないレベルだった。プロンプトもかなり詳細に作り込みましたが、根本的な問題がありました。

定性フィルターが判断しなければならないのは、「この銘柄が今、買ってはいけない状態にあるかどうか」です。これを判断するには、24時間以内に出た新鮮な適時開示情報を正確に取得する必要がある。そしてこれが、現在のAIと決定的に相性が悪い。

ハルシネーション(事実と異なる情報を生成すること)がしばしば起きる。情報が古い、そもそも取れていない。これは特定のAIの問題ではなく、大規模言語モデル全般が抱える構造的な弱点です。

前回のDiscord通知にAPIエラー(503)が映っていたのを覚えているでしょうか。

Discord通知:棄却された銘柄一覧。途中にAPIエラー(503)が見える(前回の再掲)
Discord通知:棄却された銘柄一覧。途中にAPIエラー(503)が見える(前回の再掲)

ハルシネーション以前に、こうして通信エラーで結果が返ってこないケースすらある。これはGemini API側の混雑の問題なので、こちらで直しようがありません。だから対処もシンプルです。エラーが出た銘柄は「判定なし」のまま、後段の定性チェック(Gemini Proと人間)で普通に処理する。1次フィルターが落ちても、2次・3次が控えている。3重構造にしておいたことが、こういうところでも効いてきます。

だから現状、API定性フィルターはコンセプトとしては正しいが、実用上は自己満足に近い。「全自動とAI」というコンセプトの看板として組み込んではいるけれど、実際の判断を支えているのは2段目・3段目のほうです。いずれ性能が上がった時のことも踏まえた先行投資として実装してある、と考えることにしています。


偽陰性と偽陽性——見逃しと過剰棄却は同じ重さではない

ここで、定性フィルターの設計思想を支える考え方を紹介します。

フィルターがミスをするパターンは2つあります。

過剰棄却(偽陽性)——買うべき銘柄を間違えて弾いてしまう。結果は機会損失。利益を逃したかもしれないが、お金は減らない。ただし、本来取るべきトレードを逃し続ければPFを毀損する可能性はあるので、無視していいわけでもない。

見逃し(偽陰性)——弾くべき銘柄を見逃して通してしまう。結果は実損。業績崩壊中の銘柄を買ってしまう、上場廃止直前の銘柄を掴んでしまう。お金が消える。

この2つは、被害の大きさが決定的に違います。

だから定性フィルターは「疑わしきは棄却」に振ります。過剰棄却は許容する。見逃しは許容しない。100個の良い銘柄を間違えて弾いても、1個の毒饅頭を通してしまうよりマシ。

そしてGemini APIの現状は、まさにこの見逃しが起きるレベルだった。だから人間のチェックが外せない。APIだと古い・取れてない・見逃しのオンパレードで、さらに通信エラーで返ってこないこともある。


絶対棄却と棄却——2種類の毒饅頭

前回チラ見せした、Pythonバッチ内のGemini APIプロンプトを再掲します。この中に書き込まれている棄却条件が、ここからの本題です。

Pythonコード内のGemini APIプロンプト(前回の再掲)
Pythonコード内のGemini APIプロンプト(前回の再掲)

棄却条件は2種類に分かれています。

絶対棄却(共通)——Tierに関係なく、1つでも該当したら問答無用で弾く。毒饅頭の中でも「食べたら即死」レベルのもの。

  1. コーポレートアクション(TOB・MBO等が進行中)
  2. 上場廃止・ターミナルリスク(監理銘柄・整理銘柄・GC注記等)
  3. 株式の希薄化リスク(公募増資・MSワラント等)
  4. 暗号資産連動リスク
  5. 超低位株(100円未満)
  6. イベント通過リスク(翌日が決算発表日、配当権利日接近等)

棄却(Tier別・業績悪化条件)——戦略の性質に応じた基準。毒饅頭というより「消費期限が怪しい饅頭」。

  • Tier 1(上昇トレンド逆張り):業績悪化を厳しめに判定。上昇トレンドにある銘柄の逆張りなので、業績が悪化している銘柄は質が低い可能性が高い
  • Tier 2(トレンド不問逆張り):業績悪化をゆるめに判定。パニック売りの反発を狙う戦略なので、多少の業績悪化は許容するが、大幅減益は弾く

Tier 1のほうが質の高い銘柄が揃うはずですが、シグナルの数が少ない。Tier 2はシグナルが多いので、遊び資金を減らすための補完的な役割。この二段構えで「弱めのロバスト」を実現しています。

なお、業績悪化条件はバックテストでは検証が難しいため、実際の取引データを蓄積して、そのデータをもとに設定しました(この改訂を反映した現行版が、後ほど登場するチェックシートv2.0です)。この取引の過程と結果については、次回詳しく話します。


ビーマップ事件——3重チェックが全部すり抜けた日

定性フィルターの設計思想はここまでにして、私が定性スクリーニングの重要性を身をもって認識した話をします。

運用を始めて1ヶ月弱の3月27日、金曜日。イラン危機の影響や年度末の監理銘柄関連のニュースが集中していました。開発も並行中、株式投資の知識不足も実感していた頃。なかなか忙しい毎日でした。

この日のシグナルは30件を超えていました。3重チェックの仕組み自体は動いていましたが、プロンプトも手順もまだ固定化されておらず、少々荒い運用でした。

チェックしていくと、ほとんどの銘柄が監理銘柄でした。おそらくそれ以前にも監理銘柄はシグナルに引っかかっていたはずですが、なあなあで処理して、AIがうまく弾いてくれていたようです。

恥ずかしながら、「監理銘柄」が何なのか、よく分かっていませんでした。調べてみたところ、上場廃止一歩手前の状態。当然買ってはいけない。人力で株探のニュースを確認し、URLを指定してAIにもチェックしてもらい、最終的に定性スクリーニングを通過した銘柄に絞って、週明けの注文を出しました。そして——3月30日、月曜の朝を迎えました。

病院の待合室

この朝は珍しく朝一で病院の予約が入っていました。8時40分に受付が開くので、少し前からソファに座り、受付を済ませ、採血。8時50分過ぎには採血が終わり、9時過ぎには診察に呼ばれるスケジュール。暇なのでSBI証券のアプリを開きました。

あれ?おかしい。

注文を出しておいた銘柄のひとつ——ビーマップ(4316)がストップ安張り付き気配です。

監理銘柄指定は確かチェックしたはず。もう一度ニュースを見るが、直近では監理銘柄指定のニュースは出ていない。ただのパニック売りかな?——一応Geminiに相談しました。

Geminiの最初の回答。「注文維持」と判断
Geminiの最初の回答。「注文維持」と判断

Geminiの回答は「注文維持」。論理は明快でした。「S安気配はパニック売りが拡大している証拠。平均回帰のエネルギーが数学的に最も高まっている状態。システムの設計思想に完全に合致する特大のエッジ。恐怖は定性的なノイズ。絶対維持しろ」——逆張りシステムのロジックとしては、完全に正しい判断です。

でも、何か引っかかる。この銘柄の掲示板など、個別に情報を漁ってみよう。調べてみると、どうやら上場廃止リスクがあるらしい。その情報を持ってAIに投げかけました。

「ビーマップは上場廃止リスクのようです。調べてみてください。判断は維持ですか?」

人間の指摘を受けて判断を覆したGemini
人間の指摘を受けて判断を覆したGemini

Geminiは即座に判断を覆しました。「緊急の執行判断の変更:直ちに取り消してください」。

調べた結果、ビーマップは東証の上場維持基準に抵触して改善期間に入っており、その最終期限がまさに今月末——つまり本日か明日。S安気配の正体は「ただのパニック売り」ではなく、「上場廃止が市場に織り込まれ始めたことによる構造的な価格崩壊」でした。

プロトコル発動。ファインプレーの評価
プロトコル発動。ファインプレーの評価

Geminiは仕様書の合意事項——「本文書に記載のない新しい判断基準が生じた場合は都度三者で合意形成を行う」——を発動し、即座に棄却条件のアップデートを提案。さらに「運用者によるリスクの指摘は極めて正確かつシステム防衛上ファインプレーでした」と評価しました。

寄り付き(9:00)まであと数分。病院の待合室できょろきょろしながら、成行注文を取り消しました。

3月31日、引け後にビーマップの上場廃止と整理銘柄指定が正式決定。もし取り消していなければ、連続ストップ安で売りたくても約定しづらい状態に巻き込まれていた可能性があります。

真相——なぜすり抜けたか

「すでに監理銘柄には入っていた。ただし、その指定は以前から出ていたニュースであり、直近の最新ニュースには載っていなかった。年度末に最終判断が下されるだろうという市場の見方があったが、新しいニュースとしては出ていなかった」

つまり、私のスクリーニング方法——直近ニュースに棄却対象が含まれているかをチェックする——では、古い指定事項は構造的に引っかからない穴があった。APIもGemini Proも人間も、全員がこの穴を通り抜けた。

そしてもうひとつ。上場廃止リスクに関する棄却条件が、そもそもプロンプトに明文化されていなかった。場当たり的に「やばそうな銘柄」を弾いていて、そのやばさの判断をAIに一任していた。大抵は弾いてくれていたけれど、AIに任せる比重が高すぎて、人間が油断していた。

このエピソードの本質

ここで起きたことの構造を整理します。

この場面でのAIの判断は、情報が揃ったあとは妥当でした。問題は、その情報を自力で拾い切れなかったこと。最初の「注文維持」も、逆張りシステムのロジックとしては論理的に正しかった。

AIの情報探索力に弱点があった。リアルタイムの適時開示情報、特に「以前から出ていたが直近ニュースには載っていない古い情報」を、自力では拾えなかった。

人間がAIの弱点を補った。「上場廃止リスクでは?」と情報を探してきて、AIに渡した。AIはその情報を受けて、即座に正しい判断を下した。

AIが人間の弱点を補った。人間が「安く買えてリバウンドするのでは?」と煩悩を見せたとき、AIは数理的根拠を示して判断を覆し、取消を指示した。

人間がAIの弱点(情報探索)を補い、AIが人間の弱点(冷静な判断)を補った。相互補助。どちらか一方では到達できなかった正解に、二者で到達した。

これが「技術はAIに任せる、戦略は対等に話し合う」の実態です。綺麗な役割分担ではない。お互いの穴を、その場で埋め合うような泥臭い共同作業です。


チェックシートの誕生——失敗が仕組みを生んだ

ビーマップ事件の後、私は定性フィルターの運用プロセスを根本から作り直しました。

棄却条件の明文化。場当たり的だった「やばい銘柄の判断」を、先ほど紹介した絶対棄却6項目+Tier別業績条件として体系化。上場廃止・ターミナルリスクはもちろん明記。

プロンプトの固定化。毎回手作業で打っていたGemini Proへのプロンプトを、完全に固定化。株探の具体的なURL5つを指定して「ここを見ろ」と教える形に。人間がAIに情報の取り方を教える——ビーマップ事件の教訓がそのまま仕組みに落とし込まれています。

チェックシートとして文書化。STEP 1〜6の手順を固定し、誰がやっても(と言っても私しかやりませんが)同じ品質を保てるようにしました。

チェックシート:STEP 2 Gemini Proへの2次チェック
チェックシート:STEP 2 Gemini Proへの2次チェック

これがGemini Proに投げるプロンプトの固定テンプレートです。銘柄コード・Tier・Flash判定結果を記入して投げる。確認URLが5つ指定されていて、共通の絶対棄却条件が列挙されている。

チェックシート:Tier別の業績悪化条件
チェックシート:Tier別の業績悪化条件

Tier別の業績条件のページ。戦略に関わる具体的な数字は塗りつぶしていますが、雰囲気は伝わると思います。共通条件(絶対棄却)とTier別条件が明確に分離されている構造が見えるでしょうか。

チェックシート:STEP 3〜6 本人チェックから注文・報告まで
チェックシート:STEP 3〜6 本人チェックから注文・報告まで

本人による3次チェック、注文の入力、ポジションCSVの更新、Claudeへの報告。すべてチェックボックス式で、抜け漏れが起きない設計になっています。

このチェックシートを導入してから、作業時間はシグナルが少ない日で1時間以内、多い日でも2時間以内に収まるようになりました。時短しつつ、質も上がった。ビーマップ以前の「なあなあのチェック」とは別物です。


今回のまとめ

  1. 定量スクリーニングは「良い銘柄を見つける」、定性スクリーニングは「隠れ毒饅頭を探す」
  2. 見逃し(偽陰性)と過剰棄却(偽陽性)は被害の大きさが違う。疑わしきは棄却
  3. Gemini APIの定性フィルターは現時点では期待外れ。将来の性能向上を見越した先行投資
  4. AIは、情報が揃えば冷静な判断を返せる。ただし情報探索には穴がある。人間がAIの情報取得を助け、AIが人間の冷静な判断を補う。相互補助
  5. 失敗が仕組みを生んだ。チェックシートとプロンプトの固定化が品質と速度を両立させた

次回は、この物語の終着点です。第0回で「このシステムは今、止めています」と書きました。その話をします。生き残った逆張り戦略がどう運用され、どんな成績を出し、なぜ止めたのか。


次回・第8回:運用の結果と、立ち止まった理由


免責事項:本記事は筆者の実体験に基づく情報提供を目的としたものであり、特定の銘柄・手法・サービスへの投資や購入を推奨するものではありません。記載の銘柄(ビーマップ・4316)は実体験の記録として掲載しており、売買の推奨ではありません。投資判断はご自身の責任でお願いします。