diff --git a/CHANGELOG.md b/CHANGELOG.md index 66b80e07..a86a14d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- Comprehensive documentation structure (Issue #52) + - Organized `docs/` directory with structured documentation sections + - Quick start guide at `docs/QUICKSTART.md` + - Architecture documentation in `docs/architecture/` (multi-agent-system, data-flow, llm-integration) + - API reference documentation in `docs/api/` (trading-graph, agents, dataflows) + - Developer guides in `docs/guides/` (adding-new-analyst, adding-llm-provider, adding-data-vendor, configuration) + - Testing documentation in `docs/testing/` (README, running-tests, writing-tests) + - Development setup guide in `docs/development/` + - Central documentation index at `docs/README.md` with navigation and key concepts + - Updated PROJECT.md DOCUMENTATION MAP section to reference new docs/ structure + - Added Documentation section to README.md with links to key guides - Export reports to file with metadata (Issue #21) - YAML frontmatter formatting for report metadata [file:tradingagents/utils/report_exporter.py:63-111](tradingagents/utils/report_exporter.py) - Report creation with combined YAML frontmatter and markdown content [file:tradingagents/utils/report_exporter.py:112-136](tradingagents/utils/report_exporter.py) diff --git a/PROJECT.md b/PROJECT.md index 821422c9..b4712fad 100644 --- a/PROJECT.md +++ b/PROJECT.md @@ -1,53 +1,83 @@ -# PROJECT.md - TradingAgents +# PROJECT.md - TradingAgents Investment Platform -> Multi-Agent LLM Financial Trading Framework -> Last Updated: 2025-12-25 +> Multi-Agent LLM Investment Platform with Execution Capabilities +> Last Updated: 2025-12-26 --- ## PROJECT VISION -TradingAgents is a multi-agent trading framework that mirrors the dynamics of real-world trading firms. By deploying specialized LLM-powered agents—from fundamental analysts, sentiment experts, and technical analysts to traders and risk management teams—the platform collaboratively evaluates market conditions and informs trading decisions through dynamic agent discussions. +TradingAgents is evolving from a signal-generation research framework into a **complete investment platform** that: -**Research Focus**: This framework is designed for research purposes to explore how multi-agent LLM systems can approach complex financial decision-making. +1. **Analyzes markets** using multi-agent LLM collaboration (existing capability) +2. **Executes trades** via broker APIs (Alpaca, Interactive Brokers) +3. **Manages portfolios** with performance tracking and Australian CGT compliance +4. **Simulates strategies** to compare effectiveness before risking capital +5. **Learns from outcomes** using a layered memory system (FinMem pattern) + +**Target Markets:** US Stocks, ETFs, Crypto, Futures, Australian Equities + +**Patterns Borrowed From:** +- **FinMem**: Layered memory system (recency, relevancy, importance scoring) +- **Microsoft Qlib**: Modular loose-coupled architecture +- **Alpaca Bots**: Order execution, position tracking, risk controls --- ## GOALS -### Primary Goals -- [x] Provide a modular multi-agent framework for financial trading analysis -- [x] Support multiple LLM providers (OpenAI, Anthropic, Google, OpenRouter, Ollama) -- [x] Enable configurable data vendors (yfinance, Alpha Vantage, local) -- [x] Implement specialized analyst agents (fundamental, sentiment, news, technical) -- [x] Support researcher debates (bull vs bear perspectives) -- [x] Include risk management and portfolio approval workflow +### Phase 1: Foundation (Current) +- [x] Multi-agent framework for financial analysis +- [x] Multiple LLM providers (OpenAI, Anthropic, Google, OpenRouter, Ollama) +- [x] Data vendors (yfinance, Alpha Vantage, Google News) +- [x] Analyst agents (fundamental, sentiment, news, technical) +- [x] Researcher debates (bull vs bear) +- [x] Risk management workflow +- [ ] **Database layer** for user persistence (#2-7) +- [ ] **Enhanced data layer** - FRED, multi-timeframe, benchmarks (#8-12) -### Secondary Goals -- [ ] Expand backtesting capabilities with Tauric TradingDB -- [ ] Add support for additional asset classes -- [ ] Improve caching and performance optimization -- [ ] Enhance CLI experience with more configuration options +### Phase 2: Enhanced Analysis +- [ ] **Momentum Analyst** - multi-timeframe momentum, ROC, ADX (#13) +- [ ] **Macro Analyst** - FRED interpretation, regime detection (#14) +- [ ] **Correlation Analyst** - cross-asset, sector rotation (#15) +- [ ] **Position Sizing Manager** - Kelly, risk parity, ATR (#16) +- [ ] **Memory System** - FinMem pattern for learning (#18-21) + +### Phase 3: Execution & Portfolio +- [ ] **Broker Integration** - Alpaca (US), IBKR (futures, ASX) (#22-28) +- [ ] **Portfolio Management** - positions, performance, CGT (#29-32) +- [ ] **Simulation Mode** - strategy comparison without real money (#33-37) + +### Phase 4: Alerts & Polish +- [ ] **Alert System** - Email, Slack, SMS (#38-41) +- [ ] **Backtest Engine** - historical simulation (#42-44) +- [ ] **REST API** - external access (#45-48) --- ## SCOPE ### In Scope -- Stock trading analysis and recommendations -- Multi-agent collaboration and debate mechanisms -- Integration with financial data APIs +- Multi-agent LLM analysis (fundamentals, sentiment, news, technical, momentum, macro) +- **Live trade execution** via Alpaca and Interactive Brokers +- **Paper trading / simulation mode** for strategy testing +- Multi-asset support: US stocks, ETFs, crypto, futures, Australian equities +- Portfolio tracking with mark-to-market valuation +- **Australian CGT calculations** with 50% discount for >12 month holdings +- Multi-timeframe analysis (daily, weekly, monthly) +- Macro-economic data integration (FRED) +- User database for profiles, portfolios, settings +- Alert notifications (email, Slack, SMS) +- Backtesting with historical data - CLI and programmatic Python interfaces -- Configuration of LLM models and data sources -- Risk assessment and position management -- Support for multiple LLM providers (OpenAI, Anthropic, Google, OpenRouter, Ollama) +- Optional REST API ### Out of Scope -- Live trading execution (simulation only) -- Cryptocurrency or forex trading -- Real-time streaming data -- Mobile or web interfaces -- Financial advice (research purposes only) +- Mobile or web UI (API only for now) +- Real-time streaming data (polling-based) +- Options trading +- Financial advice (investment decisions are user's responsibility) +- Tax advice (CGT calculations are informational only) --- @@ -73,40 +103,67 @@ TradingAgents is a multi-agent trading framework that mirrors the dynamics of re ## ARCHITECTURE -### System Overview +### System Overview (Extended) ``` -┌─────────────────────────────────────────────────────────────────┐ -│ TradingAgents Graph │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌──────────────────┐ ┌──────────────────┐ │ -│ │ Analyst Team │ │ Researcher Team │ │ -│ ├──────────────────┤ ├──────────────────┤ │ -│ │ • Fundamentals │───▶│ • Bull Researcher│ │ -│ │ • Sentiment │ │ • Bear Researcher│ │ -│ │ • News │ │ (Debates) │ │ -│ │ • Technical │ └────────┬─────────┘ │ -│ └──────────────────┘ │ │ -│ ▼ │ -│ ┌──────────────────┐ ┌──────────────────┐ │ -│ │ Data Vendors │ │ Trader Agent │ │ -│ ├──────────────────┤ └────────┬─────────┘ │ -│ │ • yfinance │ │ │ -│ │ • Alpha Vantage │ ▼ │ -│ │ • OpenAI │ ┌──────────────────┐ │ -│ │ • Google │ │ Risk Management │ │ -│ │ • Local │ ├──────────────────┤ │ -│ └──────────────────┘ │ • Aggressive │ │ -│ │ • Conservative │ │ -│ │ • Neutral │ │ -│ └────────┬─────────┘ │ -│ │ │ -│ ▼ │ -│ ┌──────────────────┐ │ -│ │Portfolio Manager │ │ -│ │ (Final Decision) │ │ -│ └──────────────────┘ │ -└─────────────────────────────────────────────────────────────────┘ +┌─────────────────────────────────────────────────────────────────────┐ +│ DATA LAYER │ +├─────────────────────────────────────────────────────────────────────┤ +│ yfinance │ Alpha Vantage │ FRED (NEW) │ Alpaca │ Multi-Timeframe │ +└─────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────┐ +│ ANALYSIS LAYER │ +├─────────────────────────────────────────────────────────────────────┤ +│ Market │ Momentum │ Macro │ Correlation │ News │ Fundamentals │ +│ Analyst │ Analyst │ Analyst │ Analyst │ │ │ +│ │ (NEW) │ (NEW) │ (NEW) │ │ │ +├─────────────────────────────────────────────────────────────────────┤ +│ Bull ←── Debate ──→ Bear → Research Manager │ +├─────────────────────────────────────────────────────────────────────┤ +│ Trader → Signal + Confidence Score │ +├─────────────────────────────────────────────────────────────────────┤ +│ Risk Debate → Position Sizing Manager (NEW) │ +└─────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────┐ +│ STRATEGY LAYER (NEW) │ +├─────────────────────────────────────────────────────────────────────┤ +│ Signal-to-Order │ Position Sizing │ Timeframe Coordinator │ +└─────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────┐ +│ EXECUTION LAYER (NEW) │ +├─────────────────────────────────────────────────────────────────────┤ +│ Order Validator │ Risk Controls │ Broker Router │ +│ │ │ (Paper / Alpaca / IBKR) │ +└─────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────┐ +│ PORTFOLIO LAYER (NEW) │ +├─────────────────────────────────────────────────────────────────────┤ +│ Position Tracker │ Portfolio State │ Performance │ CGT Calculator │ +└─────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────┐ +│ MEMORY & LEARNING (Enhanced) │ +├─────────────────────────────────────────────────────────────────────┤ +│ Layered Memory (FinMem) │ Trade History │ Risk Profiles │ +└─────────────────────────────────────────────────────────────────────┘ +``` + +### Broker Routing +``` +Asset Type → Broker Selection +───────────────────────────────────── +US Stocks/ETFs → Alpaca +Crypto → Alpaca +Futures (GC, SI) → Interactive Brokers +ASX (Australia) → Interactive Brokers ``` ### Technology Stack @@ -133,49 +190,121 @@ TradingAgents is a multi-agent trading framework that mirrors the dynamics of re ``` TradingAgents/ -├── tradingagents/ # Main package -│ ├── agents/ # LLM agent implementations -│ │ ├── analysts/ # Analyst agents (fundamental, sentiment, news, technical) -│ │ ├── researchers/ # Bull/bear researcher debate agents -│ │ ├── risk_mgmt/ # Risk management debators -│ │ ├── trader/ # Trader agent -│ │ ├── managers/ # Research and risk managers -│ │ └── utils/ # Agent utilities, tools, states -│ ├── dataflows/ # Data vendor integrations -│ │ ├── alpha_vantage*.py # Alpha Vantage API modules -│ │ ├── y_finance.py # yfinance integration -│ │ ├── google.py # Google news integration -│ │ └── local.py # Local data vendor -│ ├── graph/ # LangGraph workflow -│ │ ├── trading_graph.py # Main graph definition -│ │ ├── propagation.py # Forward propagation logic -│ │ ├── reflection.py # Agent reflection -│ │ └── signal_processing.py -│ └── default_config.py # Default configuration -├── cli/ # Command-line interface -│ ├── main.py # CLI entry point -│ ├── models.py # CLI data models -│ └── utils.py # CLI utilities -├── main.py # Quick start example -├── test.py # Basic tests -├── requirements.txt # Python dependencies -├── pyproject.toml # Project metadata -└── assets/ # Documentation images +├── tradingagents/ # Main package (existing + enhanced) +│ ├── agents/ +│ │ ├── analysts/ # Analyst agents +│ │ │ ├── fundamentals_analyst.py +│ │ │ ├── sentiment_analyst.py +│ │ │ ├── news_analyst.py +│ │ │ ├── market_analyst.py (technical) +│ │ │ ├── momentum_analyst.py # NEW +│ │ │ ├── macro_analyst.py # NEW +│ │ │ └── correlation_analyst.py # NEW +│ │ ├── managers/ +│ │ │ └── position_sizing_manager.py # NEW +│ │ └── ... +│ ├── dataflows/ +│ │ ├── fred.py # NEW - Federal Reserve data +│ │ ├── multi_timeframe.py # NEW - Weekly/Monthly +│ │ ├── benchmark.py # NEW - SPY, sectors +│ │ └── ... +│ └── memory/ # NEW - FinMem pattern +│ ├── layered_memory.py +│ ├── trade_history.py +│ └── risk_profiles.py +│ +├── execution/ # NEW - Broker integration +│ ├── brokers/ +│ │ ├── base.py +│ │ ├── broker_router.py +│ │ ├── alpaca_broker.py +│ │ ├── ibkr_broker.py +│ │ └── paper_broker.py +│ ├── orders/ +│ └── risk_controls/ +│ +├── portfolio/ # NEW - Portfolio management +│ ├── portfolio_state.py +│ ├── position_tracker.py +│ ├── performance.py +│ └── tax_calculator.py # Australian CGT +│ +├── simulation/ # NEW - Strategy testing +│ ├── scenario_runner.py +│ ├── strategy_comparator.py +│ └── economic_conditions.py +│ +├── strategy/ # NEW +│ ├── signal_to_order.py +│ ├── position_sizing.py +│ └── strategy_executor.py +│ +├── backtest/ # NEW +│ ├── backtest_engine.py +│ └── results_analyzer.py +│ +├── alerts/ # NEW +│ ├── alert_manager.py +│ └── channels/ +│ +├── database/ # NEW - User persistence +│ ├── models/ +│ │ ├── user.py +│ │ ├── portfolio.py +│ │ ├── settings.py +│ │ └── trade.py +│ ├── migrations/ +│ └── db.py +│ +├── api/ # NEW - REST API (optional) +│ └── app.py +│ +├── cli/ # Existing CLI +├── main.py +└── scripts/ + └── create_issues.py # GitHub issue creation ``` --- ## TESTING STRATEGY -### Current State -- Basic test file exists (`test.py`) -- No formal test framework configured +### Test Organization (REQUIRED) +All new code MUST include tests organized as follows: -### Recommended Testing -- Unit tests for individual agents -- Integration tests for data vendor APIs -- End-to-end tests for trading graph propagation -- Mock LLM responses for deterministic testing +``` +tests/ +├── conftest.py # Shared fixtures (LLM mocks, env mocks) +├── unit/ # Fast, mocked tests +│ ├── conftest.py # Unit-specific fixtures +│ └── test_*.py +├── integration/ # Tests with real internal components +│ ├── conftest.py # Integration fixtures +│ └── test_*.py +└── e2e/ # End-to-end tests + └── test_*.py +``` + +### Testing Requirements +1. **TDD Approach**: Write tests BEFORE implementation +2. **Unit Tests**: All new functions must have unit tests +3. **Integration Tests**: All new features must have integration tests +4. **Mocking**: Use fixtures in conftest.py for LLM and API mocking +5. **Markers**: Use `@pytest.mark.unit`, `@pytest.mark.integration`, `@pytest.mark.e2e` + +### Test Fixtures (conftest.py) +Standard fixtures that MUST be used: +- `mock_env_openrouter`, `mock_env_openai`, `mock_env_anthropic` - Environment isolation +- `mock_langchain_classes` - LLM class mocking +- `mock_chromadb` - Database mocking (uses `get_or_create_collection`) +- `mock_yfinance`, `mock_alpha_vantage` - Data vendor mocking + +### Running Tests +```bash +pytest tests/unit -m unit # Fast unit tests only +pytest tests/integration -m integration # Integration tests +pytest tests/ --tb=short # All tests +``` --- @@ -183,25 +312,81 @@ TradingAgents/ | Document | Purpose | |----------|---------| -| README.md | Installation, usage, API reference | +| README.md | Installation, usage, API reference, feature overview | +| PROJECT.md | This file - project roadmap, architecture, configuration | | LICENSE | MIT License | -| PROJECT.md | This file - project overview | +| docs/ | Comprehensive documentation structure (see below) | | assets/ | Architecture diagrams, CLI screenshots | +### Documentation Structure (`docs/`) +Located in `/docs/` directory with the following sections: + +- **Getting Started** + - `QUICKSTART.md` - Get up and running with TradingAgents + - `development/setup.md` - Development environment setup + - `guides/configuration.md` - Configuration reference for LLM providers and data vendors + +- **Architecture & Design** + - `architecture/multi-agent-system.md` - Agent roles and collaboration patterns + - `architecture/data-flow.md` - System data flow and integrations + - `architecture/llm-integration.md` - LLM provider abstraction and selection + +- **API Reference** + - `api/trading-graph.md` - Core TradingGraph orchestration API + - `api/agents.md` - Agent interfaces and implementations + - `api/dataflows.md` - Data vendor integrations and APIs + +- **Developer Guides** + - `guides/adding-new-analyst.md` - Extend framework with custom analysts + - `guides/adding-llm-provider.md` - Integrate new LLM providers + - `guides/adding-data-vendor.md` - Add new data vendor integrations + +- **Testing** + - `testing/README.md` - Testing philosophy and overview + - `testing/running-tests.md` - Test suite execution guide + - `testing/writing-tests.md` - Guidelines for writing new tests + +- **Development** + - `development/setup.md` - Development environment configuration + - `development/contributing.md` - Contributing guidelines + +**For full documentation index, see `docs/README.md`** + --- ## CURRENT SPRINT - +### Sprint: Platform Foundation + +**Goal:** Build the foundation for the investment platform ### Active Work -- [ ] Define sprint goals here +See [GitHub Issues](https://github.com/akaszubski/TradingAgents/issues) for full backlog. -### Backlog -- Expand data vendor options -- Improve caching performance -- Add more comprehensive testing -- Enhance CLI configuration options +**Phase 1: Database (Issues #2-7)** +- [ ] #2 Database setup - SQLAlchemy + PostgreSQL/SQLite +- [ ] #3 User model - profiles, tax jurisdiction +- [ ] #4 Portfolio model - live, paper, backtest +- [ ] #5 Settings model - risk profiles, alerts +- [ ] #6 Trade model - CGT tracking +- [ ] #7 Alembic migrations + +**Phase 2: Data Layer (Issues #8-12)** +- [ ] #8 FRED API integration +- [ ] #9 Multi-timeframe aggregation +- [ ] #10 Benchmark data +- [ ] #11 Interface routing +- [ ] #12 Data caching + +### Backlog (47 total issues) +- Phase 3: New Analysts (#13-17) +- Phase 4: Memory System (#18-21) +- Phase 5: Execution Layer (#22-28) +- Phase 6: Portfolio Management (#29-32) +- Phase 7: Simulation (#33-37) +- Phase 8: Alerts (#38-41) +- Phase 9: Backtest (#42-44) +- Phase 10: API & Docs (#45-48) --- diff --git a/README.md b/README.md index 5bbdd755..947a3a09 100644 --- a/README.md +++ b/README.md @@ -335,6 +335,17 @@ grep ERROR ./logs/tradingagents.log If an error occurs during analysis, partial results are automatically saved, allowing you to inspect completed work and resume processing. Partial results are saved to the results directory in JSON format. +## Documentation + +For comprehensive documentation, guides, and API references, please visit the [docs/](docs/) directory: + +- **[Quick Start Guide](docs/QUICKSTART.md)** - Get up and running quickly +- **[Architecture Documentation](docs/architecture/)** - Understand system design and components +- **[API Reference](docs/api/)** - Detailed API documentation +- **[Developer Guides](docs/guides/)** - How-to guides for extending the framework +- **[Testing Guide](docs/testing/)** - Testing infrastructure and best practices +- **[Complete Documentation Index](docs/README.md)** - Full table of contents + ## Contributing We welcome contributions from the community! Whether it's fixing a bug, improving documentation, or suggesting a new feature, your input helps make this project better. If you are interested in this line of research, please consider joining our open-source financial AI research community [Tauric Research](https://tauric.ai/). diff --git a/docs/QUICKSTART.md b/docs/QUICKSTART.md new file mode 100644 index 00000000..dd4ef21d --- /dev/null +++ b/docs/QUICKSTART.md @@ -0,0 +1,241 @@ +# Quick Start Guide + +Get started with TradingAgents in under 10 minutes. + +## Installation + +### Prerequisites + +- Python >= 3.10 (Python 3.13 recommended) +- pip package manager +- Conda or virtualenv (recommended) + +### Step 1: Clone the Repository + +```bash +git clone https://github.com/TauricResearch/TradingAgents.git +cd TradingAgents +``` + +### Step 2: Create Virtual Environment + +Using conda (recommended): + +```bash +conda create -n tradingagents python=3.13 +conda activate tradingagents +``` + +Or using venv: + +```bash +python -m venv venv +source venv/bin/activate # On Windows: venv\Scripts\activate +``` + +### Step 3: Install Dependencies + +```bash +pip install -r requirements.txt +``` + +## Required APIs + +TradingAgents requires API keys for LLM providers and data sources. + +### LLM Provider (choose one) + +**Option 1: OpenAI (default)** + +```bash +export OPENAI_API_KEY=your_api_key_here +``` + +Get your key at: [https://platform.openai.com/api-keys](https://platform.openai.com/api-keys) + +**Option 2: Anthropic** + +```bash +export ANTHROPIC_API_KEY=your_api_key_here +``` + +Get your key at: [https://console.anthropic.com/](https://console.anthropic.com/) + +**Option 3: OpenRouter (unified access)** + +```bash +export OPENROUTER_API_KEY=your_api_key_here +export OPENAI_API_KEY=your_api_key_here # Still needed for embeddings +``` + +Get your key at: [https://openrouter.ai/keys](https://openrouter.ai/keys) + +**Option 4: Google Generative AI** + +```bash +export GOOGLE_API_KEY=your_api_key_here +``` + +Get your key at: [https://makersuite.google.com/app/apikey](https://makersuite.google.com/app/apikey) + +### Data Vendor + +**Alpha Vantage (required for fundamental and news data)** + +```bash +export ALPHA_VANTAGE_API_KEY=your_api_key_here +``` + +Get a free key at: [https://www.alphavantage.co/support/#api-key](https://www.alphavantage.co/support/#api-key) + +TradingAgents users get increased rate limits (60 requests/minute, no daily limits) thanks to Alpha Vantage's open-source support program. + +### Using .env File + +Alternatively, create a `.env` file in the project root: + +```bash +cp .env.example .env +# Edit .env with your actual API keys +``` + +Example `.env`: + +```env +OPENAI_API_KEY=your_openai_key_here +ALPHA_VANTAGE_API_KEY=your_alpha_vantage_key_here +TRADINGAGENTS_RESULTS_DIR=./results +``` + +## Your First Analysis + +### CLI Mode + +Run the interactive CLI: + +```bash +python -m cli.main +``` + +You'll see a menu where you can: +- Select ticker symbols (e.g., NVDA, AAPL, TSLA) +- Choose analysis date +- Configure LLM models +- Set research depth (debate rounds) + +The CLI will display real-time progress as agents analyze the market and generate trading signals. + +### Programmatic Mode + +Create a Python script: + +```python +from tradingagents.graph.trading_graph import TradingAgentsGraph +from tradingagents.default_config import DEFAULT_CONFIG + +# Initialize the trading graph +ta = TradingAgentsGraph(debug=True, config=DEFAULT_CONFIG.copy()) + +# Run analysis for NVDA on a specific date +_, decision = ta.propagate("NVDA", "2024-05-10") + +# Print the trading decision +print(f"Decision: {decision['action']}") +print(f"Confidence: {decision['confidence_score']}") +print(f"Reasoning: {decision['reasoning']}") +``` + +Run your script: + +```bash +python your_script.py +``` + +## Configuration + +### Using Different LLM Providers + +**OpenAI (default):** + +```python +config = DEFAULT_CONFIG.copy() +config["llm_provider"] = "openai" +config["deep_think_llm"] = "o4-mini" +config["quick_think_llm"] = "gpt-4o-mini" +config["backend_url"] = "https://api.openai.com/v1" +``` + +**Anthropic:** + +```python +config["llm_provider"] = "anthropic" +config["deep_think_llm"] = "claude-sonnet-4-20250514" +config["quick_think_llm"] = "claude-sonnet-4-20250514" +config["backend_url"] = "https://api.anthropic.com" +``` + +**OpenRouter:** + +```python +config["llm_provider"] = "openrouter" +config["deep_think_llm"] = "anthropic/claude-sonnet-4.5" +config["quick_think_llm"] = "openai/gpt-4o-mini" +config["backend_url"] = "https://openrouter.ai/api/v1" +``` + +### Customizing Data Vendors + +```python +config["data_vendors"] = { + "core_stock_apis": "yfinance", # Stock prices + "technical_indicators": "yfinance", # Technical analysis + "fundamental_data": "alpha_vantage", # Company fundamentals + "news_data": "alpha_vantage", # News and sentiment +} +``` + +See [Configuration Guide](guides/configuration.md) for all available options. + +## Next Steps + +- **[Architecture Overview](architecture/multi-agent-system.md)** - Understand how agents work together +- **[API Reference](api/trading-graph.md)** - Explore the full API +- **[Adding New Analysts](guides/adding-new-analyst.md)** - Extend the framework +- **[Configuration Guide](guides/configuration.md)** - Advanced configuration options + +## Troubleshooting + +### Common Issues + +**API Rate Limits** + +If you hit rate limits, the framework will automatically save partial analysis state. Wait for the suggested retry time and re-run. + +**Missing API Keys** + +Ensure environment variables are set: + +```bash +echo $OPENAI_API_KEY +echo $ALPHA_VANTAGE_API_KEY +``` + +**Import Errors** + +Ensure you're in the correct virtual environment: + +```bash +conda activate tradingagents # or source venv/bin/activate +``` + +**Data Vendor Errors** + +Check your Alpha Vantage API key is valid and has remaining quota. Free tier allows 25 requests/day; TradingAgents users get 60 requests/minute. + +## Getting Help + +- **Documentation**: Browse the [full documentation](README.md) +- **Discord**: Join our [Discord community](https://discord.com/invite/hk9PGKShPK) +- **GitHub Issues**: [Report bugs or ask questions](https://github.com/TauricResearch/TradingAgents/issues) + +Happy trading! diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..d88899e9 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,105 @@ +# TradingAgents Documentation + +Welcome to the TradingAgents documentation. This guide will help you understand, use, and extend the TradingAgents multi-agent financial trading framework. + +## Overview + +TradingAgents is a multi-agent trading framework that mirrors the dynamics of real-world trading firms. By deploying specialized LLM-powered agents - from fundamental analysts, sentiment experts, and technical analysts, to traders and risk management teams - the platform collaboratively evaluates market conditions and informs trading decisions. + +## Documentation Structure + +### Getting Started + +- **[Quick Start Guide](QUICKSTART.md)** - Get up and running quickly with TradingAgents +- **[Development Setup](development/setup.md)** - Set up your development environment +- **[Configuration Guide](guides/configuration.md)** - Configure LLM providers, data vendors, and system settings + +### Architecture + +Understand the system design and how components interact: + +- **[Multi-Agent System](architecture/multi-agent-system.md)** - Agent roles, responsibilities, and collaboration patterns +- **[Data Flow](architecture/data-flow.md)** - How data moves through the system +- **[LLM Integration](architecture/llm-integration.md)** - Provider abstraction and model selection + +### API Reference + +Detailed API documentation for developers: + +- **[TradingGraph API](api/trading-graph.md)** - Core orchestration API +- **[Agents API](api/agents.md)** - Agent interfaces and implementations +- **[Data Flows API](api/dataflows.md)** - Data vendor integrations + +### Guides + +Step-by-step tutorials for common tasks: + +- **[Adding a New Analyst](guides/adding-new-analyst.md)** - Extend the framework with custom analyst agents +- **[Adding an LLM Provider](guides/adding-llm-provider.md)** - Integrate new language model providers +- **[Configuration Options](guides/configuration.md)** - Comprehensive configuration reference + +### Testing + +Learn about the testing infrastructure: + +- **[Testing Overview](testing/README.md)** - Testing philosophy and structure +- **[Running Tests](testing/running-tests.md)** - How to run the test suite +- **[Writing Tests](testing/writing-tests.md)** - Guidelines for writing new tests + +### Development + +Contributing and development guidelines: + +- **[Development Setup](development/setup.md)** - Set up your development environment +- **[Contributing Guide](development/contributing.md)** - How to contribute to TradingAgents + +## Key Concepts + +### Multi-Agent Architecture + +TradingAgents decomposes complex trading tasks into specialized roles: + +- **Analyst Team**: Fundamentals, Sentiment, News, and Technical analysts +- **Researcher Team**: Bull and Bear researchers who debate insights +- **Trader Agent**: Makes trading decisions based on comprehensive analysis +- **Risk Management**: Evaluates portfolio risk and validates strategies +- **Portfolio Manager**: Final approval and execution oversight + +### LangGraph Framework + +Built on LangGraph for: +- State management across agent workflows +- Tool orchestration for data access +- Conditional routing based on agent outputs +- Memory persistence for context retention + +### Data Vendor Abstraction + +Flexible data sourcing through configurable vendors: +- **yfinance**: Stock prices and technical indicators +- **Alpha Vantage**: Fundamental data and news +- **Google News**: Alternative news sources +- **Local**: Offline backtesting data + +## Quick Links + +- [Installation Instructions](QUICKSTART.md#installation) +- [API Keys Setup](QUICKSTART.md#required-apis) +- [First Analysis](QUICKSTART.md#your-first-analysis) +- [Configuration Options](guides/configuration.md) +- [GitHub Repository](https://github.com/TauricResearch/TradingAgents) +- [Research Paper](https://arxiv.org/abs/2412.20138) + +## Support + +- **Discord**: [Join our community](https://discord.com/invite/hk9PGKShPK) +- **GitHub Issues**: [Report bugs or request features](https://github.com/TauricResearch/TradingAgents/issues) +- **Twitter**: [@TauricResearch](https://x.com/TauricResearch) + +## License + +TradingAgents is released under the MIT License. See the [LICENSE](../LICENSE) file for details. + +## Disclaimer + +TradingAgents is designed for research and educational purposes. It is not intended as financial, investment, or trading advice. Trading performance may vary based on many factors including model selection, data quality, and market conditions. See [Tauric AI Disclaimer](https://tauric.ai/disclaimer/) for full details. diff --git a/docs/api/agents.md b/docs/api/agents.md new file mode 100644 index 00000000..99a14b95 --- /dev/null +++ b/docs/api/agents.md @@ -0,0 +1,391 @@ +# Agents API Reference + +This document provides API reference for all agent types in the TradingAgents framework. + +## Agent Types + +All agents are located in `tradingagents/agents/` + +### Analyst Agents + +Analysts conduct specialized analysis on market data. + +#### Base Analyst Interface + +All analysts inherit from a common interface pattern: + +```python +class BaseAnalyst: + def __init__(self, llm, tools): + self.llm = llm + self.tools = tools + + def analyze(self, ticker: str, date: str) -> str: + """Perform analysis and return report.""" + pass +``` + +#### Market Analyst + +**Location**: `tradingagents/agents/analysts/market_analyst.py` + +**Purpose**: Technical analysis using price patterns and indicators + +**Tools**: +- `get_stock_data()` - Historical prices +- `get_indicators()` - Technical indicators (MACD, RSI, Bollinger Bands) + +**Output**: Technical analysis report with trend identification and signals + +**Example**: +```python +report = market_analyst.analyze("NVDA", "2024-05-10") +# Returns: "Technical analysis shows bullish MACD crossover..." +``` + +#### Fundamentals Analyst + +**Location**: `tradingagents/agents/analysts/fundamentals_analyst.py` + +**Purpose**: Company financial health and valuation analysis + +**Tools**: +- `get_fundamentals()` - Financial ratios and metrics +- `get_balance_sheet()` - Balance sheet data +- `get_income_statement()` - Income statement +- `get_cashflow()` - Cash flow statement + +**Output**: Financial health assessment and valuation analysis + +**Example**: +```python +report = fundamentals_analyst.analyze("NVDA", "2024-05-10") +# Returns: "Strong balance sheet with P/E ratio of 35..." +``` + +#### Sentiment Analyst + +**Location**: `tradingagents/agents/analysts/sentiment_analyst.py` + +**Purpose**: Social media and public sentiment analysis + +**Tools**: +- Reddit data via PRAW +- Sentiment scoring algorithms + +**Output**: Sentiment score and trending topics + +**Example**: +```python +report = sentiment_analyst.analyze("NVDA", "2024-05-10") +# Returns: "Positive social sentiment with score 0.75..." +``` + +#### News Analyst + +**Location**: `tradingagents/agents/analysts/news_analyst.py` + +**Purpose**: News and macroeconomic event analysis + +**Tools**: +- `get_news()` - Company-specific news +- `get_global_news()` - Market-wide news + +**Output**: Event impact assessment + +**Example**: +```python +report = news_analyst.analyze("NVDA", "2024-05-10") +# Returns: "Recent product launch expected to boost revenue..." +``` + +### Researcher Agents + +Researchers debate analyst findings to evaluate opportunities and risks. + +#### Bull Researcher + +**Purpose**: Identify bullish opportunities and positive catalysts + +**Input**: Analyst reports + +**Output**: Bull case arguments with supporting evidence + +#### Bear Researcher + +**Purpose**: Identify risks and potential downsides + +**Input**: Analyst reports + +**Output**: Bear case arguments with risk assessments + +#### Research Manager + +**Purpose**: Moderate debates and synthesize perspectives + +**Input**: Bull/bear arguments from debate rounds + +**Output**: Balanced research synthesis + +### Trader Agent + +**Location**: `tradingagents/agents/trader.py` + +**Purpose**: Make final trading decisions based on comprehensive analysis + +**Input**: +- Analyst reports +- Research synthesis +- Market conditions + +**Output**: +```python +{ + "action": "BUY" | "SELL" | "HOLD", + "confidence_score": 0.0 to 1.0, + "reasoning": str, + "position_size": float +} +``` + +**Example**: +```python +decision = trader.decide(state) +print(decision["action"]) # "BUY" +print(decision["confidence_score"]) # 0.75 +``` + +### Risk Management Agents + +#### Risk Analysts + +**Purpose**: Assess portfolio risk (volatility, liquidity, correlation) + +**Tools**: Risk metrics, scenario analysis + +**Output**: Risk assessment with mitigation recommendations + +#### Portfolio Manager + +**Location**: `tradingagents/agents/portfolio_manager.py` + +**Purpose**: Final approval/rejection of trading proposals + +**Input**: +- Trading decision +- Risk assessment + +**Output**: +```python +{ + "approved": bool, + "reasoning": str, + "modifications": dict # Suggested changes if not approved +} +``` + +## Agent Tools + +Location: `tradingagents/agents/utils/agent_utils.py` + +### Data Access Tools + +```python +get_stock_data(ticker: str, start_date: str, end_date: str) -> dict +``` +Get historical stock prices (OHLCV data) + +```python +get_indicators(ticker: str, indicators: List[str]) -> dict +``` +Calculate technical indicators. Available: MACD, RSI, BollingerBands, SMA, EMA + +```python +get_fundamentals(ticker: str) -> dict +``` +Get company fundamental metrics (P/E, P/B, ROE, etc.) + +```python +get_balance_sheet(ticker: str) -> dict +``` +Get balance sheet data + +```python +get_income_statement(ticker: str) -> dict +``` +Get income statement + +```python +get_cashflow(ticker: str) -> dict +``` +Get cash flow statement + +```python +get_news(ticker: str, date: str) -> dict +``` +Get company-specific news articles + +```python +get_global_news(date: str) -> dict +``` +Get market-wide news and events + +```python +get_insider_sentiment(ticker: str) -> dict +``` +Get insider trading sentiment + +```python +get_insider_transactions(ticker: str) -> dict +``` +Get insider transaction history + +## Agent State + +Location: `tradingagents/agents/utils/agent_states.py` + +### AgentState + +Main state object passed through the workflow: + +```python +@dataclass +class AgentState: + ticker: str + date: str + analyst_reports: Dict[str, str] + research_synthesis: str + trading_decision: Dict[str, Any] + risk_assessment: Dict[str, Any] + final_decision: Dict[str, Any] +``` + +### InvestDebateState + +State for research debate rounds: + +```python +@dataclass +class InvestDebateState: + bull_arguments: List[str] + bear_arguments: List[str] + debate_round: int + synthesis: str +``` + +### RiskDebateState + +State for risk management discussions: + +```python +@dataclass +class RiskDebateState: + risk_assessments: List[str] + discussion_round: int + final_recommendation: str +``` + +## Memory System + +Location: `tradingagents/agents/utils/memory.py` + +### FinancialSituationMemory + +Vector-based memory for storing and retrieving analysis context: + +```python +class FinancialSituationMemory: + def __init__(self, persist_directory: str = "./memory_cache"): + """Initialize memory with ChromaDB backend.""" + + def add_situation( + self, + ticker: str, + date: str, + analysis: dict, + metadata: dict = None + ): + """Store an analysis in memory.""" + + def search_similar( + self, + query: str, + k: int = 5, + filter: dict = None + ) -> List[dict]: + """Search for similar past analyses.""" + + def get_by_ticker(self, ticker: str, limit: int = 10) -> List[dict]: + """Get all analyses for a specific ticker.""" +``` + +**Example**: +```python +memory = FinancialSituationMemory() + +# Store analysis +memory.add_situation( + ticker="NVDA", + date="2024-05-10", + analysis=final_state, + metadata={"confidence": 0.75} +) + +# Retrieve similar analyses +similar = memory.search_similar( + query="NVDA technical bullish", + k=5 +) +``` + +## Creating Custom Agents + +### Step 1: Define Agent Class + +```python +from typing import List + +class CustomAnalyst: + def __init__(self, llm, tools: List): + self.llm = llm + self.tools = tools + + def analyze(self, ticker: str, date: str) -> str: + # Your analysis logic + data = self.tools["get_stock_data"](ticker, date) + prompt = f"Analyze {ticker} data: {data}" + response = self.llm.invoke(prompt) + return response.content +``` + +### Step 2: Register Tools + +```python +from tradingagents.agents.utils.agent_utils import get_stock_data + +tools = { + "get_stock_data": get_stock_data, + # Add more tools as needed +} + +analyst = CustomAnalyst(llm, tools) +``` + +### Step 3: Integrate into Graph + +```python +from tradingagents.graph.trading_graph import TradingAgentsGraph + +# Register custom analyst +ta = TradingAgentsGraph() +ta.add_analyst("custom", custom_analyst) +``` + +See [Adding New Analyst Guide](../guides/adding-new-analyst.md) for complete details. + +## See Also + +- [Multi-Agent System Architecture](../architecture/multi-agent-system.md) +- [TradingGraph API](trading-graph.md) +- [Data Flows API](dataflows.md) +- [Adding New Analyst Guide](../guides/adding-new-analyst.md) diff --git a/docs/api/dataflows.md b/docs/api/dataflows.md new file mode 100644 index 00000000..2a6b7654 --- /dev/null +++ b/docs/api/dataflows.md @@ -0,0 +1,368 @@ +# Data Flows API Reference + +This document describes the data vendor abstraction layer and available data sources. + +## Overview + +TradingAgents uses a vendor-agnostic interface for data access, allowing seamless switching between data providers. + +Location: `tradingagents/dataflows/` + +## Configuration + +### Setting Data Vendors + +```python +from tradingagents.dataflows.config import set_config + +config = { + "data_vendors": { + "core_stock_apis": "yfinance", + "technical_indicators": "yfinance", + "fundamental_data": "alpha_vantage", + "news_data": "alpha_vantage" + } +} + +set_config(config) +``` + +### Getting Current Configuration + +```python +from tradingagents.dataflows.config import get_config + +config = get_config() +print(config["data_vendors"]) +``` + +## Data Vendors + +### yfinance + +**Location**: `tradingagents/dataflows/yfinance.py` + +**Capabilities**: +- Stock prices (OHLCV) +- Technical indicators +- Basic company information + +**Setup**: No API key required + +**Rate Limits**: None (public data) + +**Example**: +```python +from tradingagents.dataflows.yfinance import ( + yfinance_get_stock_data, + yfinance_get_indicators +) + +# Get stock data +data = yfinance_get_stock_data("NVDA", "2024-01-01", "2024-12-31") + +# Get indicators +indicators = yfinance_get_indicators("NVDA", ["MACD", "RSI"]) +``` + +### Alpha Vantage + +**Location**: `tradingagents/dataflows/alpha_vantage.py` + +**Capabilities**: +- Fundamental data +- Company financials +- News articles +- Economic indicators + +**Setup**: +```bash +export ALPHA_VANTAGE_API_KEY=your_key_here +``` + +**Rate Limits**: 60 requests/minute for TradingAgents users + +**Example**: +```python +from tradingagents.dataflows.alpha_vantage import ( + alphavantage_get_fundamentals, + alphavantage_get_news +) + +# Get fundamentals +fundamentals = alphavantage_get_fundamentals("NVDA") + +# Get news +news = alphavantage_get_news("NVDA", "2024-01-15") +``` + +### Google News + +**Location**: `tradingagents/dataflows/google.py` + +**Capabilities**: +- Real-time news articles +- Global news search + +**Setup**: +```bash +export GOOGLE_API_KEY=your_key_here # Optional for basic usage +``` + +**Example**: +```python +from tradingagents.dataflows.google import google_get_news + +news = google_get_news("NVDA", "2024-01-15") +``` + +### Local Cache + +**Location**: `tradingagents/dataflows/local.py` + +**Capabilities**: +- Offline backtesting +- Pre-downloaded data access + +**Setup**: Place data files in `data_cache_dir` + +**Example**: +```python +from tradingagents.dataflows.local import local_get_stock_data + +data = local_get_stock_data("NVDA", "2024-01-01", "2024-12-31") +``` + +## Interface Layer + +**Location**: `tradingagents/dataflows/interface.py` + +### Unified Data Access + +The interface layer provides vendor-agnostic functions: + +```python +from tradingagents.dataflows.interface import ( + get_stock_data, + get_indicators, + get_fundamentals, + get_news +) +``` + +### Automatic Routing + +Based on configuration, requests are automatically routed: + +```python +# Config says: "core_stock_apis": "yfinance" +data = get_stock_data("NVDA", "2024-01-01", "2024-12-31") +# Automatically calls yfinance_get_stock_data() +``` + +## Data Schemas + +### Stock Data (OHLCV) + +```python +{ + "ticker": "NVDA", + "dates": ["2024-01-01", "2024-01-02", ...], + "open": [150.0, 151.2, ...], + "high": [152.5, 153.0, ...], + "low": [149.8, 150.5, ...], + "close": [151.0, 152.0, ...], + "volume": [1000000, 1200000, ...], + "adj_close": [151.0, 152.0, ...] # Optional +} +``` + +### Technical Indicators + +```python +{ + "MACD": { + "macd": [0.5, 0.6, ...], + "signal": [0.4, 0.5, ...], + "histogram": [0.1, 0.1, ...] + }, + "RSI": { + "rsi": [65.0, 67.5, ...] + }, + "BollingerBands": { + "upper": [155.0, 156.0, ...], + "middle": [150.0, 151.0, ...], + "lower": [145.0, 146.0, ...] + } +} +``` + +### Fundamental Data + +```python +{ + "Symbol": "NVDA", + "MarketCapitalization": 2800000000000, + "PERatio": 35.2, + "PEGRatio": 1.8, + "BookValue": 25.50, + "DividendYield": 0.005, + "EPS": 4.25, + "ProfitMargin": 0.25, + "OperatingMarginTTM": 0.30, + "ReturnOnAssetsTTM": 0.22, + "ReturnOnEquityTTM": 0.45, + "RevenueTTM": 60000000000, + "GrossProfitTTM": 45000000000 +} +``` + +### News Data + +```python +{ + "ticker": "NVDA", + "date": "2024-01-15", + "articles": [ + { + "title": "Company Announces Record Earnings", + "source": "Reuters", + "url": "https://...", + "published_at": "2024-01-15T10:30:00Z", + "sentiment": 0.8, # -1 to 1 + "summary": "Full article summary...", + "authors": ["John Doe"], + "time_published": "20240115T103000" + }, + ... + ] +} +``` + +## Error Handling + +### VendorError + +Base exception for data vendor errors: + +```python +from tradingagents.dataflows.exceptions import VendorError + +try: + data = get_stock_data("INVALID", "2024-01-01", "2024-12-31") +except VendorError as e: + print(f"Vendor error: {e}") +``` + +### RateLimitError + +Raised when API rate limits are exceeded: + +```python +from tradingagents.dataflows.exceptions import RateLimitError + +try: + data = get_fundamentals("NVDA") +except RateLimitError as e: + print(f"Rate limit hit. Retry after {e.retry_after}s") + time.sleep(e.retry_after) +``` + +### DataUnavailableError + +Raised when requested data is not available: + +```python +from tradingagents.dataflows.exceptions import DataUnavailableError + +try: + data = get_stock_data("NVDA", "1900-01-01", "1900-12-31") +except DataUnavailableError: + print("Historical data not available for this date range") +``` + +## Caching + +### Cache Configuration + +```python +config = { + "data_cache_dir": "./dataflows/data_cache", + "cache_ttl": { + "stock_data": 3600, # 1 hour + "fundamentals": 86400, # 1 day + "news": 3600 # 1 hour + } +} +``` + +### Cache Functions + +```python +from tradingagents.dataflows.cache import ( + get_cached, + save_cache, + clear_cache +) + +# Get from cache +cached_data = get_cached("nvda_stock_2024") + +# Save to cache +save_cache("nvda_stock_2024", data, ttl=3600) + +# Clear cache +clear_cache() +``` + +## Best Practices + +1. **Use Configuration**: Don't hardcode vendors +2. **Handle Errors**: Implement retry logic for rate limits +3. **Cache Data**: Avoid redundant API calls +4. **Validate Inputs**: Check ticker symbols and dates +5. **Use Fallbacks**: Have backup vendors configured + +## Examples + +### Basic Data Retrieval + +```python +from tradingagents.dataflows.interface import get_stock_data + +data = get_stock_data("NVDA", "2024-01-01", "2024-12-31") +print(f"Close prices: {data['close']}") +``` + +### Multiple Indicators + +```python +from tradingagents.dataflows.interface import get_indicators + +indicators = get_indicators("NVDA", ["MACD", "RSI", "BollingerBands"]) +print(f"RSI: {indicators['RSI']['rsi'][-1]}") +``` + +### With Error Handling + +```python +from tradingagents.dataflows.interface import get_news +from tradingagents.dataflows.exceptions import VendorError +import time + +def get_news_with_retry(ticker, date, max_retries=3): + for attempt in range(max_retries): + try: + return get_news(ticker, date) + except VendorError as e: + if attempt < max_retries - 1: + time.sleep(2 ** attempt) + else: + raise +``` + +## See Also + +- [Data Flow Architecture](../architecture/data-flow.md) +- [Configuration Guide](../guides/configuration.md) +- [Adding Data Vendor Guide](../guides/adding-data-vendor.md) diff --git a/docs/api/trading-graph.md b/docs/api/trading-graph.md new file mode 100644 index 00000000..16df46fc --- /dev/null +++ b/docs/api/trading-graph.md @@ -0,0 +1,457 @@ +# TradingGraph API Reference + +The `TradingAgentsGraph` class is the main entry point for the TradingAgents framework. It orchestrates all agents, manages state, and coordinates the analysis workflow. + +## Class: TradingAgentsGraph + +Location: `tradingagents/graph/trading_graph.py` + +### Constructor + +```python +TradingAgentsGraph( + selected_analysts: List[str] = ["market", "social", "news", "fundamentals"], + debug: bool = False, + config: Dict[str, Any] = None +) +``` + +#### Parameters + +- **selected_analysts** (List[str], optional): List of analyst types to include in analysis + - Default: `["market", "social", "news", "fundamentals"]` + - Available: `"market"`, `"social"`, `"news"`, `"fundamentals"` + - Example: `["market", "fundamentals"]` for technical and fundamental analysis only + +- **debug** (bool, optional): Enable debug mode with verbose logging + - Default: `False` + - When `True`: Prints detailed execution traces and intermediate states + +- **config** (Dict[str, Any], optional): Configuration dictionary + - Default: `None` (uses `DEFAULT_CONFIG`) + - See [Configuration Reference](../guides/configuration.md) for all options + +#### Returns + +- Instance of `TradingAgentsGraph` + +#### Example + +```python +from tradingagents.graph.trading_graph import TradingAgentsGraph +from tradingagents.default_config import DEFAULT_CONFIG + +# Basic initialization +ta = TradingAgentsGraph() + +# With custom analysts +ta = TradingAgentsGraph( + selected_analysts=["market", "fundamentals"], + debug=True +) + +# With custom configuration +config = DEFAULT_CONFIG.copy() +config["llm_provider"] = "anthropic" +config["deep_think_llm"] = "claude-sonnet-4-20250514" + +ta = TradingAgentsGraph(config=config) +``` + +### Methods + +#### propagate() + +Run the complete trading analysis workflow for a company on a specific date. + +```python +propagate( + company_name: str, + trade_date: str +) -> Tuple[Dict[str, Any], Dict[str, Any]] +``` + +##### Parameters + +- **company_name** (str): Ticker symbol of the company to analyze + - Example: `"NVDA"`, `"AAPL"`, `"TSLA"` + - Must be a valid US stock ticker + +- **trade_date** (str): Date for analysis in YYYY-MM-DD format + - Example: `"2024-05-10"` + - Must be a valid trading day (not weekend or holiday) + +##### Returns + +Tuple of two dictionaries: + +1. **Final State** (Dict[str, Any]): Complete agent state after analysis + - Contains all analyst reports, debate outcomes, risk assessments + - Useful for debugging and detailed inspection + +2. **Trading Decision** (Dict[str, Any]): The final trading recommendation + - `action`: `"BUY"`, `"SELL"`, or `"HOLD"` + - `confidence_score`: Float between 0.0 and 1.0 + - `reasoning`: Detailed explanation of the decision + - `position_size`: Recommended position size (if applicable) + - `risk_assessment`: Risk evaluation summary + +##### Example + +```python +ta = TradingAgentsGraph(debug=True) + +# Run analysis +final_state, decision = ta.propagate("NVDA", "2024-05-10") + +# Access decision +print(f"Action: {decision['action']}") +print(f"Confidence: {decision['confidence_score']:.2%}") +print(f"Reasoning: {decision['reasoning']}") + +# Access detailed state +print(f"Analyst Reports: {final_state['analyst_reports']}") +print(f"Research Synthesis: {final_state['research_synthesis']}") +``` + +##### Raises + +- **ValueError**: Invalid ticker or date format +- **LLMRateLimitError**: LLM API rate limit exceeded +- **DataUnavailableError**: Required data not available for the ticker/date +- **APIError**: Generic API error from LLM or data provider + +## Configuration + +### Default Configuration + +The default configuration is defined in `tradingagents/default_config.py`: + +```python +DEFAULT_CONFIG = { + # Directories + "project_dir": "", + "results_dir": "./results", + "data_cache_dir": "./dataflows/data_cache", + + # LLM settings + "llm_provider": "openai", + "deep_think_llm": "o4-mini", + "quick_think_llm": "gpt-4o-mini", + "backend_url": "https://api.openai.com/v1", + + # Workflow settings + "max_debate_rounds": 1, + "max_risk_discuss_rounds": 1, + "max_recur_limit": 100, + + # Data vendors + "data_vendors": { + "core_stock_apis": "yfinance", + "technical_indicators": "yfinance", + "fundamental_data": "alpha_vantage", + "news_data": "alpha_vantage" + } +} +``` + +### Customizing Configuration + +```python +from tradingagents.default_config import DEFAULT_CONFIG + +config = DEFAULT_CONFIG.copy() + +# Change LLM provider +config["llm_provider"] = "anthropic" +config["deep_think_llm"] = "claude-sonnet-4-20250514" + +# Increase debate rounds +config["max_debate_rounds"] = 2 + +# Change data vendors +config["data_vendors"]["news_data"] = "google" + +# Initialize with custom config +ta = TradingAgentsGraph(config=config) +``` + +## Workflow Stages + +The `propagate()` method executes these stages: + +### 1. Data Collection + +All selected analysts collect relevant data in parallel: + +- **Market Analyst**: Stock prices, technical indicators +- **Fundamentals Analyst**: Financial statements, ratios +- **Sentiment Analyst**: Social media sentiment +- **News Analyst**: News articles, events + +### 2. Analyst Reports + +Each analyst generates a specialized report: + +```python +state.analyst_reports = { + "market": "Technical analysis shows bullish MACD crossover...", + "fundamentals": "Strong balance sheet with P/E ratio of 35...", + "sentiment": "Positive social sentiment with score 0.75...", + "news": "Recent product launch expected to boost revenue..." +} +``` + +### 3. Research Debate + +Bull and Bear researchers debate the analyst findings: + +```python +# Round 1 +bull_researcher: "Strong fundamentals support upside potential..." +bear_researcher: "High valuation creates downside risk..." + +# Round 2 (if configured) +bull_researcher: "Growth prospects justify premium valuation..." +bear_researcher: "Market volatility increases uncertainty..." + +# Synthesis +research_manager: "Balanced view: Bullish bias with risk management..." +``` + +### 4. Trading Decision + +Trader agent synthesizes all inputs and makes a decision: + +```python +decision = { + "action": "BUY", + "confidence_score": 0.75, + "reasoning": "Strong fundamentals and positive momentum outweigh valuation concerns...", + "position_size": 0.05 # 5% of portfolio +} +``` + +### 5. Risk Validation + +Risk management team evaluates the proposal: + +```python +risk_assessment = { + "approved": True, + "risk_score": 0.3, # Low to medium risk + "recommendations": [ + "Set stop-loss at -5%", + "Monitor volatility", + "Review position after earnings" + ] +} +``` + +### 6. Final Decision + +Portfolio manager approves or rejects: + +```python +final_decision = { + "approved": True, + "action": "BUY", + "confidence_score": 0.75, + "execution_details": { + "position_size": 0.05, + "stop_loss": -0.05, + "take_profit": 0.15 + } +} +``` + +## State Management + +The graph maintains state through the `AgentState` class: + +```python +@dataclass +class AgentState: + ticker: str + date: str + analyst_reports: Dict[str, str] + research_synthesis: str + trading_decision: Dict[str, Any] + risk_assessment: Dict[str, Any] + final_decision: Dict[str, Any] +``` + +Location: `tradingagents/agents/utils/agent_states.py` + +## Memory System + +The graph uses `FinancialSituationMemory` for context retention: + +```python +from tradingagents.agents.utils.memory import FinancialSituationMemory + +memory = FinancialSituationMemory( + persist_directory="./memory_cache" +) + +# Store analysis +memory.add_situation( + ticker="NVDA", + date="2024-05-10", + analysis=state +) + +# Retrieve similar past analyses +similar = memory.search_similar( + query="NVDA technical analysis", + k=5 +) +``` + +## Error Handling + +### Handling Rate Limits + +```python +from tradingagents.utils.exceptions import LLMRateLimitError +import time + +def run_with_retry(ta, ticker, date, max_retries=3): + for attempt in range(max_retries): + try: + return ta.propagate(ticker, date) + except LLMRateLimitError as e: + if attempt < max_retries - 1: + wait_time = e.retry_after or 60 + print(f"Rate limit hit. Waiting {wait_time}s...") + time.sleep(wait_time) + else: + raise +``` + +### Handling Missing Data + +```python +from tradingagents.utils.exceptions import DataUnavailableError + +try: + state, decision = ta.propagate("INVALID", "2024-05-10") +except DataUnavailableError as e: + print(f"Data not available: {e}") + # Fall back to alternative ticker or date +``` + +## Performance Considerations + +### Execution Time + +Typical execution times (single ticker): + +- **1 debate round**: 30-60 seconds +- **2 debate rounds**: 60-120 seconds +- **3 debate rounds**: 120-180 seconds + +Factors affecting speed: +- Number of selected analysts +- Number of debate rounds +- LLM provider and model choice +- Data vendor API latency + +### Cost Optimization + +Estimated costs per analysis: + +| Configuration | LLM Calls | Cost (USD) | +|---------------|-----------|------------| +| Minimal (1 round, 2 analysts) | ~10-15 | $0.05-0.10 | +| Standard (1 round, 4 analysts) | ~20-25 | $0.10-0.20 | +| Deep (2 rounds, 4 analysts) | ~35-45 | $0.20-0.40 | + +Cost reduction strategies: +- Use `gpt-4o-mini` instead of `o4-mini` for testing +- Reduce debate rounds +- Select only necessary analysts +- Enable caching + +### Parallel Execution + +Analyze multiple tickers in parallel: + +```python +import asyncio +from concurrent.futures import ThreadPoolExecutor + +tickers = ["NVDA", "AAPL", "MSFT", "TSLA"] +date = "2024-05-10" + +def analyze_ticker(ticker): + ta = TradingAgentsGraph() + return ta.propagate(ticker, date) + +with ThreadPoolExecutor(max_workers=4) as executor: + results = list(executor.map(analyze_ticker, tickers)) +``` + +## Examples + +### Basic Usage + +```python +from tradingagents.graph.trading_graph import TradingAgentsGraph + +ta = TradingAgentsGraph(debug=True) +state, decision = ta.propagate("NVDA", "2024-05-10") + +print(f"Decision: {decision['action']}") +print(f"Confidence: {decision['confidence_score']:.2%}") +``` + +### Custom Analysts + +```python +# Only technical and fundamental analysis +ta = TradingAgentsGraph( + selected_analysts=["market", "fundamentals"], + debug=True +) + +state, decision = ta.propagate("AAPL", "2024-05-10") +``` + +### Multiple LLM Providers + +```python +# Use different models for deep vs. quick thinking +config = DEFAULT_CONFIG.copy() +config["llm_provider"] = "openrouter" +config["deep_think_llm"] = "anthropic/claude-sonnet-4.5" +config["quick_think_llm"] = "openai/gpt-4o-mini" + +ta = TradingAgentsGraph(config=config) +state, decision = ta.propagate("TSLA", "2024-05-10") +``` + +### Batch Analysis + +```python +tickers = ["NVDA", "AAPL", "MSFT"] +date = "2024-05-10" + +results = {} +ta = TradingAgentsGraph() + +for ticker in tickers: + state, decision = ta.propagate(ticker, date) + results[ticker] = decision + +# Compare decisions +for ticker, decision in results.items(): + print(f"{ticker}: {decision['action']} ({decision['confidence_score']:.2%})") +``` + +## See Also + +- [Multi-Agent System Architecture](../architecture/multi-agent-system.md) +- [Agents API Reference](agents.md) +- [Configuration Guide](../guides/configuration.md) +- [Adding New Analyst](../guides/adding-new-analyst.md) diff --git a/docs/architecture/data-flow.md b/docs/architecture/data-flow.md new file mode 100644 index 00000000..6852265a --- /dev/null +++ b/docs/architecture/data-flow.md @@ -0,0 +1,408 @@ +# Data Flow Architecture + +This document describes how data flows through the TradingAgents system, from external data sources to final trading decisions. + +## Overview + +TradingAgents implements a flexible data abstraction layer that allows seamless switching between data vendors without changing agent code. + +## Data Flow Diagram + +``` +External Sources Abstraction Layer Agents Decision +───────────────── ────────────────── ──────── ───────── + +yfinance ─┐ +Alpha Vantage ─┼→ Interface Layer → Analysts → Researchers → Trader +Google News ─┤ (config-driven) ↓ ↓ ↓ +Local Cache ─┘ Reports Debates Decision + ↓ ↓ ↓ + Vector Memory Synthesis Risk Check +``` + +## Data Vendors + +### Core Data Vendors + +TradingAgents supports multiple data vendors, configurable per data category: + +#### yfinance +- **Purpose**: Stock prices, technical indicators +- **Pros**: Free, reliable, comprehensive market data +- **Cons**: Limited fundamental data +- **Rate Limits**: None (public data) +- **Location**: `tradingagents/dataflows/yfinance.py` + +#### Alpha Vantage +- **Purpose**: Fundamental data, news, company financials +- **Pros**: Rich fundamental data, partnership with TradingAgents for enhanced limits +- **Cons**: Requires API key +- **Rate Limits**: 60 requests/minute for TradingAgents users (normally 25/day free tier) +- **Location**: `tradingagents/dataflows/alpha_vantage.py` + +#### Google News +- **Purpose**: News articles and headlines +- **Pros**: Real-time news, comprehensive coverage +- **Cons**: Requires API key for full access +- **Location**: `tradingagents/dataflows/google.py` + +#### Local Cache +- **Purpose**: Offline backtesting, development +- **Pros**: Fast, no API limits, reproducible +- **Cons**: Data must be pre-downloaded +- **Location**: `tradingagents/dataflows/local.py` + +### Data Categories + +Data vendor configuration is organized by category: + +```python +config["data_vendors"] = { + "core_stock_apis": "yfinance", # Price data, quotes + "technical_indicators": "yfinance", # MACD, RSI, etc. + "fundamental_data": "alpha_vantage", # Financials, ratios + "news_data": "alpha_vantage", # News and events +} +``` + +## Interface Layer + +### Unified Interface + +All agents access data through a unified interface: + +```python +from tradingagents.agents.utils.agent_utils import ( + get_stock_data, + get_indicators, + get_fundamentals, + get_news +) +``` + +### Interface Routing + +The interface layer routes requests to the configured vendor: + +**Configuration:** +```python +from tradingagents.dataflows.config import set_config + +config = { + "data_vendors": { + "core_stock_apis": "yfinance" + } +} +set_config(config) +``` + +**Usage:** +```python +# Automatically routes to yfinance based on config +data = get_stock_data("NVDA", "2024-01-01", "2024-12-31") +``` + +**Implementation:** +```python +def get_stock_data(ticker: str, start_date: str, end_date: str): + vendor = get_vendor_for_category("core_stock_apis") + + if vendor == "yfinance": + return yfinance_get_stock_data(ticker, start_date, end_date) + elif vendor == "alpha_vantage": + return alphavantage_get_stock_data(ticker, start_date, end_date) + elif vendor == "local": + return local_get_stock_data(ticker, start_date, end_date) +``` + +Location: `tradingagents/dataflows/interface.py` + +## Data Types + +### Price Data + +Historical stock prices (OHLCV): + +```python +{ + "dates": ["2024-01-01", "2024-01-02", ...], + "open": [150.0, 151.2, ...], + "high": [152.5, 153.0, ...], + "low": [149.8, 150.5, ...], + "close": [151.0, 152.0, ...], + "volume": [1000000, 1200000, ...] +} +``` + +### Technical Indicators + +Calculated technical analysis metrics: + +```python +{ + "MACD": { + "macd": [...], + "signal": [...], + "histogram": [...] + }, + "RSI": { + "rsi": [...] + }, + "BollingerBands": { + "upper": [...], + "middle": [...], + "lower": [...] + } +} +``` + +### Fundamental Data + +Company financial metrics: + +```python +{ + "MarketCapitalization": 2800000000000, + "PERatio": 35.2, + "PEGRatio": 1.8, + "BookValue": 25.50, + "DividendYield": 0.005, + "ProfitMargin": 0.25, + "OperatingMarginTTM": 0.30, + "ReturnOnAssetsTTM": 0.22, + "ReturnOnEquityTTM": 0.45 +} +``` + +### News Data + +News articles and headlines: + +```python +{ + "articles": [ + { + "title": "Company Announces Record Earnings", + "source": "Reuters", + "published_at": "2024-01-15T10:30:00Z", + "sentiment": 0.8, # -1 to 1 + "summary": "..." + }, + ... + ] +} +``` + +## Data Caching + +### Cache Strategy + +TradingAgents implements multi-level caching: + +1. **Memory Cache**: In-process cache for repeated requests within a session +2. **Disk Cache**: Persistent cache for expensive API calls +3. **Vector Store**: Semantic cache for analysis results + +### Cache Configuration + +```python +config["data_cache_dir"] = "./dataflows/data_cache" +``` + +### Cache Keys + +Cache keys are generated from request parameters: + +```python +cache_key = f"{vendor}_{function}_{ticker}_{start_date}_{end_date}" +``` + +### Cache Invalidation + +Caches expire based on data freshness requirements: + +- **Price Data**: 1 hour (intraday), 1 day (historical) +- **Fundamental Data**: 1 day +- **News Data**: 1 hour +- **Technical Indicators**: Based on underlying price data + +Location: `tradingagents/dataflows/cache.py` + +## Data Validation + +### Input Validation + +All data inputs are validated before processing: + +```python +def validate_ticker(ticker: str) -> bool: + """Validate ticker symbol format.""" + return bool(re.match(r'^[A-Z]{1,5}$', ticker)) + +def validate_date(date_str: str) -> bool: + """Validate date format (YYYY-MM-DD).""" + try: + datetime.strptime(date_str, '%Y-%m-%d') + return True + except ValueError: + return False +``` + +### Output Validation + +Data vendor responses are validated for completeness: + +```python +def validate_stock_data(data: dict) -> bool: + """Ensure stock data has required fields.""" + required = ["dates", "open", "high", "low", "close", "volume"] + return all(field in data for field in required) +``` + +## Error Handling + +### Vendor Fallback + +If a vendor fails, the system can fall back to alternatives: + +```python +def get_stock_data_with_fallback(ticker, start_date, end_date): + vendors = ["yfinance", "alpha_vantage", "local"] + + for vendor in vendors: + try: + return get_stock_data(ticker, start_date, end_date, vendor=vendor) + except VendorError: + continue + + raise DataUnavailableError(f"No vendor could provide data for {ticker}") +``` + +### Rate Limit Handling + +Automatic retry with exponential backoff for rate limits: + +```python +def handle_rate_limit(func, max_retries=3): + for attempt in range(max_retries): + try: + return func() + except RateLimitError as e: + wait_time = e.retry_after or (2 ** attempt) + time.sleep(wait_time) + + raise RateLimitExceeded("Max retries exceeded") +``` + +## Data Flow Examples + +### Market Analyst Workflow + +```python +# 1. Market Analyst requests technical data +data = get_stock_data("NVDA", "2024-01-01", "2024-12-31") +indicators = get_indicators("NVDA", ["MACD", "RSI", "BollingerBands"]) + +# 2. Interface routes to configured vendor (yfinance) +# 3. Data is fetched, cached, and validated +# 4. Analyst processes data and generates report +report = analyze_technical_signals(data, indicators) + +# 5. Report is stored in agent state +state.analyst_reports["market"] = report +``` + +### Fundamentals Analyst Workflow + +```python +# 1. Fundamentals Analyst requests financial data +fundamentals = get_fundamentals("NVDA") +balance_sheet = get_balance_sheet("NVDA") +income_statement = get_income_statement("NVDA") + +# 2. Interface routes to configured vendor (alpha_vantage) +# 3. Data is fetched from Alpha Vantage API +# 4. Analyst evaluates financial health +report = analyze_financial_health(fundamentals, balance_sheet, income_statement) + +# 5. Report is stored in agent state +state.analyst_reports["fundamentals"] = report +``` + +### News Analyst Workflow + +```python +# 1. News Analyst requests news data +company_news = get_news("NVDA", "2024-01-15") +global_news = get_global_news("2024-01-15") + +# 2. Interface routes to configured vendor (alpha_vantage or google) +# 3. News articles are fetched and sentiment scored +# 4. Analyst identifies market-moving events +report = analyze_news_impact(company_news, global_news) + +# 5. Report is stored in agent state +state.analyst_reports["news"] = report +``` + +## Performance Optimization + +### Batch Requests + +Request multiple data points in a single API call: + +```python +# Bad: Multiple API calls +data1 = get_stock_data("NVDA", "2024-01-01", "2024-01-02") +data2 = get_stock_data("NVDA", "2024-01-03", "2024-01-04") + +# Good: Single API call +data = get_stock_data("NVDA", "2024-01-01", "2024-01-04") +``` + +### Parallel Requests + +Fetch data for multiple tickers in parallel: + +```python +import asyncio + +async def fetch_multiple_tickers(tickers): + tasks = [get_stock_data_async(ticker, start, end) for ticker in tickers] + return await asyncio.gather(*tasks) +``` + +### Data Preprocessing + +Preprocess data once and cache results: + +```python +def get_preprocessed_indicators(ticker, start_date, end_date): + cache_key = f"preprocessed_{ticker}_{start_date}_{end_date}" + + if cached := get_from_cache(cache_key): + return cached + + data = get_stock_data(ticker, start_date, end_date) + indicators = calculate_all_indicators(data) + + save_to_cache(cache_key, indicators) + return indicators +``` + +## Best Practices + +1. **Use Configuration**: Always configure vendors through config, not hardcoded +2. **Handle Errors Gracefully**: Implement fallbacks and retries +3. **Cache Aggressively**: Cache expensive API calls with appropriate TTL +4. **Validate Data**: Check data completeness before using +5. **Monitor Usage**: Track API quotas and rate limits +6. **Batch When Possible**: Minimize API calls through batching +7. **Use Async for Parallelism**: Fetch multiple resources concurrently + +## References + +- [Multi-Agent System](multi-agent-system.md) +- [Data Flows API](../api/dataflows.md) +- [Configuration Guide](../guides/configuration.md) +- [Adding Data Vendor Guide](../guides/adding-data-vendor.md) diff --git a/docs/architecture/llm-integration.md b/docs/architecture/llm-integration.md new file mode 100644 index 00000000..8f750ed1 --- /dev/null +++ b/docs/architecture/llm-integration.md @@ -0,0 +1,451 @@ +# LLM Integration Architecture + +This document describes how TradingAgents integrates with different Large Language Model (LLM) providers through a unified abstraction layer. + +## Overview + +TradingAgents supports multiple LLM providers through a flexible configuration system that allows switching between providers without code changes. + +## Supported Providers + +### OpenAI +- **Models**: GPT-4o, GPT-4o-mini, o4-mini (default), o1-preview +- **Strengths**: Strong reasoning, reliable, extensive fine-tuning +- **Use Case**: Default choice for production +- **API Key**: `OPENAI_API_KEY` +- **Endpoint**: `https://api.openai.com/v1` + +### Anthropic +- **Models**: Claude Sonnet 4, Claude Opus 4 +- **Strengths**: Strong reasoning, long context windows, excellent instruction following +- **Use Case**: Alternative to OpenAI, good for complex analysis +- **API Key**: `ANTHROPIC_API_KEY` +- **Endpoint**: `https://api.anthropic.com` + +### OpenRouter +- **Models**: Unified access to 100+ models from multiple providers +- **Strengths**: Single API for multiple providers, competitive pricing +- **Use Case**: Flexibility, cost optimization, accessing diverse models +- **API Key**: `OPENROUTER_API_KEY` (plus `OPENAI_API_KEY` for embeddings) +- **Endpoint**: `https://openrouter.ai/api/v1` + +### Google Generative AI +- **Models**: Gemini 2.0 Flash, Gemini Pro +- **Strengths**: Fast inference, multimodal capabilities +- **Use Case**: Cost-effective alternative, multimodal analysis +- **API Key**: `GOOGLE_API_KEY` +- **Endpoint**: Built-in (no custom endpoint) + +### Ollama +- **Models**: Local models (Llama, Mistral, etc.) +- **Strengths**: No API costs, data privacy, offline operation +- **Use Case**: Development, experimentation, privacy-sensitive analysis +- **API Key**: None (local) +- **Endpoint**: `http://localhost:11434/v1` + +## Provider Abstraction + +### Configuration-Driven Selection + +LLM providers are selected through configuration: + +```python +config = { + "llm_provider": "openai", # Provider selection + "deep_think_llm": "o4-mini", # Model for complex reasoning + "quick_think_llm": "gpt-4o-mini", # Model for fast tasks + "backend_url": "https://api.openai.com/v1" +} +``` + +### Initialization Logic + +The `TradingAgentsGraph` class handles provider initialization: + +```python +if config["llm_provider"].lower() in ("openai", "ollama"): + from langchain_openai import ChatOpenAI + + self.deep_thinking_llm = ChatOpenAI( + model=config["deep_think_llm"], + base_url=config["backend_url"] + ) + self.quick_thinking_llm = ChatOpenAI( + model=config["quick_think_llm"], + base_url=config["backend_url"] + ) + +elif config["llm_provider"].lower() == "anthropic": + from langchain_anthropic import ChatAnthropic + + self.deep_thinking_llm = ChatAnthropic( + model=config["deep_think_llm"], + base_url=config["backend_url"] + ) + self.quick_thinking_llm = ChatAnthropic( + model=config["quick_think_llm"], + base_url=config["backend_url"] + ) + +elif config["llm_provider"].lower() == "openrouter": + from langchain_openai import ChatOpenAI + + openrouter_key = os.getenv("OPENROUTER_API_KEY") + if not openrouter_key: + raise ValueError("OPENROUTER_API_KEY required") + + default_headers = { + "HTTP-Referer": "https://github.com/TauricResearch/TradingAgents", + "X-Title": "TradingAgents" + } + + self.deep_thinking_llm = ChatOpenAI( + model=config["deep_think_llm"], + base_url=config["backend_url"], + api_key=openrouter_key, + default_headers=default_headers + ) + self.quick_thinking_llm = ChatOpenAI( + model=config["quick_think_llm"], + base_url=config["backend_url"], + api_key=openrouter_key, + default_headers=default_headers + ) + +elif config["llm_provider"].lower() == "google": + from langchain_google_genai import ChatGoogleGenerativeAI + + self.deep_thinking_llm = ChatGoogleGenerativeAI( + model=config["deep_think_llm"] + ) + self.quick_thinking_llm = ChatGoogleGenerativeAI( + model=config["quick_think_llm"] + ) +``` + +Location: `tradingagents/graph/trading_graph.py` + +## Model Selection Strategy + +### Two-Tier Model Approach + +TradingAgents uses two types of LLMs for different tasks: + +#### Deep Thinking LLM +- **Purpose**: Complex reasoning, strategic analysis, debate moderation +- **Characteristics**: Larger models, slower, more expensive, higher quality +- **Use Cases**: + - Researcher debate moderation + - Trading decision synthesis + - Risk assessment evaluation +- **Recommended Models**: + - OpenAI: o4-mini, o1-preview + - Anthropic: claude-sonnet-4, claude-opus-4 + - OpenRouter: anthropic/claude-sonnet-4.5 + +#### Quick Thinking LLM +- **Purpose**: Fast analysis, data summarization, routine tasks +- **Characteristics**: Smaller models, faster, cost-effective +- **Use Cases**: + - Analyst report generation + - Data interpretation + - Tool calling +- **Recommended Models**: + - OpenAI: gpt-4o-mini, gpt-4o + - Anthropic: claude-sonnet-4 + - OpenRouter: openai/gpt-4o-mini + +### Model Selection Guidelines + +**For Production:** +```python +config["deep_think_llm"] = "o1-preview" # Best reasoning +config["quick_think_llm"] = "gpt-4o-mini" # Cost-effective +``` + +**For Development/Testing:** +```python +config["deep_think_llm"] = "o4-mini" # Fast and cheaper +config["quick_think_llm"] = "gpt-4o-mini" # Consistent quality +``` + +**For Cost Optimization:** +```python +config["llm_provider"] = "openrouter" +config["deep_think_llm"] = "anthropic/claude-sonnet-4.5" +config["quick_think_llm"] = "openai/gpt-4o-mini" +``` + +## Provider-Specific Configuration + +### OpenAI Configuration + +```python +config = { + "llm_provider": "openai", + "deep_think_llm": "o4-mini", + "quick_think_llm": "gpt-4o-mini", + "backend_url": "https://api.openai.com/v1" +} +``` + +Environment: +```bash +export OPENAI_API_KEY=sk-your_key_here +``` + +### Anthropic Configuration + +```python +config = { + "llm_provider": "anthropic", + "deep_think_llm": "claude-sonnet-4-20250514", + "quick_think_llm": "claude-sonnet-4-20250514", + "backend_url": "https://api.anthropic.com" +} +``` + +Environment: +```bash +export ANTHROPIC_API_KEY=sk-ant-your_key_here +``` + +### OpenRouter Configuration + +```python +config = { + "llm_provider": "openrouter", + "deep_think_llm": "anthropic/claude-sonnet-4.5", + "quick_think_llm": "openai/gpt-4o-mini", + "backend_url": "https://openrouter.ai/api/v1" +} +``` + +Environment: +```bash +export OPENROUTER_API_KEY=sk-or-v1-your_key_here +export OPENAI_API_KEY=sk-your_key_here # Required for embeddings +``` + +**Note**: OpenRouter uses `provider/model-name` format: +- `anthropic/claude-sonnet-4.5` +- `openai/gpt-4o` +- `google/gemini-pro` + +### Google Generative AI Configuration + +```python +config = { + "llm_provider": "google", + "deep_think_llm": "gemini-2.0-flash", + "quick_think_llm": "gemini-2.0-flash" +} +``` + +Environment: +```bash +export GOOGLE_API_KEY=your_key_here +``` + +### Ollama Configuration + +```python +config = { + "llm_provider": "ollama", + "deep_think_llm": "mistral", + "quick_think_llm": "mistral", + "backend_url": "http://localhost:11434/v1" +} +``` + +Prerequisites: +```bash +# Install Ollama +curl -fsSL https://ollama.com/install.sh | sh + +# Pull model +ollama pull mistral + +# Start Ollama server +ollama serve +``` + +## Error Handling + +### Rate Limit Handling + +Unified rate limit error handling across providers: + +```python +from tradingagents.utils.exceptions import LLMRateLimitError + +try: + response = llm.invoke(messages) +except LLMRateLimitError as e: + print(f"Rate limit hit: {e.message}") + if e.retry_after: + print(f"Retry after {e.retry_after} seconds") +``` + +Location: `tradingagents/utils/exceptions.py` + +### Provider-Specific Errors + +Each provider may raise different errors: + +**OpenAI:** +- `RateLimitError` → Retry after specified time +- `InvalidRequestError` → Check model name, parameters +- `AuthenticationError` → Verify API key + +**Anthropic:** +- `RateLimitError` → Retry with backoff +- `InvalidRequestError` → Check message format +- `APIError` → Server-side issues + +**OpenRouter:** +- Follows OpenAI error format +- Additional headers required for attribution + +### Fallback Strategy + +Implement provider fallback for resilience: + +```python +providers = ["openai", "anthropic", "openrouter"] + +for provider in providers: + try: + config["llm_provider"] = provider + ta = TradingAgentsGraph(config=config) + result = ta.propagate(ticker, date) + break + except LLMRateLimitError: + continue +``` + +## Cost Optimization + +### Model Cost Comparison + +**Deep Thinking Tasks:** +| Provider | Model | Cost/1M Tokens (Input/Output) | +|----------|-------|-------------------------------| +| OpenAI | o4-mini | $1.50 / $6.00 | +| OpenAI | o1-preview | $15.00 / $60.00 | +| Anthropic | claude-sonnet-4 | $3.00 / $15.00 | +| OpenRouter | Varies by model | Check OpenRouter pricing | + +**Quick Thinking Tasks:** +| Provider | Model | Cost/1M Tokens (Input/Output) | +|----------|-------|-------------------------------| +| OpenAI | gpt-4o-mini | $0.15 / $0.60 | +| OpenAI | gpt-4o | $2.50 / $10.00 | +| Google | gemini-2.0-flash | Free tier available | +| Ollama | Local models | Free (local) | + +### Cost Reduction Strategies + +1. **Use Smaller Models for Simple Tasks** + ```python + config["quick_think_llm"] = "gpt-4o-mini" # Instead of gpt-4o + ``` + +2. **Reduce Debate Rounds** + ```python + config["max_debate_rounds"] = 1 # Instead of 2-3 + ``` + +3. **Use OpenRouter for Competitive Pricing** + ```python + config["llm_provider"] = "openrouter" + ``` + +4. **Cache LLM Responses** + ```python + # Implemented in agent memory system + memory.store_analysis(ticker, date, result) + ``` + +5. **Use Ollama for Development** + ```python + config["llm_provider"] = "ollama" # No API costs + ``` + +## Embeddings + +### Embedding Provider + +TradingAgents uses OpenAI embeddings for vector storage (memory system): + +```python +from langchain_openai import OpenAIEmbeddings + +embeddings = OpenAIEmbeddings(model="text-embedding-3-small") +``` + +**Important**: Even when using non-OpenAI LLM providers (Anthropic, Google, etc.), `OPENAI_API_KEY` is still required for embeddings. + +### Alternative Embedding Providers + +For fully offline operation, consider: + +```python +from langchain_community.embeddings import HuggingFaceEmbeddings + +embeddings = HuggingFaceEmbeddings( + model_name="sentence-transformers/all-MiniLM-L6-v2" +) +``` + +Note: This requires updating the memory initialization code. + +## Performance Considerations + +### Latency + +**Provider Latency (Approximate):** +- OpenAI: 1-3 seconds per request +- Anthropic: 1-2 seconds per request +- Google: 0.5-1.5 seconds per request +- OpenRouter: Varies by underlying model +- Ollama: 0.5-5 seconds (depends on local hardware) + +### Throughput + +**Concurrent Requests:** +- OpenAI: Tier-based limits (20-5000 RPM) +- Anthropic: Tier-based limits (50-2000 RPM) +- OpenRouter: Model-specific limits +- Ollama: Limited by local GPU/CPU + +### Caching + +LangChain provides built-in caching: + +```python +from langchain.cache import SQLiteCache +from langchain.globals import set_llm_cache + +set_llm_cache(SQLiteCache(database_path=".langchain.db")) +``` + +## Best Practices + +1. **Set API Keys as Environment Variables**: Never hardcode keys +2. **Use Two-Tier Model Strategy**: Deep/quick thinking separation +3. **Implement Error Handling**: Catch rate limits and retry +4. **Monitor Costs**: Track token usage and expenses +5. **Test with Cheaper Models**: Use o4-mini/gpt-4o-mini for development +6. **Cache When Possible**: Avoid redundant API calls +7. **Use OpenRouter for Flexibility**: Easy switching between providers +8. **Implement Timeouts**: Prevent hanging requests +9. **Log API Usage**: Track which models are called +10. **Consider Local Models**: Ollama for sensitive data or development + +## References + +- [Multi-Agent System](multi-agent-system.md) +- [Configuration Guide](../guides/configuration.md) +- [Adding LLM Provider Guide](../guides/adding-llm-provider.md) +- [TradingGraph API](../api/trading-graph.md) diff --git a/docs/architecture/multi-agent-system.md b/docs/architecture/multi-agent-system.md new file mode 100644 index 00000000..ac8a4626 --- /dev/null +++ b/docs/architecture/multi-agent-system.md @@ -0,0 +1,353 @@ +# Multi-Agent System Architecture + +TradingAgents implements a multi-agent architecture that mirrors real-world trading firms, where specialized teams collaborate to make informed investment decisions. + +## System Overview + +The framework decomposes complex trading analysis into specialized agent roles, each with specific responsibilities and expertise. Agents collaborate through structured workflows orchestrated by LangGraph. + +``` +┌─────────────────────────────────────────────────────────────────────┐ +│ DATA LAYER │ +├─────────────────────────────────────────────────────────────────────┤ +│ yfinance │ Alpha Vantage │ FRED (NEW) │ Alpaca │ Multi-Timeframe │ +└─────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────┐ +│ ANALYSIS LAYER │ +├─────────────────────────────────────────────────────────────────────┤ +│ Market │ Momentum │ Macro │ Correlation │ News │ Fundamentals │ +│ Analyst │ Analyst │ Analyst │ Analyst │ │ │ +│ │ (NEW) │ (NEW) │ (NEW) │ │ │ +├─────────────────────────────────────────────────────────────────────┤ +│ Bull ←── Debate ──→ Bear → Research Manager │ +├─────────────────────────────────────────────────────────────────────┤ +│ Trader → Signal + Confidence Score │ +├─────────────────────────────────────────────────────────────────────┤ +│ Risk Debate → Position Sizing Manager (NEW) │ +└─────────────────────────────────────────────────────────────────────┘ +``` + +## Agent Roles + +### Analyst Team + +The analyst team conducts specialized analysis, each agent focusing on a specific domain: + +#### Market Analyst (Technical) +- **Responsibility**: Technical analysis using price patterns and indicators +- **Tools**: MACD, RSI, Bollinger Bands, moving averages +- **Output**: Technical trends, support/resistance levels, momentum signals +- **Location**: `tradingagents/agents/analysts/market_analyst.py` + +#### Fundamentals Analyst +- **Responsibility**: Company financial health and valuation analysis +- **Tools**: Balance sheet, income statement, cash flow, financial ratios +- **Output**: Intrinsic value estimates, financial health assessment +- **Location**: `tradingagents/agents/analysts/fundamentals_analyst.py` + +#### Sentiment Analyst +- **Responsibility**: Social media and public sentiment analysis +- **Tools**: Reddit data (PRAW), sentiment scoring algorithms +- **Output**: Public sentiment scores, trending topics, investor mood +- **Location**: `tradingagents/agents/analysts/sentiment_analyst.py` + +#### News Analyst +- **Responsibility**: Global news and macroeconomic event analysis +- **Tools**: News APIs, event impact models +- **Output**: Event impact assessments, market-moving news identification +- **Location**: `tradingagents/agents/analysts/news_analyst.py` + +### Researcher Team + +Researchers engage in structured debates to evaluate analyst insights: + +#### Bull Researcher +- **Responsibility**: Identify bullish opportunities and positive catalysts +- **Approach**: Seeks upside potential, growth drivers, favorable trends +- **Output**: Bull case arguments with supporting evidence + +#### Bear Researcher +- **Responsibility**: Identify risks and potential downsides +- **Approach**: Seeks red flags, overvaluation signals, adverse conditions +- **Output**: Bear case arguments with risk assessments + +#### Research Manager +- **Responsibility**: Moderate debates, synthesize perspectives +- **Process**: Coordinates debate rounds, ensures balanced analysis +- **Output**: Balanced research report with bull/bear synthesis + +### Trader Agent + +The trader makes final trading decisions based on comprehensive analysis: + +- **Input**: Analyst reports, researcher debates, market conditions +- **Process**: Weighs evidence, assesses conviction levels +- **Output**: Trading signal (BUY/SELL/HOLD) with confidence score +- **Location**: `tradingagents/agents/trader.py` + +### Risk Management Team + +Risk agents evaluate portfolio impact and validate strategies: + +#### Risk Analysts +- **Responsibility**: Assess volatility, liquidity, correlation risks +- **Tools**: Risk metrics, scenario analysis, stress testing +- **Output**: Risk assessments with mitigation recommendations + +#### Portfolio Manager +- **Responsibility**: Final approval/rejection of trading proposals +- **Process**: Reviews risk reports, validates against portfolio constraints +- **Output**: Approved orders or rejection with reasoning +- **Location**: `tradingagents/agents/portfolio_manager.py` + +## Agent Workflow + +### 1. Data Collection + +All analysts access data through the unified data vendor interface: + +```python +from tradingagents.agents.utils.agent_utils import ( + get_stock_data, + get_indicators, + get_fundamentals, + get_news +) +``` + +### 2. Parallel Analysis + +Analysts work in parallel, each producing specialized reports: + +``` +Market Analyst → Technical Report +Fundamentals → Financial Report +Sentiment → Sentiment Report +News Analyst → Event Report +``` + +### 3. Research Debate + +Researchers debate analyst findings over multiple rounds: + +``` +Round 1: Bull presents arguments → Bear counters +Round 2: Bear presents risks → Bull defends +... +Final: Research Manager synthesizes +``` + +Configuration: `config["max_debate_rounds"]` (default: 1) + +### 4. Trading Decision + +Trader evaluates research synthesis: + +```python +decision = { + "action": "BUY" | "SELL" | "HOLD", + "confidence_score": 0.0 to 1.0, + "reasoning": "...", + "position_size": float +} +``` + +### 5. Risk Validation + +Risk team reviews the trading proposal: + +``` +Risk Analysts → Risk Assessment +Portfolio Manager → Approve or Reject +``` + +Configuration: `config["max_risk_discuss_rounds"]` (default: 1) + +## State Management + +TradingAgents uses LangGraph for state management across the agent workflow. + +### AgentState + +The main state object carries information through the graph: + +```python +@dataclass +class AgentState: + ticker: str + date: str + analyst_reports: Dict[str, str] + research_synthesis: str + trading_decision: Dict[str, Any] + risk_assessment: str + final_decision: Dict[str, Any] +``` + +Location: `tradingagents/agents/utils/agent_states.py` + +### InvestDebateState + +Manages researcher debate rounds: + +```python +@dataclass +class InvestDebateState: + bull_arguments: List[str] + bear_arguments: List[str] + debate_round: int + synthesis: str +``` + +### RiskDebateState + +Manages risk team discussions: + +```python +@dataclass +class RiskDebateState: + risk_assessments: List[str] + discussion_round: int + final_recommendation: str +``` + +## Memory System + +Agents maintain context through a vector-based memory system: + +### FinancialSituationMemory + +- **Purpose**: Store and retrieve historical analysis context +- **Backend**: ChromaDB vector store +- **Features**: + - Semantic search for relevant past analyses + - Recency, relevancy, and importance scoring (FinMem pattern) + - Persistent storage across runs +- **Location**: `tradingagents/agents/utils/memory.py` + +## Tool Integration + +Agents access data through a unified tool interface: + +### Data Tools + +Available to all analyst agents: + +- `get_stock_data(ticker, start_date, end_date)` - Historical prices +- `get_indicators(ticker, indicators_list)` - Technical indicators +- `get_fundamentals(ticker)` - Financial metrics +- `get_balance_sheet(ticker)` - Balance sheet data +- `get_cashflow(ticker)` - Cash flow statements +- `get_income_statement(ticker)` - Income statements +- `get_news(ticker, date)` - Company-specific news +- `get_global_news(date)` - Market-wide news + +Location: `tradingagents/agents/utils/agent_utils.py` + +### Tool Nodes + +LangGraph ToolNodes wrap data access functions: + +```python +from langgraph.prebuilt import ToolNode + +analyst_tools = ToolNode([ + get_stock_data, + get_indicators, + get_fundamentals +]) +``` + +## Conditional Routing + +The graph uses conditional logic to route between agents: + +### Debate Continuation + +```python +def should_continue_debate(state: InvestDebateState) -> str: + if state.debate_round >= config["max_debate_rounds"]: + return "finalize" + return "continue_debate" +``` + +### Risk Approval + +```python +def check_risk_approval(state: AgentState) -> str: + if state.risk_assessment["approved"]: + return "execute" + return "reject" +``` + +Location: `tradingagents/graph/conditional_logic.py` + +## Extensibility + +The multi-agent architecture is designed for extensibility: + +### Adding New Analysts + +1. Create analyst class inheriting from base analyst +2. Implement `analyze()` method +3. Register in analyst list +4. Agent automatically joins parallel analysis + +See [Adding New Analyst Guide](../guides/adding-new-analyst.md) + +### Adding Custom Workflows + +1. Define new state classes +2. Create agent nodes +3. Add conditional routing logic +4. Integrate into main graph + +## Performance Considerations + +### Parallel Execution + +Analysts run in parallel to minimize latency: + +```python +# Analysts execute simultaneously +analyst_nodes = { + "market": market_analyst, + "fundamentals": fundamentals_analyst, + "sentiment": sentiment_analyst, + "news": news_analyst +} +``` + +### Debate Rounds + +More debate rounds increase analysis depth but also API costs: + +- 1 round: Fast, lower cost, adequate for most cases +- 2-3 rounds: Deeper analysis, higher confidence +- 4+ rounds: Diminishing returns, significantly higher cost + +### Memory Optimization + +Vector store queries are batched and cached: + +```python +memory = FinancialSituationMemory( + persist_directory="./memory_cache" +) +``` + +## Best Practices + +1. **Select Relevant Analysts**: Only enable analysts needed for your strategy +2. **Tune Debate Rounds**: Start with 1 round, increase only if needed +3. **Monitor API Usage**: Track LLM API calls and costs +4. **Use Memory Wisely**: Leverage past analyses for similar contexts +5. **Test Incrementally**: Validate each agent's output before full integration + +## References + +- [Data Flow Architecture](data-flow.md) +- [LLM Integration](llm-integration.md) +- [TradingGraph API](../api/trading-graph.md) +- [Agent APIs](../api/agents.md) diff --git a/docs/development/contributing.md b/docs/development/contributing.md new file mode 100644 index 00000000..9afa175e --- /dev/null +++ b/docs/development/contributing.md @@ -0,0 +1,405 @@ +# Contributing to TradingAgents + +Thank you for your interest in contributing to TradingAgents! This guide will help you get started. + +## Code of Conduct + +By participating in this project, you agree to maintain a respectful and collaborative environment. + +## How to Contribute + +### Reporting Bugs + +1. **Check existing issues**: Search [GitHub Issues](https://github.com/TauricResearch/TradingAgents/issues) first +2. **Create detailed report**: Include: + - Clear description of the bug + - Steps to reproduce + - Expected vs actual behavior + - Environment details (Python version, OS, etc.) + - Relevant code snippets or logs + - Screenshots if applicable + +Example bug report: +```markdown +**Description**: Market analyst fails when ticker has no data + +**Steps to Reproduce**: +1. Initialize TradingAgentsGraph +2. Call propagate("INVALID", "2024-01-01") +3. Error occurs in market analyst + +**Expected**: Graceful error handling +**Actual**: Unhandled exception + +**Environment**: +- Python 3.13 +- macOS 14.0 +- TradingAgents v0.1.0 + +**Error**: +```python +KeyError: 'close' +``` + +### Requesting Features + +1. **Check existing requests**: Search issues for similar requests +2. **Create feature request**: Include: + - Clear use case + - Proposed solution + - Alternative approaches considered + - Impact on existing functionality + +Example feature request: +```markdown +**Feature**: Add momentum analyst for multi-timeframe analysis + +**Use Case**: Traders need to analyze momentum across daily, weekly, and monthly timeframes + +**Proposed Solution**: Create MomentumAnalyst that: +- Calculates ROC, ADX across timeframes +- Identifies trend strength +- Generates momentum-based signals + +**Alternatives**: Could extend existing MarketAnalyst + +**Impact**: Adds new optional analyst, no breaking changes + +### Contributing Code + +#### 1. Fork and Clone + +```bash +# Fork repository on GitHub +# Then clone your fork +git clone https://github.com/YOUR_USERNAME/TradingAgents.git +cd TradingAgents +``` + +#### 2. Set Up Development Environment + +Follow the [Development Setup Guide](setup.md): + +```bash +# Create virtual environment +conda create -n tradingagents python=3.13 +conda activate tradingagents + +# Install dependencies +pip install -r requirements.txt +pip install -e . + +# Install development tools +pip install pytest black isort flake8 mypy pre-commit +pre-commit install +``` + +#### 3. Create Feature Branch + +```bash +git checkout -b feature/your-feature-name +``` + +Branch naming conventions: +- `feature/` - New features +- `fix/` - Bug fixes +- `docs/` - Documentation updates +- `test/` - Test additions/improvements +- `refactor/` - Code refactoring + +#### 4. Make Changes + +Follow coding standards: +- **PEP 8**: Python style guide +- **Type Hints**: Add type annotations +- **Docstrings**: Google-style docstrings +- **Tests**: Write tests for new code +- **Documentation**: Update relevant docs + +Example with type hints and docstrings: + +```python +from typing import Dict, List, Any + +def analyze_momentum( + ticker: str, + date: str, + timeframes: List[str] +) -> Dict[str, Any]: + """ + Analyze momentum across multiple timeframes. + + Args: + ticker: Stock ticker symbol (e.g., "NVDA") + date: Analysis date in YYYY-MM-DD format + timeframes: List of timeframes ("daily", "weekly", "monthly") + + Returns: + Dictionary containing momentum analysis: + - trend_strength: float between 0.0 and 1.0 + - direction: "bullish" or "bearish" + - signals: list of identified signals + + Raises: + ValueError: If ticker or date format is invalid + DataUnavailableError: If data cannot be retrieved + + Example: + >>> result = analyze_momentum("NVDA", "2024-05-10", ["daily", "weekly"]) + >>> print(result["trend_strength"]) + 0.75 + """ + # Implementation + pass +``` + +#### 5. Write Tests + +Create tests following TDD approach: + +```python +# tests/unit/test_momentum_analyst.py + +import pytest +from tradingagents.agents.analysts.momentum_analyst import MomentumAnalyst +from unittest.mock import Mock + +def test_momentum_analyst_initialization(): + """Test MomentumAnalyst can be initialized.""" + llm = Mock() + tools = [] + + analyst = MomentumAnalyst(llm, tools) + + assert analyst.name == "momentum" + assert analyst.llm == llm + +def test_momentum_analyst_analyze(): + """Test analyst generates momentum analysis.""" + # Arrange + llm = Mock() + llm.invoke.return_value = Mock( + content="Momentum analysis: Strong uptrend..." + ) + tools = [Mock(name="get_stock_data")] + + analyst = MomentumAnalyst(llm, tools) + + # Act + report = analyst.analyze("NVDA", "2024-05-10") + + # Assert + assert "momentum" in report.lower() + assert llm.invoke.called +``` + +Run tests: +```bash +pytest tests/ -v +pytest tests/ --cov=tradingagents --cov-report=term-missing +``` + +#### 6. Update Documentation + +Update relevant documentation: +- **API docs**: Add new classes/functions to API reference +- **Guides**: Create/update guides for new features +- **README**: Update if adding major features +- **Docstrings**: Ensure all public APIs have docstrings + +#### 7. Format and Lint + +```bash +# Format code +black tradingagents/ tests/ + +# Sort imports +isort tradingagents/ tests/ + +# Check linting +flake8 tradingagents/ tests/ + +# Type checking +mypy tradingagents/ +``` + +#### 8. Commit Changes + +Follow conventional commits format: + +```bash +git add . +git commit -m "feat(analysts): add momentum analyst for multi-timeframe analysis" +``` + +Commit message format: +``` +(): + + + +