Skip to content

Repository files navigation

llm-trader-battle

LLM(GPT / Gemini / Claude / Grok など)が週初に日本株を2銘柄ずつピックし、その週のリターンを比較するゲーム用ツールです。実際の売買は行いません。ピック対象の銘柄は LLM が自分で考えて選びます。

ゲームルール(週次)

  • 週の最初(日曜日の朝・JST想定)に、その週に値上がりしそうな 2銘柄 を予想します。
  • 採点は「月曜日の始値で買い、金曜日の終値で売る」と仮定した週次リターンで行い、2銘柄の合計で競います。
  • LLMは必要に応じて、利用可能な範囲で Web検索 / URL参照 / X検索 などのツールを使ってOKです(モデル/SDKによって実行痕跡の出方は異なります)。

仕様ハイライト

  • データ取得: yfinance を使用。日本株ティッカーは 7203.T のようにコード+取引所を使用します。
  • マーケットカレンダー: 平日かつ jpholiday 非対象日のみ取引日とみなし、さらに data/calendar/manual_closed_dates.json に列挙した半休日・臨時休場日もスキップします。月曜が祝日の場合は次の取引日に始値を取り、週末側(通常は金曜)が休場の場合はその週(Mon→Fri)の範囲内で最後に取引があった日の終値を採用します(例: 金曜休場なら木曜終値)。
  • タイムゾーン: 内部では Asia/Tokyo を基準に計算し、記録時刻は UTC へ変換します(JSON に ISO 8601 で保存)。
  • LLMピック: 各 LLM クライアントを実際に呼び出してピックを生成します。銘柄ユニバースは固定せず、LLM が自ら選びます。
  • データ保存: GitHub リポジトリ内にファイルとして保存(DB 不使用)。週次ピック/日次価格/日次結果はいずれもフラットな日付付きファイル名(JSON・Markdown)で管理。
  • GitHub Actions: uv を使って3本の定期バッチを実行し、自動コミット/Pushします。

ディレクトリ構成(主要)

  • src/llm_trader_battle/ : アプリ本体
  • data/picks/picks-<week>.json : ピック(model ごとに銘柄・理由を含むオブジェクト形式)
  • data/prices/prices-<YYYY-MM-DD>.json : その日1日の OHLC ロング形式
  • data/result/result-<YYYY-MM-DD>.json : 日次リザルト(llm_avg と銘柄別リターン)
  • data/result/result-<YYYY-MM-DD>.md : 日次リザルト(Markdown)
  • reports/<YYYYMM>/summary.md : 月次サマリ(summary.png を埋め込み)
  • .github/workflows/weekly-picks.yml : 週末ピック(手動時は week_start / llms / skip_current を任意指定可)
  • .github/workflows/daily-prices.yml : 日次価格取得(手動時は date を任意指定可)
  • .github/workflows/daily-aggregate.yml : 日次集計(手動時は date を任意指定可)

コマンド(uv 経由)

  • 週次ピック(週末実行): uv run llm-trader-battle predict --week-start 2025-01-06(省略時は次の月曜を自動推定) - --skip-current を付けると data/picks/picks-<YYYY-MM-DD>.json は生成しつつ、data/picks/current.json を上書きしません(検証用)
  • 日次価格取得(16:00以降・取引日だけ実行): uv run llm-trader-battle fetch-daily --date 2025-01-06
  • 日次集計(17:00以降・取引日だけ実行): uv run llm-trader-battle aggregate-daily --date 2025-01-06

uv sync が失敗する場合(開発環境向け)

一部の環境(例: Codespaces / Dev Container のワークスペースマウント)では、.venv をリポジトリ直下に作ると ファイルシステムの都合で uv syncNo such file or directory (os error 2) で失敗することがあります。

その場合は、仮想環境の作成先をホームディレクトリ側に逃がすと解消します:

  • export UV_PROJECT_ENVIRONMENT="$HOME/.venv-llm-trader-battle"
  • uv sync

Dev Container(Macだけ別imageにしたい場合)

Dev Containers にはOSごとの条件分岐がないため、リポジトリ既定は Windows/Codespaces 向けにして、Mac だけローカルoverrideで差し替える運用にしています。

  • 既定: .devcontainer/devcontainer.jsonmcr.microsoft.com/devcontainers/universal:linux
  • Mac用override: .devcontainer/devcontainer.local.json(git管理しません)

Macでは次を実行してください:

  • .devcontainer/devcontainer.local.json.example.devcontainer/devcontainer.local.json にコピー
  • Dev Containers: Rebuild and Reopen in Container

LLMを1つだけ動かす方法

  • predict 実行時に --llms で1件だけ指定します(例: GPT だけ動かす): - uv run llm-trader-battle predict --week-start 2025-12-15 --llms gpt - 同様に --llms gemini / --llms claude / --llms grok で単体実行できます。

Debug(LLM出力・ツール使用の可視化)

LLMが「検索/URL取得」などの外部ツールを使える設定かと、実行時に実際に使ったかは別です。 このプロジェクトでは、実行ログ(stderr)にツール使用痕跡を出すためのデバッグ用環境変数を用意しています。

ログ出力の環境変数

  • LLM_TRADER_BATTLE_LOG_LLM_OUTPUT=1
    • LLMの生出力(raw)を stderr に出します。
  • LLM_TRADER_BATTLE_LOG_LLM_TOOL=1
    • tool_used を stderr に1行で出します。
  • LLM_TRADER_BATTLE_LOG_LLM_TOOL_TRACE=1
    • tool_trace(プロバイダごとの詳細痕跡)を JSON で stderr に出します。

例:

LLM_TRADER_BATTLE_LOG_LLM_TOOL=1 \
LLM_TRADER_BATTLE_LOG_LLM_TOOL_TRACE=1 \
uv run llm-trader-battle predict

tool_used の意味

tool_used は「このLLM呼び出しで、外部ツール(検索等)を実行した痕跡が取れたか」を表します。

  • tool_used=True: 何らかのツール実行痕跡がレスポンスに含まれていた
  • tool_used=False: ツール実行痕跡が見当たらなかった
  • tool_used=None: そのプロバイダのレスポンスからは判定できなかった(フィールドが無い等)

注意:

  • tool_used=False は「ツールが無効」という意味ではなく、「痕跡が取れなかった」という意味です。
  • プロバイダによっては、ツールの実行がサーバ側で完結し、クライアントには詳細な tool calls が返らないことがあります。

各LLMが使えるように設定されている外部ツール(現状)

実装は src/llm_trader_battle/llm_clients/ 配下にあります。

  • GPT(Azure OpenAI Responses API)

    • 有効化: web_search ツールをリクエストに含めます。
    • 痕跡: response.output 内の web_search_call などを拾って tool_trace に記録します。
  • Claude(claude_agent_sdk)

    • 有効化: preset(claude_code)を使いつつ、allowed_tools=["WebSearch", "WebFetch"] で WebSearch/WebFetch を許可します。
    • 痕跡: ToolUseBlock(WebSearch/WebFetch)を tool_trace.tool_uses に記録します。
  • Gemini(Google Generative AI SDK)

    • 有効化: toolsgoogle_searchurl_context を設定します。
    • 痕跡: grounding_metadata / citation_metadata / url_context_metadata の有無を tool_trace に記録します。
      • これらが出ていない場合でも、将来SDK/モデル挙動が変わる可能性はあります。
  • Grok(xAI SDK)

    • 有効化: search_parameters で Live Search を有効化し、sources=["web","x"]mode="auto" を指定します。
    • 痕跡: usage.num_sources_used(検索で使われたソース数)や citations の件数を tool_trace に記録します。
      • tool_calls が空でも num_sources_used>0 なら「検索が動いた」と判定できます。

週の決め方

  • 週IDは 月曜日の日付(JST)YYYY-MM-DD で用います(週末のピック時に翌週の月曜を自動算出)。

マーケットカレンダー仕様

  • 取引日: 平日かつ jpholiday で祝日判定されない日。
  • 追加の休場日: data/calendar/manual_closed_dates.json に ISO 日付 (YYYY-MM-DD) の配列で記述すると、その日も非取引日扱いになります(半休日や臨時休場日を想定)。
  • 週内の最初に取得できた始値を「購入価格」とみなし、以降の日次終値でリターンを算出。

GitHub Actions スケジュール(UTC / JST)

  • 週末ピック: 0 23 * * SAT (JST 日曜 08:00)
  • 日次価格取得: 0 7 * * * (JST 16:00)
  • 日次集計: 0 8 * * * (JST 17:00)

すべて contents: write 権限で自動コミット/Pushします。失敗時は GitHub Actions の通知に任せます。

レポート出力仕様

  • 日次レポート (data/result/result-<date>.md / .json): 当日の始値(週内の初回取引日)と終値から銘柄別リターン・LLM平均を掲載。
  • 月次サマリ (reports/<YYYYMM>/summary.md): 日ごと×LLMごとの平均リターン表、折れ線グラフ(summary.png)、週ごとのホールディング一覧(週初→週末の銘柄)が含まれます。

今後差し替えるポイント

  • LLM 呼び出しロジック: src/llm_trader_battle/llm_clients/ 配下の各クライアントを運用環境に合わせて調整してください(プロンプトやフォーマット変更など)。

  • レポート形式: 必要に応じてチャートやより詳細な指標(勝率、ドローダウン等)を追加してください。

  • GPT (Azure OpenAI Responses API): AZURE_OPENAI_ENDPOINT, AZURE_OPENAI_API_KEY, AZURE_OPENAI_API_VERSION, AZURE_OPENAI_DEPLOYMENT_GPT (例: gpt-5.1-thinking)

  • Grok (公式SDK/Responses互換): GROK_ENDPOINT, GROK_API_KEY, GROK_MODEL (例: grok-4) — 別名として XAI_ENDPOINT, XAI_API_KEY も使用可。

  • Gemini (Google Generative AI SDK): GEMINI_API_KEY, optional GEMINI_MODEL (例: gemini-2.5-pro)

  • Claude (Anthropic SDK): ANTHROPIC_API_KEY, optional CLAUDE_MODEL (例: claude-4.5-sonnet) いずれか欠けた場合はエラーになります。

環境変数の読み込み

開発時はリポジトリ直下の .env に上記キーを記載すれば、自動で読み込まれます(python-dotenv を利用)。

About

A weekly stock-picking battle where LLMs (GPT, Gemini, Claude, Grok) each pick 2 Japanese stocks and compete on weekly returns — fully automated via GitHub Actions. No actual trading involved.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages