From 24edac65c401901e7723d23ea49d6a66265fc53f Mon Sep 17 00:00:00 2001 From: "swj.premkumar" Date: Wed, 14 Jan 2026 05:58:33 -0600 Subject: [PATCH] - **Standalone HTML Reports**: Refactored report generation to perform server-side Markdown-to-HTML rendering using Python. - Removed dependency on client-side `marked.js` and CDNs. - Reports are now fully offline-capable. - Cleaned up JSON keys to remove `.md` extensions for cleaner data structure. - **Google News Adapter**: Implemented `get_google_global_news` adapter in `google.py` to match the standard `(curr_date, look_back_days)` interface, adhering to the Adapter Pattern and fixing signature mismatches. - **Robust Demo Script**: Created `run_agent.py` (replacing demo scripts) with: - Automatic `.env` loading. - `backend_url` handling (clearing OpenAI defaults when using Anthropic). - Hardened configuration for "Deep Analysis" (Debate Rounds=2). - Pre-configured Google News vendor to bypass AlphaVantage rate limits. ### Fixed - **Rate Limit Crash**: Fixed `AlphaVantageRateLimitError` by switching default news vendor to Google in `run_agent.py`. --- .gitignore | 1 + CHANGELOG.md | 31 ++++ README.md | 12 ++ run_agent.py | 140 ++++++++++++++++++ scripts/generate_report_html.py | 12 +- startAgent.sh | 2 +- startAgentInteractive.sh | 101 +++++++++++++ .../agents/utils/core_stock_tools.py | 16 +- .../agents/utils/fundamental_data_tools.py | 15 +- tradingagents/agents/utils/news_data_tools.py | 30 ++-- .../utils/technical_indicators_tools.py | 14 +- tradingagents/dataflows/google.py | 35 +++-- tradingagents/dataflows/googlenews_utils.py | 4 +- tradingagents/dataflows/interface.py | 4 +- tradingagents/graph/trading_graph.py | 1 - 15 files changed, 371 insertions(+), 47 deletions(-) create mode 100644 run_agent.py create mode 100755 startAgentInteractive.sh diff --git a/.gitignore b/.gitignore index 125352dd..8b58e42b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ eval_data/ .env venv_torture_test *.log +data_cache \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 697d7fc3..567cad38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,37 @@ All notable changes to the **TradingAgents** project will be documented in this file. +## [Unreleased] - 2026-01-14 + +### Added +- **Standalone HTML Reports**: Refactored report generation to perform server-side Markdown-to-HTML rendering using Python. + - Removed dependency on client-side `marked.js` and CDNs. + - Reports are now fully offline-capable. + - Cleaned up JSON keys to remove `.md` extensions for cleaner data structure. +- **Google News Adapter**: Implemented `get_google_global_news` adapter in `google.py` to match the standard `(curr_date, look_back_days)` interface, adhering to the Adapter Pattern and fixing signature mismatches. +- **Robust Demo Script**: Created `run_agent.py` (replacing demo scripts) with: + - Automatic `.env` loading. + - `backend_url` handling (clearing OpenAI defaults when using Anthropic). + - Hardened configuration for "Deep Analysis" (Debate Rounds=2). + - Pre-configured Google News vendor to bypass AlphaVantage rate limits. + +### Fixed +- **Rate Limit Crash**: Fixed `AlphaVantageRateLimitError` by switching default news vendor to Google in `run_agent.py`. +- **Interface Mismatch**: Fixed `TypeError` in `get_global_news` where string dates were passed to integer arguments. +- **Logic Crash**: Fixed `TypeError` in `TradingAgentsGraph.apply_trend_override` caused by duplicate arguments in the method call. +- **Broken Entry Point**: Updated `startAgent.sh` to point to the correct `run_agent.py` script instead of a non-existent file. + +## [Released] - 2026-01-13 + +### Added +- **Dynamic Parameter Tuning (The Learning Loop)**: Implemented full self-reflection cycle. The Reflector agent now parses its own advice into JSON (`rsi_period`, `stop_loss_pct`), persists it to `data_cache/runtime_config.json`, and the Market Analyst loads it to tune the Regime Detector in real-time. +- **Audit Archival**: Every tuning event is now archived to `results/{TICKER}/{DATE}/runtime_config.json` for historical auditing, ensuring we can reproduce why parameters changed on any given day. +- **Atomic Persistence**: Implemented `agent_utils.write_json_atomic` to prevent race conditions during config saves. +- **Centralized Config**: Moved hardcoded paths to `default_config.py` (DRY principle). + +### Fixed +- **Reflector Logic Gap**: The Reflector was previously "shouting into the void"β€”making suggestions but having no mechanism to apply them. This circuit is now closed. + ## [Unreleased] - 2026-01-11 ### Added diff --git a/README.md b/README.md index 79c073b2..1ca2e81f 100644 --- a/README.md +++ b/README.md @@ -185,6 +185,18 @@ cp .env.example .env **Note:** We are happy to partner with Alpha Vantage to provide robust API support for TradingAgents. You can get a free AlphaVantage API [here](https://www.alphavantage.co/support/#api-key), TradingAgents-sourced requests also have increased rate limits to 60 requests per minute with no daily limits. Typically the quota is sufficient for performing complex tasks with TradingAgents thanks to Alpha Vantage’s open-source support program. If you prefer to use OpenAI for these data sources instead, you can modify the data vendor settings in `tradingagents/default_config.py`. +### Quick Start (Recommended) + +To run a deep analysis on a specific ticker and automatically open the result: + +```bash +./startAgent.sh [TICKER] [DATE] +# Example: +./startAgent.sh NVDA 2024-05-10 +``` + +This script executes the robust `run_agent.py` logic (configured for Deep Analysis) and generates a **Standalone HTML Report** that is fully offline-capable (no external JS dependencies). + ### CLI Usage You can also try out the CLI directly by running: diff --git a/run_agent.py b/run_agent.py new file mode 100644 index 00000000..acf0c330 --- /dev/null +++ b/run_agent.py @@ -0,0 +1,140 @@ +import sys +import os +import argparse +from dotenv import load_dotenv +from datetime import datetime +from tradingagents.graph.trading_graph import TradingAgentsGraph +from tradingagents.default_config import DEFAULT_CONFIG + +def main(): + parser = argparse.ArgumentParser(description="Run Trading Agent with Deep Analysis and Claude Sonnet 4.5 Thinking") + parser.add_argument("ticker", type=str, help="Stock Ticker Symbol (e.g., AAPL)") + parser.add_argument("--date", type=str, default=datetime.now().strftime("%Y-%m-%d"), help="Trade Date (YYYY-MM-DD)") + + args = parser.parse_args() + + # Load environment variables + load_dotenv() + + # 1. Configuration Setup + # Mixing CLI args with required distinct configuration + config = DEFAULT_CONFIG.copy() + + # User Request: "anthropic claude sonnet 4.5 thinking" + config["llm_provider"] = "anthropic" + config["deep_think_llm"] = "claude-sonnet-4-5-thinking" + + # FIX: Clear backend_url so it doesn't default to OpenAI's endpoint, + # unless specified in environment (e.g. for proxy) + config["backend_url"] = os.getenv("BACKEND_URL") + + # Also setting quick_think to a high-quality model to support the deep analysis, + # though usually this is lighter. User emphasis was on "thinking" model. + config["quick_think_llm"] = "claude-sonnet-4-5-thinking" + + # User Request: "Deep Analysis" + # We enable debate rounds to trigger the deep thinking loops + config["max_debate_rounds"] = 2 + config["max_risk_discuss_rounds"] = 2 + + # 2. Tool Configuration (Data Vendors) + # FIX: Use Google for news to avoid AlphaVantage rate limits (and handle fallback better) + config["tool_vendors"] = { + "get_news": "google", + "get_global_news": "google" + } + + print(f"πŸš€ Initializing Trading Agent for {args.ticker} on {args.date}") + print(f"🧠 Model: {config['deep_think_llm']} (Provider: {config['llm_provider']})") + print(f"πŸ” Deep Analysis: ENABLED (Debate Rounds: {config['max_debate_rounds']})") + print(f"πŸ“° News Vendor: Google (Rate Limit Bypass)") + + # 3. Initialize Graph + # User Request: "Fundamental Analysis" (Explicitly included) + analysts = ["market", "fundamentals", "news", "social"] + + try: + agent_graph = TradingAgentsGraph( + selected_analysts=analysts, + config=config, + debug=True # Enable debug to see the "Thinking" process in logs + ) + + # 4. Run Propagation + final_state, signal = agent_graph.propagate(args.ticker, args.date) + + # 5. Output Summary + print("\n" + "="*50) + print(f"🏁 FINAL DECISION for {args.ticker}") + print("="*50) + + decision = final_state.get("final_trade_decision", "NO DECISION") + if isinstance(decision, dict): + print(f"ACTION: {decision.get('action')}") + print(f"QUANTITY: {decision.get('quantity')}") + print(f"REASONING: {decision.get('reasoning')}") + else: + print(f"DECISION: {decision}") + + print("\nβœ… Run Complete. Check 'eval_results' for detailed logs and reports.") + + # 6. Generate HTML Report + print("\nπŸ“Š Generating Standalone HTML Report...") + + # 6.1 Identify Reports Directory + base_dir = os.path.dirname(os.path.abspath(__file__)) + results_dir = os.path.join(base_dir, "results", args.ticker, args.date) + reports_dir = os.path.join(results_dir, "reports") + os.makedirs(reports_dir, exist_ok=True) + + # 6.2 Write Markdown Files from State + # Map state keys to friendly filenames + report_map = { + "market_report": "market_analyst.md", + "news_report": "news_analyst.md", + "fundamentals_report": "fundamentals_analyst.md", + "sentiment_report": "sentiment_analyst.md", + "investment_plan": "investment_plan.md", + "trader_investment_plan": "trader_decision.md" # Optional/Internal + } + + + print(f"DEBUG: Calculated raw reports_dir: {reports_dir}") + if not os.path.exists(reports_dir): + print(f"DEBUG: creating directory {reports_dir}") + os.makedirs(reports_dir, exist_ok=True) + + for key, filename in report_map.items(): + content = final_state.get(key) + if content: + # Ensure directory exists (User Request) + if not os.path.exists(reports_dir): + os.makedirs(reports_dir, exist_ok=True) + + file_path = os.path.join(reports_dir, filename) + with open(file_path, "w", encoding="utf-8") as f: + f.write(str(content)) + + # 6.3 Call Generator with CORRECT Path + import subprocess + generator_script = os.path.join(base_dir, "scripts", "generate_report_html.py") + + try: + # generator expects: + print(f"DEBUG: Calling generator with path: {reports_dir}") + cmd = [sys.executable, generator_script, reports_dir] + subprocess.run(cmd, check=True) + print(f"βœ… Report Generated Successfully: {reports_dir}/index.html") + except subprocess.CalledProcessError as e: + print(f"⚠️ Report Generation Failed: {e}") + except Exception as e: + print(f"⚠️ Error running report generator: {e}") + + + except Exception as e: + print(f"\n❌ ERROR: Agents failed to run: {e}") + import traceback + traceback.print_exc() + +if __name__ == "__main__": + main() diff --git a/scripts/generate_report_html.py b/scripts/generate_report_html.py index e56afe9a..875f8a67 100644 --- a/scripts/generate_report_html.py +++ b/scripts/generate_report_html.py @@ -1,5 +1,6 @@ import sys import json +import markdown from pathlib import Path # Add project root to sys.path to allow importing tradingagents @@ -18,7 +19,6 @@ TEMPLATE = """ Trading Agent Report - {ticker} - {date} -