AIファンドリーグ蠱毒 (MVP)
AIファンドリーグ蠱毒 (MVP)
複数のAIファンドマネージャーが仮想100万円を運用し、AI社長が評価・フィードバックする自動運用システムのMVPです。
本プロジェクトは仮想運用による研究・エンタメ・教育目的のAIファンドリーグです。
特定銘柄の売買を推奨するものではありません。
実売買・投資助言・運用代行は行いません。
表示される成績は仮想運用の結果です。
安全装置
- 実売買は一切行いません(仮想売買のみ)。
.envのDRY_RUN=trueが初月の既定値です。falseにしても本MVPは外部発注を実装していません。
セットアップ
cp .env.example .env
npm install
LLM APIキー(ANTHROPIC_API_KEY / OPENAI_API_KEY)は任意です。
未設定の場合、各AIは投資思想に基づくローカルのヒューリスティックで判断します(オフライン動作)。
コマンド
npm run init:season # シーズン初期化+各AIに100万円配布+初回3銘柄購入
npm run run:once # 1回分の運用判断を実行(判断→ルール→社長承認→仮想売買→ログ→dashboard)
npm run run:scheduled # 平日 10/11/13/14時 に自動実行(node-cron)
npm run generate:dashboard # public/data/dashboard.json を再生成
npm run generate:note # 火/木/土に note 原稿を生成(--force で任意の日に生成)
npm run seed # 動作確認用のタイムスタンプ付きサンプル株価を生成
npm run dev # Next.js ダッシュボード (http://localhost:3000)
最短の動作確認
npm run init:season
npm run run:once
npm run generate:note -- --force
npm run dev
ディレクトリ構成
app/ Next.js ダッシュボード(Vercel)
src/
config/ ルール・エージェント定義・環境変数・パス
types/ 共有型(single source of truth)
scheduler/ runOnce / cron / season
market/ 株価・候補銘柄の読み込み(将来API差し替え可)
agents/ ファンドマネージャー5名 / AI社長 / 広報AI / LLMクライアント
portfolio/ 仮想売買・時価評価
rules/ 売買ルール検証(§7/§16)
logs/ activity/decision/trouble/learning の jsonl ロガー
reports/ note原稿生成
export/ dashboard.json 生成
commands/ npm scripts のエントリ
data/ JSON/JSONL 永続化(候補・ポートフォリオ・ログ・レポート・株価)
public/data/dashboard.json ダッシュボード配信用JSON
定期実行と安全装置
npm run run:scheduled で平日 10:00 / 11:00 / 13:00 / 14:00 に自動実行します(node-cron)。
暴走やトークン浪費を防ぐため、以下の安全装置が常に働きます。
- 多重起動の防止: ロックファイル(
data/.scheduler.lock)で同時に1インスタンスのみ。 - 実行中スキップ: 前回が終わるまで次のティックを実行しない(積み上がり防止)。
- 1日の実行回数上限:
MAX_RUNS_PER_DAY(既定4)を超えるとスキップ。 - 1日のLLM呼び出し上限:
MAX_LLM_CALLS_PER_DAY(既定60)を超えると以降はヒューリスティック判断に切替(トークン浪費の安全弁)。カウントはdata/scheduler_state.jsonに永続化され、再起動しても累積される。 - シーズン終了後は実行しない:
Day > total_daysで停止。 - 連続エラーで自動停止:
SCHEDULER_MAX_CONSECUTIVE_ERRORS(既定3)回連続失敗で停止。 - 完全停止:
SCHEDULER_ENABLED=falseで起動自体を拒否。
LLMを使わず回したい場合は LLM_PROVIDER=heuristic。株価は実行前に npm run seed 等で更新する運用です。
2ジョブ構成(昼=株価取得 / 夜=AI判断)
日中に画面を見られない場合の最小運用。昼は株価スナップショットを貯めるだけ(LLM不使用=ゼロ課金)、夜にその日の分をまとめて再生します。
- 昼ジョブ:
npm run capture:scheduled(平日10/11/13/14時に株価を保存)。単発ならnpm run capture:prices。 - 夜ジョブ:
npm run run:replay(その日のスナップショットを時刻順に再生し、各時点で判断サイクルを実行。ポートフォリオは引き継ぐ)。スナップショットが無ければ最新株価で1回だけ実行。
# 昼(別プロセスで放置 / Mac はスリープ回避に caffeinate 推奨)
caffeinate -i npm run capture:scheduled
# 夜(見られる時に1回)。LLMで判断させる場合は LLM_PROVIDER=claude_cli
LLM_PROVIDER=claude_cli npm run run:replay
常時稼働(launchd・設定済み)
昼の株価取得は macOS の launchd エージェント ~/Library/LaunchAgents/com.aifundleague.capture.plist
として登録済みで、平日10/11/13/14時に自動で capture:prices を実行します(LLM不使用=ゼロ課金)。
常駐プロセス不要・再起動後も有効。Mac がスリープ中は動かず、復帰時に逃した分を実行します。
launchctl list | grep aifundleague # 状態確認
launchctl start com.aifundleague.capture # 今すぐ1回テスト実行
tail -f ~/ai-fund-league/data/capture.log # ログ
launchctl unload -w ~/Library/LaunchAgents/com.aifundleague.capture.plist # 無効化
LLM呼び出しは MAX_LLM_CALLS_PER_DAY、再生サイクル数は MAX_RUNS_PER_DAY で上限管理されます。
夜間など、定刻以外でテストする
- 起動時刻は
CRON_EXPRで上書きできます(例: 10分おきCRON_EXPR="*/10 * * * *")。 AUTO_SEED=trueにすると各実行前に株価を自動生成し、値動き・売買が見えます。- Mac はスリープすると cron が止まるので、放置テストは
caffeinate併用を推奨。
例(夜に10分おき・自動株価・トークン消費なし):
CRON_EXPR="*/10 * * * *" AUTO_SEED=true LLM_PROVIDER=heuristic \
MAX_RUNS_PER_DAY=20 npx tsx src/commands/runScheduled.ts
例(夜に10分おき・本物のAI判断・LLMは1日60回で自動打ち切り):
CRON_EXPR="*/10 * * * *" AUTO_SEED=true LLM_PROVIDER=claude_cli \
MAX_RUNS_PER_DAY=12 MAX_LLM_CALLS_PER_DAY=60 npx tsx src/commands/runScheduled.ts
Vercel公開(デプロイ)
ダッシュボードはビルド時に public/data/dashboard.json を読み込んで静的生成します(DB不要・サーバーレスでも確実に表示)。データを更新したら再デプロイで反映する運用です。
初回のみ(Vercelにログイン・プロジェクト連携):
npx vercel login
npx vercel link # 案内に従ってプロジェクトを作成/紐付け
公開(ローカルで実行)。最新のポートフォリオから dashboard を作り直してから本番デプロイ:
npm run publish:vercel # = generate:dashboard → vercel deploy --prod --yes
- 免責文(下記)は本番画面にも常時表示されます。
- リアルタイム更新ではなく「更新したら再デプロイ」モデルです(MVPの最小構成)。
GitHub連携の自動デプロイ(設定済み)
このプロジェクトの Vercel は GitHub リポジトリ shinta007009/ai-fund-league と接続済みで、
master への git push で本番が自動デプロイされます。推奨運用ループ:
# 夜(見られる時)
npm run run:replay # または run:once(AI判断)
npm run generate:dashboard # 念のため最新スナップショット化(replay/onceでも生成済み)
git add public/data/dashboard.json && git commit -m "update dashboard" && git push
# → push をトリガーに Vercel が自動でビルド・公開
npm run publish:vercel(手動デプロイ)も引き続き使えます。
Supabase(履歴・分析レイヤー)
ファイル保存(data/)を運用の正本として残したまま、判断・成績・トラブル・学習を Supabase(Postgres) にも蓄積し、期間横断の分析や公開サイトの履歴表示に使えるようにします。未設定なら自動でスキップ(運用は止まりません)。
セットアップ:
- https://supabase.com で無料プロジェクトを作成
- SQL Editor で
db/schema.sqlを実行(テーブル+RLS読み取り許可を作成) - Settings > API から URL と各キーを取得し
.envに設定:
SUPABASE_URL=https://xxxx.supabase.co
SUPABASE_SERVICE_KEY=... # 書き込み用(秘密厳守)
SUPABASE_ANON_KEY=... # 読み取り用(公開サイト)
- 接続確認:
npm run test:supabase - 同期:
npm run sync:supabase(ファイル→Supabase。upsertなので何度でも実行可)
運用ループに組み込む例(夜):
npm run run:replay && npm run sync:supabase && git add -A && git commit -m "update" && git push
ニュース連携(案A: 軽量テーマ信号)
市場ニュースRSS(日経マーケット / Yahoo経済)の見出しを取得し、AIのプロンプトに
「今日の市場テーマ」と候補銘柄の言及数(📰xN) を付与します。LLMトークンは使いません(取得+文字列照合のみ)。
- 自動有効化:
NEWS_START_DATE(既定2026-06-22)以降は自動でON。NEWS_ENABLED=true/falseで手動上書きも可能。 - 有効時、
captureジョブが株価と一緒に当日ニュースも保存(data/news/news_<日付>.json)。 - 動作確認:
npm run test:news(見出しとテーマ・言及銘柄を表示)。
適時開示(TDnet・無料・キー不要)
ニュース有効時、TDnet の適時開示(決算・業績予想の修正・配当・自社株買い・M&A等)を無料のYanoshin Web APIから取得し、証券コード単位で候補58銘柄に直接マッチさせて「材料(📄)」としてプロンプトとnoteに付与します(src/market/tdnet.ts、data/news/tdnet_<日付>.json)。RSSニュースより精度の高い銘柄別シグナルです。
- 動作確認:
npm run test:tdnet - 非公式ミラー(Yanoshin)のため失敗時は自動で無視(運用は止まりません)。JPX/TSE非公式。
ニュース有無の比較実験: 第1期(〜2026-06-21)はニュース無し、第2期(2026-06-22〜)はニュース有りで before/after を比較する設計(DEVLOG M12)。
実株価(Yahoo Finance・無料・推奨)
PRICE_SOURCE=yahoo で、Yahoo! Finance から58銘柄の実価格・出来高・前日比・時価総額を取得します(認証不要・無料、約15〜20分遅延)。非公式APIのため壊れる可能性がありますが、失敗時は合成データへ自動フォールバックします。
npm run test:yahoo # 動作確認(58銘柄の実データを表示)
PRICE_SOURCE=yahoo npm run capture:prices # 実データでスナップショット保存
.env に PRICE_SOURCE=yahoo を入れれば、launchd の昼ジョブも実データを取得します。
注意: Yahoo! Finance の非公式利用です(個人利用想定・生データの再配布不可)。本ダッシュボードは仮想運用の派生結果+免責のみを表示します。
実株価(J-Quants)連携
PRICE_SOURCE=jquants にすると、JPX公式の J-Quants API から58銘柄の実価格・出来高・前日比を取得します(時価総額は候補CSVの概算値を継続使用)。未設定/失敗時は合成データに自動フォールバックするため、パイプラインは止まりません。
- https://jpx-jquants.com で無料登録し、リフレッシュトークン(または登録メール+パスワード)を取得
.envに設定:
PRICE_SOURCE=jquants
JQUANTS_REFRESH_TOKEN=xxxxx
JQUANTS_DELAY_DAYS=90 # 無料プランは約12週間遅延。直近が必要なら有料プラン+1〜3
- 動作確認:
npm run test:jquants(基準日と先頭8銘柄を表示) - 以後は
capture:prices/capture:scheduled/ launchd が実データを取得
注意: 無料プランはデータが約12週間遅延します(=直近の株価ではない)。直近株価で運用したい場合は J-Quants の有料プラン(Light等)に加入しJQUANTS_DELAY_DAYSを 1〜3 にしてください。idTokenはdata/.jquants_token.jsonに24h キャッシュされます(gitignore済み)。
株価データ (§15)
初月は手動更新のJSONを使います。data/market/prices_*.json のうち最新の日付のものを優先し、
無ければ prices_sample.json を使用します。npm run seed で動作確認用ファイルを生成できます。
実装フェーズ
- Phase 1: ローカルで1回動く(本MVPで実装済み)
- Phase 2: 平日定期実行(
run:scheduled) - Phase 3: Vercel可視化(
app/) - Phase 4: note原稿生成(
generate:note) - Phase 5: 学習機能(learning.jsonl を次回プロンプトへ反映 / 個別・全体学習の分離)— 今後