Skip to main content

TradingAgents: Multi-Agents LLM Financial Trading Framework

Project description

TradingAgents

PyPI version python uv Ruff Pydantic v2 tests code-quality Ask DeepWiki license PRs contributors

๐Ÿš€ TradingAgents is a multi-agent LLM financial trading framework that leverages large language models to simulate analyst teams, research debates, and portfolio management decisions for stock trading analysis.

Other Languages: English | ็น้ซ”ไธญๆ–‡ | ็ฎ€ไฝ“ไธญๆ–‡

โœจ Highlights

  • Built on LangGraph for robust multi-agent orchestration
  • Multi-agent architecture: Analyst Team โ†’ Situation Summariser โ†’ Research Team โ†’ Trader โ†’ Risk Management โ†’ Portfolio Management
  • Structured trade recommendation โ€” the Risk Judge emits a typed TradeRecommendation (signal, size, entry reference, target, stop, horizon, confidence, currency, rationale) parsed from a JSON block plus the canonical FINAL TRANSACTION PROPOSAL line
  • Backtest harness โ€” tradingagents backtest drives propagate() across a date grid, scores realised returns from cached OHLCV, reports Sharpe / hit-rate / drawdown plus buy-and-hold / HOLD / SMA / random benchmarks, train / validation / test split metrics, signal distribution, warning rate, and supports a --dry-run stub-LLM mode for harness validation
  • Powered by langchain.chat_models.init_chat_model; supports any provider keyed via an explicit llm_provider field plus a model name (OpenAI, Anthropic, Google Gemini, xAI (Grok), OpenRouter, Ollama, HuggingFace, LiteLLM)
  • Unified reasoning_effort knob (low / medium / high / xhigh / max) mapped per provider to native parameters (Anthropic effort, OpenAI reasoning_effort, Google thinking_level)
  • Market data powered by yfinance for OHLCV, fundamentals, technical indicators, news, insider transactions, analyst ratings, earnings calendar, institutional holders, short interest, dividends / splits, and regional macro context (local index, ^TNX, ^VIX)
  • Locale-aware Google News routing โ€” exchange suffix (.TW, .HK, .T, .DE, ...) and resolved bare digit tickers (2330, 8069) select the right hl / gl / ceid; ticker-only RSS searches fall back to resolved company-name queries to reduce ambiguous results
  • Point-in-time-safe data fetchers โ€” graph runs install a RunContext and tool wrappers reject future curr_date / start_date / end_date with [TOOL_ERROR]; historical dataflows still filter by reporting-lag-adjusted as_of dates
  • Pydantic-based configuration with strict typing and validation
  • Analysis results automatically saved to results/ with organized subfolders (versioned state-log schema with built-in v1 โ†’ v2 migration for the reflect CLI)
  • Modern src/ layout with full type-annotated code
  • Fast dependency management via uv
  • Pre-commit suite: ruff, mdformat, codespell, mypy, uv hooks
  • Pytest with coverage; MkDocs Material documentation

๐Ÿš€ Quick Start

git clone https://github.com/Mai0313/TradingAgents.git
cd TradingAgents
make uv-install               # Install uv (only needed once)
uv sync                       # Install dependencies
cp .env.example .env          # Configure your API keys

Configure API Keys

Edit .env and set your LLM provider keys:

# LLM Providers (set the one you use)
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GOOGLE_API_KEY=AIza...
XAI_API_KEY=...
OPENROUTER_API_KEY=...

Usage

Command line / interactive

The package ships a tradingagents console script with four subcommands:

uv run tradingagents tui                     # interactive questionary prompts
uv run tradingagents cli                     # run with all defaults
uv run tradingagents cli --ticker AAPL \
    --deep_think_llm gpt-5 \
    --quick_think_llm gpt-5-mini             # override flags
uv run tradingagents reflect --ticker AAPL --date 2024-05-10 --returns 0.032   # post-trade reflection
uv run tradingagents backtest --tickers GOOG,2330.TW \
    --start 2024-01-01 --end 2024-06-30 \
    --frequency weekly --horizon-days 5 \
    --budget-cap-usd 25                      # grid backtest with LLM cost cap
uv run tradingagents backtest --tickers GOOG \
    --start 2024-01-01 --end 2024-06-30 --dry-run   # validate the harness in seconds, $0 cost
uv run tradingagents --help                  # rich-rendered top-level help
uv run tradingagents cli --help              # rich-rendered per-command flags

tradingagents tui walks you through every parameter (ticker, date, provider, models, debate rounds, analyst selection, ...) via interactive prompts; tradingagents cli is the same flow but driven entirely by command-line flags so it composes with shell scripts and CI. tradingagents reflect re-runs the post-trade reflector against a previously-recorded state log and appends lessons to the BM25 memories. tradingagents backtest iterates propagate() over a date grid, marks each decision to market against the next-bar close, reports Sharpe / hit rate / expectancy / drawdown, records split metrics / signal distribution / warning rate, and enforces a --budget-cap-usd based on token-aware cost tracking. Add --dry-run to swap in an in-memory stub LLM that produces canned TradeRecommendation payloads โ€” useful for validating the harness against real cached OHLCV without burning API budget. Both interactive routes stream LangGraph agent messages through Rich panels (Markdown for prose, JSON-pretty for tool output, truncated when payloads exceed a screenful). python -m tradingagents <subcommand> works as well.

Programmatic

from tradingagents.config import TradingAgentsConfig
from tradingagents.graph.trading_graph import TradingAgentsGraph

config = TradingAgentsConfig(
    llm_provider="openai",
    deep_think_llm="gpt-5",
    quick_think_llm="gpt-5-mini",
    max_debate_rounds=1,
    max_risk_discuss_rounds=1,
    max_recur_limit=100,
    reasoning_effort="medium",
    response_language="en-US",
)

ta = TradingAgentsGraph(debug=True, config=config)
state, recommendation = ta.propagate("NVDA", "2024-05-10")
print(recommendation.signal, recommendation.size_fraction, recommendation.confidence)
print(recommendation.rationale)

propagate() returns (AgentState, TradeRecommendation). TradeRecommendation is a Pydantic model with:

  • signal: Literal["BUY", "SELL", "HOLD"] โ€” the canonical direction
  • size_fraction: float (0.0 โ€“ 1.0) โ€” position size as a fraction of available capital; HOLD is normalised to 0.0
  • entry_reference_price: float | None, target_price: float | None, stop_loss: float | None, time_horizon_days: int | None โ€” trade plan and as-of price anchor
  • confidence: float (0.0 โ€“ 1.0), currency: str | None, rationale: str, warning_message: str | None (set when the parser falls back or normalises inconsistent output)

The structured form is also persisted to AgentState.final_trade_recommendation and the state log JSON, so the reflect and backtest subcommands can rebuild it later.

response_language is a BCP 47 tag from the ResponseLanguage Literal (zh-TW, zh-CN, en-US, ja-JP, ko-KR, de-DE); pick the closest one to the language you want the agents to reason in.

TradingAgentsGraph.propagate also accepts an optional on_message callback (Callable[[AnyMessage], None]) that fires once per streamed LangGraph message โ€” useful for plugging in your own renderer; the bundled CLI / TUI use this hook to drive the Rich panels.

llm_provider is one of the langchain.chat_models.init_chat_model registry keys (openai, anthropic, google_genai, xai, openrouter, ollama, huggingface, litellm); deep_think_llm / quick_think_llm take the model name as accepted by that provider (gpt-5, claude-sonnet-4-6, gemini-3-pro-preview, grok-4, ...).

max_recur_limit must be at least 30 โ€” the Situation Summariser node introduced in the P0 rollout adds one superstep to the graph, so the previous floor of 25 is no longer enough for the minimum-round topology. The default in the CLI / TUI is 100.

Set response_language to control the language requested in all agent prompts. Tickers without exchange suffixes are resolved automatically with Yahoo Finance Search. For Taiwan stocks, pass the numeric stock code directly, such as 2330, 2408, or 8069; explicit Yahoo Finance symbols such as 2330.TW, 8069.TWO, AAPL, and TSM are also supported.

config = TradingAgentsConfig(
    llm_provider="openai",
    deep_think_llm="gpt-5",
    quick_think_llm="gpt-5-mini",
    max_debate_rounds=1,
    max_risk_discuss_rounds=1,
    max_recur_limit=100,
    response_language="zh-TW",
)

ta = TradingAgentsGraph(config=config)
state, recommendation = ta.propagate("2330", "2024-05-10")

Backtest

The same propagate() flow can be driven over a date grid via the Backtester Pydantic model (or the tradingagents backtest CLI shown above):

from tradingagents.backtest import BacktestConfig, Backtester

cfg = BacktestConfig(
    tickers=["GOOG", "2330.TW"],
    start_date="2024-01-01",
    end_date="2024-06-30",
    frequency="weekly",  # or "daily"
    horizon_days=5,  # mark-to-market window per decision
    transaction_cost_bps=10.0,  # per-side cost
    slippage_bps=0.0,  # per-side slippage
    allow_short=None,  # None uses market-aware defaults
    budget_cap_usd=25.0,  # raises CostBudgetExceeded and stops the loop
    reflect_after_each_trade=True,
    walk_forward=True,
    split_fractions=(0.6, 0.2, 0.2),
    trading_config=config,
)
report = Backtester(config=cfg).run()
print(report.sharpe, report.hit_rate, report.warning_rate, report.estimated_cost_usd)
print(report.benchmarks["buy_and_hold"].total_return)

The harness instantiates a fresh TradingAgentsGraph per ticker (per-run state is mutable), reuses the same CostTracker callback across tickers so the budget cap accumulates, scores each decision against the next-bar OHLCV from the existing 15-year cache, applies transaction cost / slippage / shorting rules, and records benchmark returns for buy-and-hold, always-HOLD, simple SMA crossover, and a deterministic random baseline. With walk_forward=True, memory is updated only after an earlier trade has been scored. BacktestReport also records train / validation / test split reports, signal_distribution, warning_rate, prompt_versions, and model names. Pass dry_run=True to swap in the in-memory StubChatModel for harness validation.

๐Ÿ“ Project Structure

src/
โ””โ”€โ”€ tradingagents/
    โ”œโ”€โ”€ agents/           # Agent implementations
    โ”‚   โ”œโ”€โ”€ analysts/     # Market, News, News-Sentiment, Fundamentals analysts
    โ”‚   โ”œโ”€โ”€ managers/     # Research & Portfolio managers
    โ”‚   โ”œโ”€โ”€ preprocessors/# Situation Summariser node (analyst reports โ†’ BM25 query)
    โ”‚   โ”œโ”€โ”€ researchers/  # Bull & Bear researchers
    โ”‚   โ”œโ”€โ”€ risk_mgmt/    # Risk management agents
    โ”‚   โ”œโ”€โ”€ trader/       # Trader agent
    โ”‚   โ”œโ”€โ”€ prompts/      # All agent prompts as .md templates
    โ”‚   โ””โ”€โ”€ utils/        # Shared agent utilities (memory, tools, state)
    โ”œโ”€โ”€ dataflows/        # Data ingestion via yfinance + Google News RSS + provider adapters
    โ”œโ”€โ”€ graph/            # LangGraph trading graph setup
    โ”‚   โ”œโ”€โ”€ trading_graph.py    # Main TradingAgentsGraph orchestrator
    โ”‚   โ”œโ”€โ”€ signal_processing.py# TradeRecommendation parser + JSON / canonical-line precedence
    โ”‚   โ””โ”€โ”€ reflection.py       # Post-trade reflector
    โ”œโ”€โ”€ interface/        # CLI / TUI / backtest / reflect implementations
    โ”‚   โ”œโ”€โ”€ cli.py        # fire-driven flag runner (run_cli)
    โ”‚   โ”œโ”€โ”€ tui/          # textual-based interactive app
    โ”‚   โ”œโ”€โ”€ backtest.py   # fire-driven backtest runner (run_backtest)
    โ”‚   โ”œโ”€โ”€ reflect.py    # fire-driven reflect runner (run_reflect)
    โ”‚   โ”œโ”€โ”€ display.py    # rich-based LangChain message renderer + TradeRecommendation panel
    โ”‚   โ””โ”€โ”€ help.py       # rich-based replacement for fire's pager help
    โ”œโ”€โ”€ backtest.py       # Backtester engine, CostTracker, StubChatModel, BacktestReport
    โ”œโ”€โ”€ llm.py            # Chat model construction (init_chat_model wrapper + reasoning_effort mapping)
    โ”œโ”€โ”€ config.py         # TradingAgentsConfig schema + global singleton
    โ”œโ”€โ”€ __init__.py       # Top-level public API (TradingAgentsConfig, TradingAgentsGraph)
    โ””โ”€โ”€ __main__.py       # Console script entry point (fire dispatcher with rich help)

๐Ÿค– Agent Workflow

TradingAgents orchestrates 12 LLM agents plus 3 supporting components through a LangGraph StateGraph. Every run goes through 4 sequential phases linked by a Situation Summariser, and the state (reports, debate transcripts, trade decisions) is persisted through a Pydantic AgentState shared across all nodes.

Phase 1 โ€” Analyst Team (Data Collection)

By default, four analysts run in sequence; selected_analysts can run a subset. Each analyst has its LLM bound to a specific set of yfinance-backed @tool functions from the central tool registry, and loops with its own ToolNode until no more tool calls are emitted. Between analysts a Msg Clear node resets the conversation history (emitting RemoveMessage + a HumanMessage("Continue") placeholder for Anthropic compatibility).

Analyst LLM-bound tools Writes to state
Market Analyst get_stock_data, get_indicators, get_dividends_splits market_report
News Sentiment Analyst get_news sentiment_report
News Analyst get_news, get_global_news, get_insider_transactions, get_market_context, get_earnings_calendar news_report
Fundamentals Analyst get_fundamentals, get_balance_sheet, get_cashflow, get_income_statement, get_analyst_ratings, get_institutional_holders, get_short_interest, get_dividends_splits fundamentals_report

During propagate(), a run-level RunContext records the active ticker, trade date, and response language. Tool wrappers reject any future curr_date, start_date, or end_date with [TOOL_ERROR] rather than silently clamping the request. Historical dataflows still filter their output by an as_of date (reporting-lag-adjusted) so back-tests cannot leak future filings. Tools that have no historical archive in yfinance (get_institutional_holders, get_short_interest) deliberately return a [NO_DATA] sentinel for back-dated curr_date instead of leaking the current snapshot. Historical get_earnings_calendar also omits the current-only yfinance.calendar snapshot; forward rows keep only date / estimate fields with a source-limitation note.

Analyst reports are evidence-gated: if an analyst produces a final report before any tool result is observed, the node writes a [TOOL_ERROR] warning report instead of treating ungrounded prose as evidence. The prompts use fixed default windows: Market OHLCV / indicators use 90 days, news / sentiment use 14 days, and dividends / splits use 365 days ending at the trade date.

Supported technical indicators (selected by the Market Analyst, 6 โ€“ 8 per run): close_50_sma, close_200_sma, close_10_ema, macd, macds, macdh, rsi, mfi, cci, wr, kdjk, kdjd, stochrsi, adx, pdi, boll, boll_ub, boll_lb, atr, supertrend, supertrend_ub, supertrend_lb, vwma, obv. The Market Analyst is asked to pick a balanced mix of trend / momentum / volatility / volume signals; an insufficient-data preamble (DATA WARNING) is emitted whenever the underlying history has fewer than 50 bars (so long-window indicators are unreliable).

Phase 1.5 โ€” Situation Summariser

After the last selected analyst's Msg Clear, a single Situation Summariser node (quick-thinking LLM) distils the selected analyst reports into a compact โ‰ค400-token structured snapshot. Missing reports from an analyst subset are marked unavailable rather than invented. The summary populates state.situation_summary and becomes the BM25 retrieval query for every downstream memory lookup, replacing the previous 10-20 KB combined_reports query that was too lexically diffuse to surface relevant past situations.

Phase 2 โ€” Research Debate

  • Bull Researcher and Bear Researcher debate for max_debate_rounds rounds (default: 1 round each), taking turns based on who spoke last. Each researcher retrieves top-k BM25 matches from its own FinancialSituationMemory and sees both the past situation snapshot and the lesson learned (not just the lesson string).
  • Termination: count >= 2 * max_debate_rounds routes the graph to Research Manager (deep-thinking LLM), which evaluates the full debate, produces the investment_plan, and populates investment_debate_state.judge_decision.

Phase 3 โ€” Trader

Trader (quick-thinking LLM) consumes investment_plan plus the top-k trader_memory matches and produces trader_investment_plan. Its output must end with FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL**.

Phase 4 โ€” Risk Control Debate

Three debaters rotate in a fixed order โ€” Aggressive โ†’ Conservative โ†’ Neutral โ†’ Aggressive โ†’ โ€ฆ โ€” for max_risk_discuss_rounds rounds (default: 1 round per stance). Termination: count >= 3 * max_risk_discuss_rounds routes to the Risk Judge (deep-thinking LLM via create_risk_manager), which writes final_trade_decision. The Risk Judge prompt requires a fenced ```json block containing the TradeRecommendation schema (signal, size_fraction, entry_reference_price, target_price, stop_loss, time_horizon_days, confidence, currency, rationale, warning_message) plus a canonical FINAL TRANSACTION PROPOSAL: **<signal>** line. The deterministic SignalProcessor parses both โ€” the canonical line wins on disagreement, HOLD size is forced to 0.0, and missing / malformed JSON falls back to conservative defaults (size 0.25 for BUY/SELL, 0.0 for HOLD, confidence 0.5).

Supporting components

  • Situation Summariser โ€” distils analyst reports into the BM25 retrieval query so memory lookups stay lexically tight.
  • FinancialSituationMemory โ€” BM25Okapi-backed per-agent memory (5 instances: bull, bear, trader, invest_judge, risk_manager). Purely lexical, no external embeddings API required. Zero-overlap BM25 matches are filtered out, and each match surfaces both the past situation snapshot and the lesson so agents judge analogy applicability before applying it.
  • Reflector โ€” After the trade outcome is known, TradingAgentsGraph.reflect_and_remember(returns_losses) runs post-trade reflection against each of the 5 memories. Memory JSONL rows include metadata (ticker, trade_date, signal, realised_return, component, prompt_version) alongside the situation and lesson. When backtest outcome context is available, the prompt includes entry / exit prices, horizon, benchmarks, and final recommendation; the required reflection rubric is parsed into structured scores for later trend analysis.

Flow Diagram

START
  โ”‚
  โ–ผ
[Market Analyst โ‡„ tools_market] โ†’ Msg Clear
  โ”‚
  โ–ผ
[News Sentiment Analyst โ‡„ tools_social] โ†’ Msg Clear
  โ”‚
  โ–ผ
[News Analyst โ‡„ tools_news] โ†’ Msg Clear
  โ”‚
  โ–ผ
[Fundamentals Analyst โ‡„ tools_fundamentals] โ†’ Msg Clear
  โ”‚
  โ–ผ
Situation Summariser  โ†’  state.situation_summary
  โ”‚
  โ–ผ
[Bull Researcher โ‡„ Bear Researcher] ร— max_debate_rounds
  โ”‚
  โ–ผ
Research Manager  โ†’  Trader
                        โ”‚
                        โ–ผ
[Aggressive โ†’ Conservative โ†’ Neutral] ร— max_risk_discuss_rounds
  โ”‚
  โ–ผ
Risk Judge  โ†’  SignalProcessor (TradeRecommendation)  โ†’  END

Per-run logs are written under results/<TICKER>/: full_states_log_<TICKER>_<DATE>.json (v2 schema wrapped under {"schema_version": 2, "runs": {...}}), conversation_log_<TICKER>_<DATE>.txt, and conversation_log_<TICKER>_<DATE>.json (the base path resolves from TradingAgentsConfig.results_dir, which defaults to ./results). The reflect CLI transparently migrates v1 logs on read so older runs remain replayable.

๐Ÿค Contributing

For development instructions including documentation, testing, and Docker services, please see CONTRIBUTING.md.

  • Open issues/PRs
  • Follow the coding style (ruff, type hints)
  • Use Conventional Commit messages and descriptive PR titles

๐Ÿ“„ License

MIT โ€” see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tradingagents-0.7.0.tar.gz (450.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tradingagents-0.7.0-py3-none-any.whl (163.7 kB view details)

Uploaded Python 3

File details

Details for the file tradingagents-0.7.0.tar.gz.

File metadata

  • Download URL: tradingagents-0.7.0.tar.gz
  • Upload date:
  • Size: 450.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for tradingagents-0.7.0.tar.gz
Algorithm Hash digest
SHA256 94f190f8e23c3246a538d796ab159d7f50c3df3f36de73b5492e9dc8a411ade6
MD5 598e41a70bd2342a4635192cbd15681d
BLAKE2b-256 fd2092dd994d18702b3a2d586e4a8b67c7f841ba2194e30a4443a11f68b41457

See more details on using hashes here.

File details

Details for the file tradingagents-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: tradingagents-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 163.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for tradingagents-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f7d244588b7c03b0af72883f2fae875434ae4104410338f145ad9badac23cff2
MD5 764488e8a3ee5670bca9bd6ecdc42271
BLAKE2b-256 2d1200736cc7d5092137da186c4a3efe4a827acefee388bbe9c255c8fb80fd84

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page