# TradingAgents 技术架构分析及 akshare 集成修改 > **文档时间**: 2026-05-05 > **项目路径**: `/home/ubuntu/forgithub/TradingAgents` > **运行端口**: `:8500` (Web UI) --- ## 一、项目概述 TradingAgents 是一个基于 LLM 的多智能体(Multi-Agent)金融交易分析框架。它模拟真实投资决策中的"研究员→辩论→交易员"流程,由多个分析师角色协作完成对单只股票的深入分析,并输出最终交易决策(买入/卖出/持有)。 核心思想:**用 LLM 扮演不同角色的分析师,使用真实市场数据工具,通过辩论机制达成投资共识。** --- ## 二、技术栈 | 层次 | 技术选型 | |------|----------| | 多智能体编排 | LangGraph(StateGraph) | | LLM 接口 | LangChain + DeepSeek / OpenAI | | 工具系统 | LangChain `@tool` 装饰器 | | 数据源 | akshare / yfinance / Alpha Vantage | | Web 服务 | FastAPI + 自定义 SPA 页面 | | 部署 | systemd(`tradingagents.service`) | --- ## 三、架构分层 ### 3.1 整体流程 ``` 用户输入 (ticker + date) │ ▼ ┌──────────────────────┐ │ TradingAgentsGraph │ ← LangGraph StateGraph │ (trading_graph.py) │ └──────┬───────────────┘ │ ▼ ┌───────────────────────────────────────┐ │ Researcher Team │ │ ┌──────────┐ ┌──────────┐ │ │ │ Market │ │ News │ ... │ ← 并行分析 │ │ Analyst │ │ Analyst │ │ │ └────┬─────┘ └────┬─────┘ │ │ │ │ │ │ └─────┬──────┘ │ │ ▼ │ │ Debate Layer (1~N rounds) │ ← 多轮辩论 │ │ │ │ ▼ │ │ Final Decision │ │ (Buy/Sell/Hold) │ └───────────────────────────────────────┘ │ ▼ 输出:分析报告 + 交易决策 ``` ### 3.2 节点说明 | 节点 | 文件 | 角色 | 使用的工具 | |------|------|------|-----------| | **Market Analyst** | `analysts/market_analyst.py` | 技术面分析师 | `get_stock_data`, `get_indicators` (RSI, MACD, 布林带等 19 项指标) | | **News Analyst** | `analysts/news_analyst.py` | 宏观新闻分析师 | `get_news`, `get_global_news` | | **Social Media Analyst** | `analysts/social_media_analyst.py` | 社交媒体分析师 | `get_news` | | **Fundamentals Analyst** | `analysts/fundamentals_analyst.py` | 基本面分析师 | `get_fundamentals`, `get_balance_sheet`, `get_cashflow`, `get_income_statement` | | **Debate Layer** | `trading_graph.py` | 多智能体辩论 | 各分析师报告交叉辩论 | | **Final Decision** | `trading_graph.py` | 最终交易决策 | 综合所有报告和辩论结果 | ### 3.3 数据流 ``` 每个 Analyst 节点 │ ├─ 构造 system prompt + 数据查询指令 ├─ 通过 LangChain tool 调用 route_to_vendor() ├─ route_to_vendor 按优先级选择数据源 │ ├─ akshare (默认) │ ├─ yfinance (fallback) │ └─ alpha_vantage (fallback) └─ 返回格式化数据,LLM 生成分析报告 ``` --- ## 四、核心模块 ### 4.1 Graph 编排层 **文件**: `tradingagents/graph/trading_graph.py` - 基于 LangGraph `StateGraph` 构建 - `setup_graph()` 按选定的分析师列表动态添加节点 - 支持配置 `max_debate_rounds`(默认 1 轮,可多轮辩论) - 输出最终状态和交易决策 **文件**: `tradingagents/graph/setup.py` - 提供 `create_complete_graph()` 工厂函数 - 封装完整流程:研究员 → 辩论 → 终判 ### 4.2 工具层 **文件**: `tradingagents/agents/utils/agent_utils.py` - `create_completion()` — LLM 调用封装,支持 reasoning_effort 参数 - `ToolKit` — 工具集管理,按分析师类型分发工具 **工具定义文件**(位于 `agents/utils/`): | 文件 | 包含工具 | |------|---------| | `core_stock_tools.py` | `get_stock_data` | | `technical_indicators_tools.py` | `get_indicators` (19 项技术指标) | | `fundamental_data_tools.py` | `get_fundamentals`, `get_balance_sheet`, `get_cashflow`, `get_income_statement` | | `news_data_tools.py` | `get_news`, `get_global_news`, `get_insider_transactions` | 所有工具统一通过 `route_to_vendor(method, *args)` 调用,实现数据源透明切换。 ### 4.3 数据源层 **入口**: `tradingagents/dataflows/interface.py` ``` route_to_vendor(method, *args) │ ├─ 读取 config["data_vendors"] 确定主数据源 ├─ 按 fallback 链依次尝试: │ ├─ akshare (优先级最高) │ ├─ yfinance │ └─ alpha_vantage └─ 返回第一个成功结果 ``` **配置系统**: `tradingagents/dataflows/config.py` + `tradingagents/default_config.py` - `default_config.py` 定义全局默认配置 - `config.py` 提供运行时 `get_config()` / `set_config()` 接口 - 可通过 `set_config({"data_vendors": {"...": "akshare"}})` 动态切换 ### 4.4 Web 服务层 **文件**: `web_server.py` - FastAPI 应用,端口 `8500` - `POST /api/analyze` — 提交分析任务(后台异步执行) - `GET /api/task/{task_id}` — 查询任务状态 - `GET /` — 内置 Web 面板(`web.html`) --- ## 五、akshare 集成修改(详细改动点) ### 5.1 修改动机 原始项目的默认数据源是 `yfinance`,存在以下问题: 1. **国内访问不稳定**: yfinance 对非美股数据支持有限,频繁触发 Rate Limit 2. **A 股数据质量差**: yfinance 的 A 股 OHLCV 数据常常缺失或不准确 3. **新闻源偏西式**: yfinance 的新闻来源主要是英文媒体,对 A 股分析不友好 4. **无国内数据源**: 缺少针对中国市场的本地化数据适配 **解决方案**: 集成 **akshare**(国内开源金融数据接口库)作为主数据源,yfinance 降级为 fallback。 ### 5.2 文件变更清单 | 文件 | 类型 | 行数 | 说明 | |------|------|------|------| | `tradingagents/dataflows/akshare_data.py` | **新增** | 563 | A股/港股/美股行情、财务数据、技术指标适配 | | `tradingagents/dataflows/akshare_news.py` | **新增** | 165 | 个股新闻(东方财富)、全球新闻(CCTV)适配 | | `tradingagents/dataflows/interface.py` | **修改** | +22 | 注册 akshare 到 VENDOR_METHODS,调优 fallback 顺序 | | `tradingagents/default_config.py` | **修改** | +14/-8 | 默认 vendor 改为 akshare | | `web_server.py` | **新增** | 124 | FastAPI Web 服务 + 后台任务 | | `web.html` | **新增** | 480 | 前端分析面板 | ### 5.3 akshare_data.py 详细设计 #### 5.3.1 市场检测 ```python def _detect_market(symbol: str) -> str: """自动识别股票所属市场""" # 6位数字 → A股上海/深圳 # 5位数字 → 港股 # 字母 → 美股 ``` 通过 ticker 格式自动路由到正确的 akshare 接口: - `600xxx` / `000xxx` / `300xxx` → A 股(`ak.stock_zh_a_hist`) - `00700` / `09988` → 港股(`ak.stock_hk_hist`) - `AAPL` / `MSFT` / `TSLA` → 美股(`ak.stock_us_hist`) #### 5.3.2 实现的接口 | 接口 | 签名 | akshare 函数 | 说明 | |------|------|-------------|------| | `get_stock_data` | `(symbol, start_date, end_date)` | `stock_zh_a_hist` / `stock_hk_hist` / `stock_us_hist` | 三市场统一 OHLCV 数据 | | `get_indicators` | `(symbol, indicator, curr_date, look_back_days)` | `stock_zh_a_hist` + 手动计算 | 19 项技术指标(RSI/MACD/布林带等) | | `get_fundamentals` | `(ticker, curr_date)` | `stock_individual_info_em` | 公司概况/市盈率/市净率等 | | `get_balance_sheet` | `(ticker, freq, curr_date)` | `stock_balance_sheet_by_report_em` | 资产负债表(年报/季报) | | `get_cashflow` | `(ticker, freq, curr_date)` | `stock_cash_flow_sheet_by_report_em` | 现金流量表 | | `get_income_statement` | `(ticker, freq, curr_date)` | `stock_profit_sheet_by_report_em` | 利润表 | | `get_insider_transactions` | `(ticker)` | — | 抛出异常触发 fallback 到 yfinance | #### 5.3.3 技术指标计算实现 采用**原始公式重算**而非依赖第三方库,确保数据一致性: ``` rsi → 100 - (100 / (1 + RS)) [平均涨跌幅比值法] macd → EMA(12) - EMA(26), Signal=EMA(9) [指数加权移动平均] bb → MA ± 2*STD [布林带] atr → TR 的 Wilder 平滑 [真实波幅] sma_20 → MA(20) ema_20 → EMA(20) ``` 共支持 19 项常用技术指标,覆盖趋势类、动量类、波动类、成交量类。 #### 5.3.4 输出格式 所有接口返回统一格式:**Pandas DataFrame → Markdown 表格字符串**,与 yfinance 适配器输出格式一致,保证 LLM 可正常解析。 ```markdown | Date | Open | High | Low | Close | Volume | |------------|--------|--------|--------|--------|-----------| | 2026-04-25 | 12.50 | 12.80 | 12.30 | 12.65 | 12345678 | ``` #### 5.3.5 TQDM 噪音抑制 akshare 内部使用 tqdm 显示进度条,在 LLM 工具调用场景中会产生大量噪音输出。通过在 akshare import 之前设置环境变量解决: ```python os.environ.setdefault('TQDM_DISABLE', '1') import akshare as ak ``` ### 5.4 akshare_news.py 详细设计 #### 5.4.1 实现的接口 | 接口 | 说明 | 数据来源 | |------|------|---------| | `get_news(ticker, start_date, end_date)` | 个股新闻 | `ak.stock_news_em`(东方财富) | | `get_global_news(curr_date, look_back_days, limit)` | 宏观/全球新闻 | `ak.news_cctv`(CCTV 新闻联播) | #### 5.4.2 Ticker 规范化 ``` 600362 → 600362 (A股,不变) 000001 → 000001 (A股,不变) AAPL → AAPL (美股,不变) → 回退到原 ticker ``` #### 5.4.3 东方财富新闻接口特点 - 返回 15 天内个股相关新闻,含标题、发布时间、来源 - 自动按日期过滤,限制返回最近 50 条 - 格式化输出为 Markdown 表格,便于 LLM 分析 #### 5.4.4 CCTV 新闻接口特点 - 获取新闻联播文字稿摘要 - 适合宏观政策面分析 - 输出为时间线格式的文本列表 ### 5.5 interface.py 修改详情 #### 5.5.1 VENDOR_METHODS 注册 为以下 9 个方法注册了 akshare 实现: ```python VENDOR_METHODS = { "get_stock_data": {"akshare": ..., "yfinance": ..., "alpha_vantage": ...}, "get_indicators": {"akshare": ..., "yfinance": ...}, "get_fundamentals": {"akshare": ..., "yfinance": ..., "alpha_vantage": ...}, "get_balance_sheet": {"akshare": ..., "yfinance": ..., "alpha_vantage": ...}, "get_cashflow": {"akshare": ..., "yfinance": ..., "alpha_vantage": ...}, "get_income_statement": {"akshare": ..., "yfinance": ..., "alpha_vantage": ...}, "get_news": {"akshare": ..., "yfinance": ...}, "get_global_news": {"akshare": ..., "yfinance": ...}, "get_insider_transactions": {"akshare": ..., "yfinance": ..., "alpha_vantage": ...}, } ``` #### 5.5.2 Fallback 顺序优化 `get_insider_transactions` 的字典键顺序调整为 **akshare → yfinance → alpha_vantage**: ``` 原始顺序: alpha_vantage → yfinance → [无 akshare] 修改后: akshare → yfinance → alpha_vantage ``` 原因:如果 alpha_vantage 排在 yfinance 之前,当 akshare 不支持时,会先尝试 alpha_vantage —— 它的 `get_api_key()` 在无 API key 时会抛出 `ValueError`(非 `AlphaVantageRateLimitError`),导致异常直接传播、不会继续尝试 yfinance。 调整后 fallback 路径: 1. `akshare` → 抛出 `AlphaVantageRateLimitError`(触发 fallback) 2. `yfinance` → 获取数据(成功)✓ #### 5.5.3 数据源分类优化 将 akshare 明确归入 `all_available_vendors`,确保它在所有 `data_vendors` 分类组中可用: ```python all_available_vendors = ["akshare", "yfinance", "alpha_vantage"] ``` ### 5.6 default_config.py 修改 ```python # 修改前 "data_vendors": { "core_stock_data": {"primary": "yfinance"}, "technical_indicators": {"primary": "yfinance"}, "fundamental_data": {"primary": "yfinance"}, "news_data": {"primary": "yfinance"}, } # 修改后 "data_vendors": { "core_stock_data": {"primary": "akshare"}, "technical_indicators": {"primary": "akshare"}, "fundamental_data": {"primary": "akshare"}, "news_data": {"primary": "akshare"}, } ``` 效果:所有分析请求默认走 akshare,彻底避免 yfinance Rate Limit 问题。 ### 5.7 web_server.py 设计 #### 5.7.1 API 端点 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/` | Web 分析面板(`web.html`) | | GET | `/api/health` | 健康检查 | | POST | `/api/analyze` | 提交分析任务,返回 task_id | | GET | `/api/task/{task_id}` | 查询任务状态和结果 | #### 5.7.2 异步任务机制 ```python class AnalysisRequest(BaseModel): ticker: str # 股票代码 date: Optional[str] # 分析日期,默认今天 analysts: Optional[list] # 分析师列表,默认 ["market", "news"] max_debate_rounds: int # 辩论轮次,默认 1 ``` 分析流程在 `BackgroundTasks` 中异步执行,通过线程安全的 `tasks_store` 字典管理任务状态。 ### 5.8 web.html 设计 - 纯原生 HTML/CSS/JS 单页应用 - 响应式设计,支持移动端 - 输入框:股票代码 + 日期 + 分析师选择 + 辩论轮次 - 实时轮询任务状态(每 3 秒) - 结果展示:Markdown 渲染的交易决策和分析报告(使用 marked.js) - 适配 DeepSeek 推理过程的 `reasoning_content` 展示 --- ## 六、部署架构 ``` http://129.211.173.87:8500/ │ ┌────────┴────────┐ │ web_server.py │ │ (FastAPI) │ │ port :8500 │ └────────┬────────┘ │ ┌────────┴────────┐ │ TradingAgents │ │ Graph │ │ (LangGraph) │ └──────┬─────────┘ │ ┌───────────┼───────────┐ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ akshare │ │yfinance │ │ alpha │ │ (主要) │ │(备用1) │ │vantage │ └─────────┘ └─────────┘ └─────────┘ ``` - **进程管理**: systemd `tradingagents.service` - **LLM 后端**: DeepSeek(通过 `DEEPSEEK_API_KEY` 环境变量) - **数据源**: akshare(默认,国内数据丰富)+ yfinance(fallback,美股内部交易等场景) --- ## 七、修改前后对比 | 维度 | 修改前 | 修改后 | |------|--------|--------| | **默认数据源** | yfinance | **akshare** | | **A 股行情** | 不稳定,频繁 Rate Limit | ✅ 稳定,无限制 | | **A 股财务数据** | ❌ 不可用 | ✅ 完整(资产负债表/利润表/现金流) | | **技术指标** | 依赖 yfinance 返回 | ✅ 原始公式重算,19 项指标 | | **个股新闻** | 英文来源,A 股覆盖差 | ✅ 东方财富,中文,时效性强 | | **宏观新闻** | 英文来源 | ✅ CCTV 新闻联播,政策面 | | **港股支持** | 部分 | ✅ 完整 | | **Rate Limit** | 频繁触发 | ✅ 已消除 | | **内部交易** | yfinance | akshare 自动 fallback 到 yfinance | | **Web UI** | ❌ 无 | ✅ 新增 FastAPI + Web 面板 | | **任务异步** | ❌ 无 | ✅ 后台任务 + 状态查询 | | **TQDM 噪音** | — | ✅ 已抑制 | --- ## 八、项目目录结构 ``` TradingAgents/ ├── tradingagents/ │ ├── agents/ │ │ ├── analysts/ # 四个分析师角色 │ │ │ ├── fundamentals_analyst.py │ │ │ ├── market_analyst.py │ │ │ ├── news_analyst.py │ │ │ └── social_media_analyst.py │ │ └── utils/ # 工具定义和 LLM 封装 │ │ ├── agent_utils.py # LLM 调用 + ToolKit │ │ ├── core_stock_tools.py # get_stock_data │ │ ├── technical_indicators_tools.py # get_indicators │ │ ├── fundamental_data_tools.py # 财务分析工具 │ │ └── news_data_tools.py # 新闻工具 │ ├── dataflows/ # 数据源层 │ │ ├── interface.py # 路由分发 + VENDOR_METHODS │ │ ├── config.py # 运行时配置 │ │ ├── akshare_data.py # 🆕 akshare 行情+财务适配 │ │ ├── akshare_news.py # 🆕 akshare 新闻适配 │ │ ├── yfinance_news.py # yfinance 新闻 │ │ ├── y_finance.py # yfinance 行情 │ │ └── alpha_vantage*.py # Alpha Vantage 适配 │ ├── graph/ # LangGraph 编排 │ │ ├── trading_graph.py # 主图定义 │ │ └── setup.py # 图工厂 │ └── default_config.py # 默认配置(已改为 akshare) ├── docs/ # 文档 │ ├── architecture-and-modifications.md # 🆕 本文档 │ └── ... ├── web_server.py # 🆕 FastAPI Web 服务 ├── web.html # 🆕 前端面板 └── pyproject.toml # 依赖管理 ``` --- ## 九、关键代码路径 | 功能 | 起点 | 链路 | |------|------|------| | 用户提交分析 | `web_server.py:94 POST /api/analyze` | → `run_analysis_task` → `TradingAgentsGraph.propagate()` | | 获取行情数据 | `core_stock_tools.py:get_stock_data` | → `route_to_vendor("get_stock_data", ...)` → `akshare_data.get_stock_data()` | | 获取技术指标 | `technical_indicators_tools.py:get_indicators` | → `route_to_vendor` → `akshare_data.get_indicators()` | | 获取财务数据 | `fundamental_data_tools.py:get_fundamentals` | → `route_to_vendor` → `akshare_data.get_fundamentals()` | | 获取新闻 | `news_data_tools.py:get_news` | → `route_to_vendor` → `akshare_news.get_news()` | | 数据源切换 | `interface.py:route_to_vendor` | 按 config → fallback 链尝试 |