⚠️ 本仓库是 virattt/ai-hedge-fund 的 A 股研究分叉, 不是上游英文项目。本 README 下方保留上游英文说明以示出处与 credit, 但本分叉的实际工作流、CLI 与数据源与上游不同:
- 市场: A 股 (沪深), 非美股; 主要工作流是
--auto全市场筛选, 不是上游的--ticker AAPL,MSFT。- 安装: 使用
uv(本仓库同时含uv.lock与上游遗留的poetry.lock), 入口是uv run python src/main.py, 不是poetry run。- 数据源: Tushare / AkShare / Baostock (需
TUSHARE_TOKEN), 非上游的FINANCIAL_DATASETS_API_KEY。- 决策面: 本分叉新增
--auto/--explain/--why-not/--daily-brief/--decision-flow/--top-picks/--position-check等 A 股决策 CLI。新用户请直接阅读 docs/cn/user-manual.md (权威中文手册) 与 docs/cn/product/feature-proposals.md (产品 backlog / R 系列变更记录), 不要照下方上游英文说明操作。
This is a proof of concept for an AI-powered hedge fund. The goal of this project is to explore the use of AI to make trading decisions. This project is for educational purposes only and is not intended for real trading or investment.
This system employs several agents working together:
- Aswath Damodaran Agent - The Dean of Valuation, focuses on story, numbers, and disciplined valuation
- Ben Graham Agent - The godfather of value investing, only buys hidden gems with a margin of safety
- Bill Ackman Agent - An activist investor, takes bold positions and pushes for change
- Cathie Wood Agent - The queen of growth investing, believes in the power of innovation and disruption
- Charlie Munger Agent - Warren Buffett's partner, only buys wonderful businesses at fair prices
- Michael Burry Agent - The Big Short contrarian who hunts for deep value
- Mohnish Pabrai Agent - The Dhandho investor, who looks for doubles at low risk
- Peter Lynch Agent - Practical investor who seeks "ten-baggers" in everyday businesses
- Phil Fisher Agent - Meticulous growth investor who uses deep "scuttlebutt" research
- Rakesh Jhunjhunwala Agent - The Big Bull of India
- Stanley Druckenmiller Agent - Macro legend who hunts for asymmetric opportunities with growth potential
- Warren Buffett Agent - The oracle of Omaha, seeks wonderful companies at a fair price
- Valuation Agent - Calculates the intrinsic value of a stock and generates trading signals
- Sentiment Agent - Analyzes market sentiment and generates trading signals
- Fundamentals Agent - Analyzes fundamental data and generates trading signals
- Technicals Agent - Analyzes technical indicators and generates trading signals
- Risk Manager - Calculates risk metrics and sets position limits
- Portfolio Manager - Makes final trading decisions and generates orders
Note: the system does not actually make any trades.
This project is for educational and research purposes only.
- Not intended for real trading or investment
- No investment advice or guarantees provided
- Creator assumes no liability for financial losses
- Consult a financial advisor for investment decisions
- Past performance does not indicate future results
By using this software, you agree to use it solely for learning purposes.
Before you can run the AI Hedge Fund, you'll need to install it and set up your API keys. These steps are common to both the full-stack web application and command line interface.
git clone https://github.com/virattt/ai-hedge-fund.git
cd ai-hedge-fundCreate a .env file for your API keys:
# Create .env file for your API keys (in the root directory)
cp .env.example .envOpen and edit the .env file to add your API keys:
# For running LLMs hosted by openai (gpt-4o, gpt-4o-mini, etc.)
OPENAI_API_KEY=your-openai-api-key
# Optional: set a unified default model route for every CLI/script/web entry
LLM_DEFAULT_MODEL_PROVIDER=MiniMax
LLM_DEFAULT_MODEL_NAME=MiniMax-M2.7
# For getting financial data to power the hedge fund
FINANCIAL_DATASETS_API_KEY=your-financial-datasets-api-keyImportant: You must set at least one LLM API key (e.g. OPENAI_API_KEY, GROQ_API_KEY, ANTHROPIC_API_KEY, or DEEPSEEK_API_KEY) for the hedge fund to work.
Default Model Routing: You must explicitly set both LLM_DEFAULT_MODEL_PROVIDER and LLM_DEFAULT_MODEL_NAME for default routing. To avoid silent model downgrades, the system no longer falls back to provider-specific model variables such as MINIMAX_MODEL or MINIMAX_FALLBACK_MODEL when resolving the default model.
You can inspect the currently resolved default model with:
.venv/bin/python scripts/list-models.pyFinancial Data: Data for AAPL, GOOGL, MSFT, NVDA, and TSLA is free and does not require an API key. For any other ticker, you will need to set the FINANCIAL_DATASETS_API_KEY in the .env file.
You can run the AI Hedge Fund directly via terminal. This approach offers more granular control and is useful for automation, scripting, and integration purposes.
- Install Poetry (if not already installed):
curl -sSL https://install.python-poetry.org | python3 -- Install dependencies:
poetry installpoetry run python src/main.py --ticker AAPL,MSFT,NVDAYou can also specify a --ollama flag to run the AI hedge fund using local LLMs.
poetry run python src/main.py --ticker AAPL,MSFT,NVDA --ollamaYou can optionally specify the start and end dates to make decisions over a specific time period.
poetry run python src/main.py --ticker AAPL,MSFT,NVDA --start-date 2024-01-01 --end-date 2024-03-01You can inspect the currently resolved default model directly from the main CLI.
poetry run python src/main.py --show-default-modelpoetry run python src/backtester.py --ticker AAPL,MSFT,NVDAFor pipeline-style hedge fund runs and A/B backtests, the environment variable ANALYST_CONCURRENCY_LIMIT controls the default size of each provider lane.
1means fully serialized analysis. This is the safest option when your LLM quota is tight, but also the slowest.2means two analysts run in parallel per wave. This was the original conservative default used to stabilize long A-share runs.3means three analysts run in parallel per provider lane. When both Zhipu and MiniMax are available, the system can schedule them together for up to6analyst calls in the same wave.MINIMAX_PROVIDER_CONCURRENCY_LIMITandZHIPU_PROVIDER_CONCURRENCY_LIMITlet you bias the split instead of keeping the two providers at1:1.LLM_PRIMARY_PROVIDER=MiniMaxmakes the weighted wave start from MiniMax first, which is useful when MiniMax is your main workhorse and Zhipu is the overflow lane.- Larger values increase throughput, but they also increase the chance of provider-side
429, quota exhaustion, or unstable long-running jobs.
This setting does not change the number of stocks being processed. It only changes how many analyst personas are evaluated concurrently before the workflow moves on to the next batch. In dual-provider mode, total concurrency is approximately MINIMAX_PROVIDER_CONCURRENCY_LIMIT + ZHIPU_PROVIDER_CONCURRENCY_LIMIT when those two variables are set, otherwise it remains approximately ANALYST_CONCURRENCY_LIMIT * 2.
Examples
Run the main program with conservative concurrency:
ANALYST_CONCURRENCY_LIMIT=2 poetry run python src/main.py --ticker AAPL,MSFT,NVDARun a real A/B backtest with moderate concurrency:
ANALYST_CONCURRENCY_LIMIT=3 .venv/bin/backtester --ab-compare --mode pipeline \
--start-date 2025-12-01 --end-date 2026-03-04 \
--train-months 2 --test-months 1 --step-months 1 \
--model-provider Zhipu --model-name glm-4.7 \
--analysts-all \
--report-file data/reports/ab_walk_forward_first_pilot.md \
--report-json data/reports/ab_walk_forward_first_pilot.jsonRun a weighted dual-provider backtest where MiniMax carries more traffic and Zhipu stays as a spillover lane:
ANALYST_CONCURRENCY_LIMIT=3 \
MINIMAX_PROVIDER_CONCURRENCY_LIMIT=4 \
ZHIPU_PROVIDER_CONCURRENCY_LIMIT=2 \
LLM_PRIMARY_PROVIDER=MiniMax \
.venv/bin/backtester --ab-compare --mode pipeline \
--start-date 2025-12-01 --end-date 2026-03-04 \
--train-months 2 --test-months 1 --step-months 1 \
--model-provider Zhipu --model-name glm-4.7 \
--analysts-all \
--report-file data/reports/ab_weighted_dual_provider.md \
--report-json data/reports/ab_weighted_dual_provider.jsonRun the supervisor so that all future restart attempts also keep the same concurrency:
.venv/bin/python scripts/supervise_ab_compare.py \
--start-date 2025-12-01 --end-date 2026-03-04 \
--train-months 2 --test-months 1 --step-months 1 \
--analyst-concurrency-limit 3 \
--report-file data/reports/ab_walk_forward_first_pilot.md \
--report-json data/reports/ab_walk_forward_first_pilot.json \
--first-reset '2026-03-08 05:00:00'Every shared LLM call now writes structured metrics into the logs/ directory.
- One JSONL file records every logical LLM attempt, including provider, model, agent, duration, success/failure, and whether the error was a rate-limit.
- One summary JSON file keeps an aggregated view by provider, model, and agent so you can quickly judge where the bottleneck is.
Example output files:
logs/llm_metrics_20260310_183246.jsonllogs/llm_metrics_20260310_183246.summary.json
Summarize a metrics file after a run:
.venv/bin/python scripts/summarize_llm_metrics.py logs/llm_metrics_20260310_183246.jsonlYou can also save the aggregated result:
.venv/bin/python scripts/summarize_llm_metrics.py \
logs/llm_metrics_20260310_183246.jsonl \
--output data/reports/llm_metrics_summary.jsonRepeated stock-selection, replay, and backtesting windows often reuse the same Tushare and AKShare payloads. The project now persists hot market-data responses through the multi-layer cache in src/data/enhanced_cache.py, so overlapping reruns can hit the local SQLite cache instead of refetching from upstream providers.
The per-ticker CSVs under data/price_cache/ are also local runtime caches for A-share OHLCV snapshots. Keep them on your machine, refresh them through the existing post-market workflows, and do not commit them to Git.
Default cache location:
~/.cache/ai-hedge-fund/cache.sqlite- Override with
DISK_CACHE_PATH=/custom/path/cache.sqlite
Inspect cache runtime info and counters:
.venv/bin/python scripts/manage_data_cache.py statsWrite the same runtime payload to a file:
.venv/bin/python scripts/manage_data_cache.py stats \
--output data/reports/data_cache_stats.jsonClear the local cache explicitly:
.venv/bin/python scripts/manage_data_cache.py clear --yesValidate cross-process reuse on a representative trade date:
source .env && \
.venv/bin/python scripts/validate_data_cache_reuse.py \
--trade-date 20260305 \
--ticker 300724 \
--output data/reports/data_cache_reuse_20260305.jsonRun a cold-vs-warm benchmark summary in one command:
source .env && \
.venv/bin/python scripts/benchmark_data_cache_reuse.py \
--trade-date 20260305 \
--ticker 300724 \
--clear-first \
--output data/reports/data_cache_benchmark_20260305.json \
--markdown-output data/reports/data_cache_benchmark_20260305.md \
--append-markdown-to data/reports/window_review_20260305.mdInterpretation guidelines:
- The first run should usually show
missesandsetsincreasing. - Re-running the exact same command should shift the session toward
disk_hitswith few or no newmisses. manage_data_cache.py statsnow also reportsdisk_entry_countanddisk_file_size_bytes, which is useful when you want to confirm the local cache is actually growing across experiments.session_summary.jsonfor paper-trading runs now also recordsdata_cache,data_cache.session_stats, andartifacts.data_cache_pathfor later inspection.scripts/run_paper_trading.pyalso supports--cache-benchmark, so a paper-trading run can automatically emitdata_cache_benchmark.json,data_cache_benchmark.md, and an appendedwindow_review.mdin the same output directory.benchmark_data_cache_reuse.pywraps the first and second runs into one JSON summary, can emit a standalone Markdown snippet, and can append that snippet directly into an existing experiment note.- For a Chinese quickstart focused on cache inspection and reuse validation, see
docs/old-zh-cn/manual/data-cache-reuse-manual.md.
Run a paper-trading session and automatically attach a post-run cache benchmark:
source .env && \
.venv/bin/python scripts/run_paper_trading.py \
--start-date 2026-02-02 \
--end-date 2026-03-13 \
--tickers 300724 \
--cache-benchmarkIf you want the benchmark to force a cold-start comparison first:
source .env && \
.venv/bin/python scripts/run_paper_trading.py \
--start-date 2026-02-02 \
--end-date 2026-03-13 \
--tickers 300724 \
--cache-benchmark \
--cache-benchmark-clear-firstThat paper-trading output directory will now contain:
session_summary.jsonwithdata_cache_benchmarkdata_cache_benchmark.jsondata_cache_benchmark.mdwindow_review.mdwith the benchmark summary appended
If you are running under unstable quota conditions, increase concurrency gradually. In practice, moving from 2 to 3 is usually a safer step than jumping directly to 4 or higher.
Note: The --ollama, --start-date, and --end-date flags work for the backtester, as well!
The new way to run the AI Hedge Fund is through our web application that provides a user-friendly interface. This is recommended for users who prefer visual interfaces over command line tools.
Please see detailed instructions on how to install and run the web application here.
- Fork the repository
- Create a feature branch
- Commit your changes
- Push to the branch
- Create a Pull Request
Important: Please keep your pull requests small and focused. This will make it easier to review and merge.
If you have a feature request, please open an issue and make sure it is tagged with enhancement.
This project is licensed under the MIT License - see the LICENSE file for details.