1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自律的なAI分析サイクルを回してAI×株価分析

この記事は、さくらのAI Engine 記事投稿キャンペーンの活動ログです。
日経平均・個別銘柄向けの分析ツールをAIに自律的にPDCAを15サイクル+α実施させて改良した経験をまとめています。あくまでAIを使うことが目的で金融知識が素人の寄稿した記事として読んでください。


はじめに:なぜ株価分析ツールを作ったのか

「AIで株価を予測したい」——そう思ったことのある人は多いと思います。
私もその一人でした。ただ、いきなり「儲かる予測モデル」を作るのではなく、
「自分が納得できる分析フローを、小さく繰り返し改善する」ことを目指しました。ただ自分はそこまで専門的な知識はないのであくまでAIにまるなげです。

対象は日経平均(^N225)と日本の主要銘柄。
使用したのは Python と、さくらのAI Engine(Copilot CLI)です。
15回のサイクルを通じて、予測モデルが「見えない落とし穴」にどれだけ落ちやすいかを実感しました。

この記事では、AIが実施した15回分の改善プロセスを振り返り、
「AIで株価を分析する人が知っておくべきの教訓」をお伝えします。

作ったものの概要

最終的にできたのは、以下のようなツールです。

  • 入力: 銘柄コード(例: ^N225, 7203.T
  • 出力: 「買い」「売り」「様子見」のスコア、過去のバックテスト結果
  • 予測対象: 翌営業日〜60営業日先の株価リターン
  • 考慮する情報:
    • 株価のテクニカル指標(移動平均、ボラティリティ、RSI など)
    • 海外市場(S&P500、金、ドル円、VIX)
    • 日本のマクロ指標(失業率、CPI、日銀金利)
    • 業界(セクター)ごとの集計
  • リスク管理: VaR / CVaR、最大ドローダウン、損切りルール
  • 実行方法: コマンドラインと、ブラウザ上の Streamlit GUI

image.png

名前は RAES(Regime-Aware Ensemble Scorer) と勝手につけました。
要するに、「今の市場環境(レジーム)に応じて、複数の指標の重みを変えてスコアを出す」仕組みです。


このツールで使っている主な技術

技術 用途
Python 3.12 言語全体
yfinance Yahoo Finance からの株価取得
pandas / numpy データ加工
scikit-learn 標準化・相関計算
matplotlib / seaborn チャート描画
Streamlit GUI
pytest 自動テスト
uv 依存管理

エージェントはgithub copilotCLI
AIモデルはpreview/Kimi-K2.7-Codeを利用
そのほか、https://github.com/obra/superpowers のpluginを利用することでPDCAを実施


RAESの戦略とは?

RAES は、以下の3ステップで「買い・売り・様子見」のシグナルを出します。

1. 特徴量の計算

まず、対象銘柄と市場全体から複数の特徴量を計算します。

  • 株価のテクニカル指標:リターン、ボラティリティ、移動平均乖離、RSI など
  • 海外市場:S&P500、金(GC=F)、ドル円(USDJPY=X)、VIX の前日リターン
  • マクロ指標:失業率、CPI、日銀金利(1カ月以上の公開ラグを考慮)

2. レジーム別の重み付け

次に、過去のボラティリティやトレンドで「今の市場はどんな状態か」を判定します。
その状態(レジーム)ごとに、各指標が将来リターンとどれだけ相関していたかを計算し、
相関の高い指標ほど重く重み付けします。

3. スコアの較正と判定

最後に、複数の指標を重み付けで足し合わせて -1.0 〜 +1.0 のスコア を作ります。
Cycle 12 以降は、スコアのしきい値を固定せず、
直近60営業日のスコア分布で 上位20%を「買い」、下位20%を「売り」、中央60%を「様子見」 と判定します。

取引ルール

  • シグナルが「買い」に切り替わった翌営業日にエントリー
  • シグナルが「売り」に切り替わるか、指定ホライズン(5日など)が経過したら決済
  • ポジション変更時に 0.10% の取引コストを差し引く
  • 含み損が 5% に達したら損切り

実際の画面:日経平均(^N225)の例

下図は、Streamlit GUI で ^N225 を分析した結果です。
上から「株価と移動平均線」「RAESスコア」「累積リターン」の3つのグラフが並んでいます。

image.png

ポイントは、青い「買い持ち」線がオレンジの「戦略」線を大きく上回っていることです。
これは、過去1年程度の検証期間では、単純な買い持ちの方がRAES戦略よりも高いパフォーマンスを示したことを意味します。
ただし、これはあくまで過去データでの結果です。

実際の画面:個別銘柄(さくらインターネット:3778.T)の例

下図は、個別銘柄(3778.T)で同じ分析をした結果です。

image.png

「戦略」線が「買い持ち」線を大きく下回っています
同じモデルでも銘柄によって結果が大きく変わるため、
「モデルが万能」ではなく「銘柄ごとに検証が必要」ということを示しています。


15サイクルを大きく5つのステージに分けると

15回すべてを細かく書くと長くなるので、大きく5つのステージにまとめます。これは指示したわけではなくAIが自律的に判断して改良を行った結果です。

Stage 1:基盤を作る(Cycles 1〜5)

最初の5回では、分析の土台を固めました。

  1. 金(ゴールド)先物を追加
    景気不安のときに金が動くため、「リスクの匂い」を読む材料にしたかったのです。

  2. マクロ指標を追加
    失業率、CPI、日銀金利を組み込みました。
    ただし月次データなので、日次に補間する処理が必要でした。

  3. 個別銘柄のバッチ評価
    トヨタ、ソニー、ソフトバンクなどを一度に分析できるようにしました。

  4. ウォークフォワード検証
    一度だけ学習・検証するのではなく、時期をずらして何度も検証する方法を導入しました。

  5. セクター別集計
    業界ごとに「今どの業界が強そうか」を集計できるようにしました。

Stage 2:予測の幅を広げる(Cycles 6〜8)

次の3回では、予測の期間と評価の精度を高めました。

  1. マルチホライズン予測
    1日先だけでなく、5日、20日、60日先も予測できるようにしました。

  2. ホライズン対応のバックテスト
    シグナルに従って「数日間ポジションを持つ」想定で検証できるようにしました。

  3. ベンチマーク比較
    「Buy & Hold(買って放置)」と比較して、本当にモデルが意味があるかを測定しました。

Stage 3:将来情報漏洩を排除する(Cycles 9〜10)

ここが転換点でした。これまでのバックテストが「未来を見て予測している」可能性に気づき、
徹底的に見直しました。

  1. マクロ指標の公開ラグ対応
    例えば3月のCPIは4月以降にしか使えないので、1カ月シフトしました。

  2. 先頭の bfill 除去
    データの先頭を後ろの値で埋めていた箇所を削除し、
    使えない日付は素直に欠損として扱うようにしました。

Stage 4:網羅性と実用性を高める(Cycles 11〜13)

  1. 東証33業種をカバーする銘柄を追加
    業界別の傾向を読むため、より多くの業界を追加しました。

  2. スコアの動的較正
    「買い」「売り」のしきい値を固定ではなく、
    直近60営業日のスコア分布のパーセンタイルで動的に決定しました。

  3. リスク管理の強化
    VaR / CVaR、最大ドローダウン、最大連続損失日数、5%損切りを追加しました。

Stage 5:運用ツール化(Cycles 14〜15)

  1. データキャッシュ
    Yahoo Finance からの取得結果をローカルに保存し、再実行を高速化しました。

  2. Streamlit GUI
    ブラウザから銘柄コードやホライズンを選んでワンクリック分析できるようにしました。


15回やって分かった「4つの教訓」

教訓1:国内マクロより、海外市場の影響が圧倒的に大きい

最も相関が高かったのは、S&P500の前日リターンでした。
日本の失業率やCPIよりも、米国市場の動きの方が日経平均の翌日に強く影響していました。

これは驚きではありませんが、数値で確認できたのが大きかったです。
マクロ指標は長期的な流れを読む材料にはなりますが、
「明日の株価」を予測しようとすると、力不足であることが明らかになりました。

教訓2:「未来を見ていないか」は何度も疑うべき

株価予測で最も怖いのは look-ahead bias(先見バイアス) です。
つまり、予測時点ではまだ知りえない未来の情報を、うっかり特徴量や目的変数に使ってしまうこと。

私のツールでも、以下のような落とし穴がありました。

  • マクロ指標を「発表月」そのまま使っていた
  • 目的変数のタイミングがバックテストとずれていた
  • データの先頭を後ろの値で埋めていた

具体例:CPIの公開ラグ

例えば、2024年3月のCPIは4月以降に公表されます。
これを「3月1日時点で既知の情報」として使ってしまうと、
モデルは「実際には知りえない未来の数字」を見て予測することになります。

修正前:

2024-03-01 の予測に 2024年3月のCPI を使用

修正後:

2024-03-01 の予測に 2024年2月のCPI を使用(1カ月ラグ)

このような小さな違いが、バックテストの結果を大きく変えます。
「うまくいきすぎている結果」は、まず疑う——これが最大の学びです。

教訓3:1回の検証では騙される

学習データでは Sharpe レシオ 1.5 以上の銘柄があっても、
検証データではマイナスになることもありました。

原因は、市場環境が学習期間と異なる場合があること、
そしてモデルが特定の過去パターンに過学習してしまうことです。

その対策として、ウォークフォワード検証を導入しました。
時期を少しずつずらして複数回検証することで、
「本当に安定しているのか」を確認できます。

教訓4:プログラムを柔軟にしておくと、試行回数が増える

最初は「新しい指標を追加するたびに、複数ファイルを修正する」状態でした。
それを、**「利用可能な指標を自動で解決する」**設計に変えたことで、
試行のスピードが格段に上がりました。


GUIで実際に使う

Cycle 15 で Streamlit の GUI を作った理由は、
**「分析を気軽に繰り返せること」**が重要だと気づいたからです。

コマンドラインでも動きますが、ブラウザから銘柄コードを入力して
「分析開始」を押すだけでレポートが見られる方が、試行のハードルが下がります。

GUI では以下が画面から操作できます。

  • 銘柄コードの入力
  • 予測期間(1日 / 5日 / 20日 / 60日)の選択
  • データ取得期間(1年 / 3年 / 5年)の選択
  • キャッシュのクリア

個人開発では、「使うたびにコマンドを覚えている必要がある」状態が続くと、
だんだん使わなくなります。GUI は継続のための投資だと考えています。


おまけ:15サイクルでかかったAIのリクエスト分析

最後に、本プロジェクトをAI(さくらのAI Engine)と一緒に進めた際の、
LLMリクエスト消費の推移を振り返ります。

リクエスト数の推移

フェーズ 累積リクエスト数 備考
環境構築 約400 プロジェクト設定、スキル整備
株価分析 Cycles 1〜5 約631 1サイクルあたり約40リクエスト
Cycle 10 終了時点 1,127 1サイクルあたり約100リクエストに増加
Cycle 15 終了時点 1,917 1サイクルあたり約200リクエストに増加
Cycle終了後のチューニング 2300 気になった点を人間がFBして再チューニング

最初は1サイクル約40リクエストで済んでいたのに、
後半は1サイクル約200リクエストまで増えました。

なぜ後半でリクエストが増えたのか

リクエスト増加の主な原因は、以下の3つです。

  1. 出力物の強制生成
    各サイクルでレポートやサマリーを自動生成するようになったため、
    コード変更だけでなく文章生成のリクエストも増えました。

  2. 3レビュープロセスの導入
    Cycle 6 以降、精度・品質・ユーザビリティの3観点からレビューを依頼する
    プロセスを入れた結果、1サイクルあたりの対話回数が増えました。

  3. 検証の徹底
    look-ahead bias 排除やウォークフォワード検証など、
    信頼性を高めるためにテストと確認の回数が増えました。

グラフで見る消費の変化

下図は、Cycle 10 終了時点でのリクエスト消費状況です。
環境構築直後と、Cycles 9〜10 のレビュー対応で大きなピークが出ています。

image.png

下図は、Cycle 15 終了時点でのリクエスト消費状況です。
後半のサイクルで消費が加速していることが分かります。

image.png

同一セッションで、繰り返し作業をしているのでコンテキスト128Kであることを考慮するとトークン増加 > compact を繰り返します。コンテキストウインドの半分(5~6万)くらいが平均的なインプットトークンになっています。
順調にエージェントが動いてくれてるときのAPI呼び出し頻度は 1時間で183回、1分で3回程度でした。

途中、
Request failed due to a transient API error. Retrying...
が多発して作業がすすまなくなりました。
1日で2000近いリクエストを使用して制限がかかったのかそれともモデルが不安定なのか・・・

コストを抑えるための教訓

  • レビューは必要最小限に:3観点レビューは有効だが、自動化できる部分は自動化する
  • 出力物生成は計画的に:毎サイクル長文レポートを作るのではなく、
    記事化が決まったタイミングでまとめる
  • 小さな確認を繰り返さない:テストはまとめて実行し、
    細かい確認を何度もLLMに投げるのを減らす

AIを使った開発は確かに速いですが、
「何でも聞けばいい」わけではなく、リクエスト単価を意識した進め方が重要だと痛感しました。


Cycle 15 の最新結果:何が言えるのか

2026年8月23日時点での39銘柄バッチ評価結果を簡単に紹介します。

判定 件数
買い 11
売り 6
様子見 22

強い買い判定の例

  • 8306.T(三菱UFJ): パーセンタイル 98.33%
  • 8604.T(野村證券): パーセンタイル 98.33%
  • 7735.T(SCREEN HD): パーセンタイル 95.00%

強い売り判定の例

  • 5713.T(住友鉱山): パーセンタイル 0.00%
  • 2502.T(アサヒグループ): パーセンタイル 3.33%
  • 8058.T(三菱商事): パーセンタイル 3.33%

ただし、これは過去データに基づく統計的シグナルにすぎません
多くの銘柄で検証期間の Sharpe レシオが 1 を下回っており、
「そのまま従えば儲かる」という保証はありません。

むしろ重要なのは、
「検証期間でパフォーマンスが悪化する銘柄が多い」という事実です。
これは、直近の市場環境が学習期間と大きく異なる可能性を示唆しています。


初学者へ:株価予測を始めるなら、この3つだけ意識してほしい

  1. 「将来を予測する」ではなく「過去を検証する」ことを楽しむ
    まずは、自分のアイデアが過去データでどう動くか確認することから始めましょう。

  2. 「うまくいきすぎている」結果は必ず壊す
    look-ahead bias、過学習、データリークの可能性を疑ってください。

  3. 1つの指標にこだわらない
    テクニカル指標だけ、マクロだけでは偏りが生じます。複数の角度から見る習慣をつけましょう。


なぜ「儲かるモデル」ではなく「納得できるフロー」を目指すべきか

結論から言うと、15回改良しても「確実に儲かるモデル」はできませんでした。
しかし、それは失敗ではありません。

なぜなら、以下のことが身についたからです。

  • どの指標が予測に寄与しているかを定量的に確認できる
  • バックテストの落とし穴を疑える目ができた
  • 過去データの限界を正直に伝えられる
  • 改善点を次々に試せる構造を持てた

投資は最終的に「人間がリスクを取って判断する」行為です。
AIはあくまで情報整理の助けに過ぎません。
AIの出力を鵜呑みにせず、自分で検証できる仕組みを持つこと——
それが、この15回で得た最大の成果だと思います。


サイクル15以降の最適化:FeatureSelectedRAES

記事作成後、読者の指摘を受けて(という体で)パフォーマンス改善に取り組みました。
検証期間の Sharpe が低い銘柄が多かったので、
RAES のスコアリング部分を改善することに焦点を当てました。

試したアプローチ

ベースライン(元のRAES)に対して、以下の4つのスコアラー変種を実装し、
18銘柄×3ホライズンで比較しました。

  1. FeatureSelectedRAES

    • 各レジームごとに、目的変数との絶対相関が高い上位k個の特徴量だけを使う
    • ノイズになりやすいマクロ指標や弱いテクニカル指標を自動で落とす
  2. MultiRegimeRAES

    • トレンド/レンジに加え、ブル/ベアの4状態で重みを学習する
  3. ThresholdAlignedRAES

    • 推論時の閾値も学習データで最適化し、学習/推論のミスマッチを減らす
  4. MomentumVolatilityRAES

    • モメンタムとボラティリティでスコアを補正する

主な結果

銘柄 ホライズン ベースライン Sharpe 最良スコアラー 最良 Sharpe
^N225 5日 0.34 FeatureSelected_k4 1.99
^N225 20日 -0.25 FeatureSelected_k6 1.22
7203.T(トヨタ) 5日 0.60 FeatureSelected_k6 1.45
1803.T(清水建設) 5日 0.40 MomentumVolatility 1.55
5108.T(ブリヂストン) 5日 -0.03 FeatureSelected_k4 1.89
2502.T(アサヒ) 5日 -0.41 ベースライン 1.79

特に ^N225 の 5日先予測では Sharpe が 0.34 → 1.99 と劇的に改善しました。
一方で、全18銘柄の平均を取ると依然としてマイナス Sharpe になる銘柄も多く、
「1つのモデルがすべてに通用する」わけではないことが再確認されました。

  • ベースライン Sharpe:最もシンプルな標準モデル(RAES)だけで検証期間をバックテストしたときの Sharpe レシオ
  • 最良 Sharpe:いくつかの改良モデル(特徴量選択、モメンム・ボラ補正など)の中で、検証期間の Sharpe が一番高かったものの値

※Sharpe レシオ自体は「リスクに対する収益率」の指標で、1 以上だと優秀、0 付近やマイナスだとリスクに見合っていない、と考えられます。

分かったこと

  • 特徴量選択は強力だが、kの数は銘柄・ホライズンによって最適値が変わる
  • ^N225 のように「常にレンジ判定」になりがちな市場では、
    トレンド用の重みが無駄になりやすい
  • 銘柄ごとに最適なスコアラーが異なるため、
    次のステップは「過去パフォーマンスから自動でスコアラーを選ぶ」仕組みです

反映された仕様

この結果を受け、CLI / バッチ解析のデフォルトスコアラーは
**FeatureSelectedRAES(top_k=6, min_abs_corr=0.02)**に変更しました。
元のRAESに戻したい場合は --scorer raes で指定できます。

# 新しいデフォルト(特徴量選択付き)
python -m nikkei_analyzer.cli --ticker ^N225 --horizon 5

# 元のRAES
python -m nikkei_analyzer.cli --ticker ^N225 --horizon 5 --scorer raes

サイクル15以降のさらなる検討:上げ相場・下げ相場の非対称性

FeatureSelectedRAES を使っていると、次のような違和感がありました。

  • 上げ相場ではベンチマーク(買い持ち)に負ける
  • 下げ相場ではベンチマークより損失が小さい

「下げ相場で強いモデルができた?」と思いきや、調べてみると真相は違いました。

真の原因:スコアが常に正に偏っていた

^N225 の 5日先予測で診断した結果、テスト期間の取引はすべてロングで、
スコアの平均は 0.428、スコアが正になる日は 94.7% でした。
過去20日が下落局面でもスコア平均は 0.513 と依然として正。
つまり、モデルは「下げを予測してショートしている」のではなく、
「ポジションを持たずに損失を免れている」だけでした。

これは以下の理由で起こっていました。

  1. 直近5年の日経平均は上昇バイアス
  2. 目的関数が生リターンのシャープ比なので、自然と買い方向に重みが傾く
  3. 閾値 ±0.3 が固定で、スコア分布に対して高すぎたり低すぎたりする

試した改善とその結果

アプローチ 内容 ^N225 H5 の結果
グローバルセンタリング スコア中央値を0に引く sharpe 1.467 → -0.766(悪化)
サイン目的関数 リターンの符号だけ学習 sharpe 1.467 → 0.871(悪化)
閾値チューニング 0.3 → 0.25 に変更 sharpe 1.753、累積リターン 0.555(改善)
レジーム別中央値補正 トレンド/レンジごとに中央値を引く sharpe 1.575、累積リターン 0.475(改善)

閾値を緩めると ^N225 ではベンチマークを超えましたが、他銘柄では必ずしも通用しません。
これは、市場環境や銘柄特性によって最適な攻め方が変わることを示しています。

実装した新機能

この検討を受け、以下の2つのスコアラーと、非対称閾値対応を追加しました。

  • RegimeCalibratedRAES — トレンド/レンジの各レジームで訓練中央値を引き、
    レジームごとのスコアバイアスを取り除く
  • AdaptiveThresholdRAES — 訓練データで sharpe 比を最大化する閾値を自動選択
  • --long_threshold / --short_threshold 対応 — 買いと売りのエントリー感度を
    別々に調整可能
# レジーム補正スコアラー
python -m nikkei_analyzer.cli --ticker ^N225 --horizon 5 --scorer regime_calibrated

# 閾値自動最適化スコアラー
python -m nikkei_analyzer.cli --ticker ^N225 --horizon 5 --scorer adaptive_threshold

分かったこと

  • 「下げ相場で強い」印象は、能動的なショートではなく「現金に逃げた結果」であることが多い
  • スコアを無理に対称化すると、予測情報を捨ててしまう
  • 銘柄・市場環境ごとに最適な閾値や補正方法が異なる

予測スパン × スコアラー 勝敗分析

対象銘柄数: 32、スコアラー: ['adaptive_threshold', 'baseline', 'bull_bear', 'feature_selected_k4', 'feature_selected_k6', 'momentum_vol', 'multi_regime', 'regime_calibrated', 'threshold_aligned']

集計テーブル

horizon scorer 件数 勝ち 勝率 負け率 平均超過リターン 中央超過リターン 平均Sharpe
5 adaptive_threshold 32 12 37.5% 62.5% -34.51% -13.32% -0.047
5 feature_selected_k6 32 12 37.5% 62.5% -34.51% -13.32% -0.047
5 regime_calibrated 32 12 37.5% 62.5% -36.61% -20.79% -0.129
5 feature_selected_k4 32 10 31.2% 68.8% -30.34% -17.46% 0.108
5 baseline 32 9 28.1% 71.9% -34.15% -23.39% 0.121
5 momentum_vol 32 6 18.8% 81.2% -35.51% -28.98% -0.113
5 multi_regime 32 6 18.8% 81.2% -35.92% -27.69% -0.129
5 threshold_aligned 32 5 15.6% 84.4% -41.64% -45.87% -0.355
5 bull_bear 32 5 15.6% 84.4% -46.13% -28.81% -0.364
20 feature_selected_k4 32 10 31.2% 68.8% -35.41% -20.36% -0.095
20 momentum_vol 32 9 28.1% 71.9% -26.10% -25.04% 0.151
20 adaptive_threshold 32 9 28.1% 71.9% -35.98% -18.23% -0.006
20 feature_selected_k6 32 9 28.1% 71.9% -35.98% -18.23% -0.006
20 regime_calibrated 32 8 25.0% 75.0% -39.30% -23.58% -0.124
20 multi_regime 32 7 21.9% 78.1% -30.19% -19.99% -0.021
20 bull_bear 32 7 21.9% 78.1% -36.25% -24.91% -0.027
20 baseline 32 7 21.9% 78.1% -36.90% -34.18% -0.222
20 threshold_aligned 32 5 15.6% 84.4% -42.21% -44.37% -0.347

パフォーマンス改善ようPDCAでさらに5サイクル改善プロセスをまわすようにAIに指示したところ、
レート制限に引っかかったので断念。結果的に3000リクエストは使い切れず終わりました(最終的には2600リクエストくらい)。
Failed to get response from the AI model; retried 5 times (total retry wait time: 405.11 seconds) Last error: 429 rate limit exceeded

まとめ

  • AIで株価を分析する際、海外市場の影響を軽視してはいけない
  • look-ahead bias はいつもそばにあるので、何度も疑う
  • 1回の検証では過学習に騙される。ウォークフォワードで安定性を確認する
  • 小さな改善を続けるには、柔軟なプログラム構造が不可欠

15回のサイクルを通じて、私は「予測モデルの限界」と「それでも分析する価値」の両方を学びました。
この記事が、AI×株価分析に挑戦する人の「最初の一歩」になれば幸いです。


免責事項

本記事は過去データに基づく統計的な分析の記録であり、将来の株価や投資結果を保証するものではありません。
バックテストは理想化された執行を仮定しており、実際の取引コスト、税金、流動性リスク、スリッページとは異なる場合があります。
投資判断は自己責任で行ってください。


関連リンク

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?