# TradingAgents 股票分析工作流程详解 > **文档时间**: 2026-05-05 > **相关文档**: [技术架构分析](./architecture-and-modifications.md) > **配套图表**: [流程图](workflow-pipeline.html) | [架构图](workflow-architecture.html) --- ## 一、一次分析的完整生命周期 当用户在 Web UI 输入 `600362` 并点击"分析",系统会经历以下完整流程: ``` 用户点击 [分析] → 后台异步任务 → 约 3-8 分钟后 → 输出交易决策 ``` 整个流程由 **LangGraph StateGraph** 驱动,状态在 15+ 个节点间流转。下面按执行顺序逐步拆解。 --- ## 二、流程图 ![流程图](workflow-pipeline.html) > 详细架构图: [workflow-architecture.html](workflow-architecture.html) --- ## 三、分阶段详解 ### 阶段 1:请求接收与任务创建 **入口**: `web_server.py` → `POST /api/analyze` ``` 用户输入: { ticker: "600362", date: "2026-04-30", analysts: [...], max_debate_rounds: 1 } ``` 1. 生成唯一的 `task_id`(格式: `600362_20260505191807`) 2. 创建任务记录写入 `tasks_store`(内存字典) 3. 通过 FastAPI `BackgroundTasks` 异步启动 `run_analysis_task()` 4. 立即返回 `{"task_id": "...", "status": "pending"}` 5. 前端每 3 秒轮询 `GET /api/task/{task_id}` 获取进度 ### 阶段 2:Graph 初始化 **文件**: `tradingagents/graph/trading_graph.py` → `TradingAgentsGraph.propagate()` ```python # 1. 读取配置 config = get_config() # 默认 vendor: akshare llm_name = config["llm_provider"] # DeepSeek # 2. 初始化 LangGraph StateGraph workflow = StateGraph(AgentState) # 3. 按用户选择的分析师类型动态添加节点 # 可选: market, sentiment, news, fundamentals # 默认: market + news ``` `AgentState` 中关键字段: | 字段 | 初始值 | 说明 | |------|--------|------| | `messages` | `[]` | 全流程消息日志 | | `ticker` | `"600362"` | 股票代码 | | `trade_date` | `"2026-04-30"` | 分析日期 | | `company_name` | `""` | 公司名称(初始为空) | | `market_report` | `""` | 市场分析报告 | | `sentiment_report` | `""` | 情绪分析报告 | | `news_report` | `""` | 新闻分析报告 | | `fundamentals_report` | `""` | 基本面报告 | | `investment_plan` | `""` | 投资决策草案 | | `final_decision` | `""` | 最终交易信号 | | `current_debate_round` | `0` | 当前辩论轮次 | ### 阶段 3:并行分析师采集(核心环节) 这是整个流程中**数据量最大、耗时最长**的阶段。四个分析师节点通过 LangGraph 的并行边**同时启动**。 #### 3.1 市场分析师 (Market Analyst) **文件**: `tradingagents/agents/analysts/market_analyst.py` **角色定位**: 技术面专家 **System Prompt 核心**: > "You are a trading assistant agent with extensive market insight. Your task is to analyze market data using technical indicators." **执行的工具调用**: ``` 1. get_stock_data("600362", "2026-03-30", "2026-04-30") → 路线: route_to_vendor → akshare_data.get_stock_data() → 输出: 最近一个月 OHLCV 数据(~22条日K线) 2. get_indicators("600362", "rsi", "2026-04-30", 30) 3. get_indicators("600362", "macd", "2026-04-30", 30) 4. get_indicators("600362", "bollinger_bands", "2026-04-30", 30) 5. get_indicators("600362", "volume", "2026-04-30", 30) ... (最多调用 19 项技术指标中的 5-8 项关键指标) ``` **指标清单**(akshare_data.py 支持的全部 19 项): | 类别 | 指标 | |------|------| | 趋势类 | sma_20, ema_20, macd, adx | | 动量类 | rsi, stochastic_oscillator, williams_r, cci | | 波动类 | bollinger_bands, atr, standard_deviation | | 成交量类 | obv, volume, volume_sma | | 其他 | mfi, ppo, roc, triple_ema, vortex | **输出**: 一份 800-1500 字的 Markdown 技术分析报告,含关键指标解读和趋势判断。 #### 3.2 社交媒体分析师 (Social Media Analyst) **文件**: `tradingagents/agents/analysts/social_media_analyst.py` **角色定位**: 市场情绪雷达 **执行的工具调用**: ``` 1. get_news("600362", "2026-04-01", "2026-05-04") → 路线: route_to_vendor → akshare_news.get_news() → 数据源: 东方财富个股新闻 → 输出: 最近 15 天内与该股相关的新闻(最多50条) ``` **输出**: 一份舆情分析报告,提炼市场情绪信号(恐慌/贪婪/中性)。 #### 3.3 新闻分析师 (News Analyst) **文件**: `tradingagents/agents/analysts/news_analyst.py` **角色定位**: 宏观政策雷达 **System Prompt 核心**: > "You are a news analyst agent with expertise in global macro trends. Your task is to analyze news related to the company and the broader economic landscape." **执行的工具调用**: ``` 1. get_news("600362", "2026-04-01", "2026-05-04") → 与社媒分析师相同的数据源,但解读角度不同 2. get_global_news("2026-05-04", look_back_days=7, limit=20) → 路线: route_to_vendor → akshare_news.get_global_news() → 数据源: CCTV 新闻联播文字稿 → 输出: 宏观政策、经济事件摘要 ``` **输出**: 一份包含个股新闻分析和宏观经济背景的综合报告。 #### 3.4 基本面分析师 (Fundamentals Analyst) **文件**: `tradingagents/agents/analysts/fundamentals_analyst.py` **角色定位**: 价值投资者 **System Prompt 核心**: > "You are a fundamental analysis expert with deep knowledge of valuation methodologies. Your task is to analyze company fundamentals and financial health." **执行的工具调用** (共 4 次): ``` 1. get_fundamentals("600362") → 数据: 公司概况、市盈率、市净率、总市值、流通股本等 2. get_balance_sheet("600362") → 数据: 最新一期资产负债表(总资产/负债/权益) 3. get_cashflow("600362") → 数据: 最新一期现金流量表(经营/投资/筹资现金流) 4. get_income_statement("600362") → 数据: 最新一期利润表(营收/成本/净利润/每股收益) ``` **输出**: 一份包含估值分析、财务健康度评分、盈利能力判断的基本面报告。 ### 阶段 4:研究经理汇总 **文件**: `tradingagents/graph/trading_graph.py` → `create_research_manager_node()` ``` 输入: 4份分析师报告(并行采集完成后的汇总) 处理: 研究经理 LLM 阅读所有报告,提取关键矛盾点 输出: 投资者简报 (investment briefing) ``` 研究经理不产生独立决策,而是**整理和总结**分析师团队输出的核心信息,为下一阶段的辩论做准备。 ### 阶段 5:多空辩论 (Debate) **文件**: `tradingagents/graph/trading_graph.py` → `create_debate_node()` + `debate_bull_researcher()` + `debate_bear_researcher()` 这是框架的**核心创新**:用 LLM 模拟真实投资决策中的多空辩论。 #### 辩论角色 | 角色 | 文件 | 立场 | 职责 | |------|------|------|------| | **Bull Researcher** | `agents/researchers/bull_researcher.py` | 多头 | 找出所有支撑买入的论据 | | **Bear Researcher** | `agents/researchers/bear_researcher.py` | 空头 | 找出所有支撑卖出的论据 | | **Debate Judge** | `agents/managers/research_manager.py` | 裁判 | 评估双方论据,判断胜负 | #### 辩论流程 ``` 轮次 1: Bull → 提出 3-5 个多方论点(基于分析师报告) Bear → 反驳多方论点 + 提出 3-5 个空方论点 Judge → 评估双方论据质量,判断本轮是否分出胜负 轮次 2 (如果裁判认为需要继续): Bull → 回应空方反驳 + 补充新论点 Bear → 回应多方回应 + 强化空方论点 Judge → 再次评估 ... 直到 max_debate_rounds 耗尽或裁判判定胜负 ``` **关键**: `max_debate_rounds` 在配置中可调,默认 **1 轮**。每增加一轮,LLM 调用次数翻倍,总耗时显著增长。 #### 辩论输出 - 辩论完整记录(谁说了什么) - 裁判的最终评估(多方胜/空方胜/平局) ### 阶段 6:交易员决策 **文件**: `tradingagents/agents/trader/trader_agent.py` **System Prompt 核心**: > "You are a professional trader agent. Based on the analysts' reports and debate results, make a trading decision." **输入**: - 4 份分析师报告 - 辩论摘要(裁判评估) **处理**: 交易员 LLM 综合所有证据,形成投资决策草案 **输出**: `investment_plan` — 包含: - 决策方向(Buy/Sell/Hold) - 置信度评估 - 关键依据 - 风险提示 ### 阶段 7:三级风控评审 **文件**: `tradingagents/graph/trading_graph.py` → `create_risk_analysis_node()` + 三个风控 agent 这是项目的**第二道安全阀**:交易员的决策必须通过风控审查。 | 风控角色 | 文件 | 风格 | 关注点 | |----------|------|------|--------| | **Aggressive** | `agents/risk_mgmt/aggressive_debator.py` | 激进 | 机会最大化,风险容忍度较高 | | **Conservative** | `agents/risk_mgmt/conservative_debator.py` | 保守 | 本金安全第一,宁可错过不做错 | | **Neutral** | `agents/risk_mgmt/neutral_debator.py` | 中立 | 平衡收益与风险 | #### 流程 ``` 交易员输出投资草案 │ ├→ Aggressive 评估 → "风险可接受,建议执行" ├→ Conservative 评估 → "风险过高,建议降低仓位" └→ Neutral 评估 → "风险适中,可执行但需设置止损" │ └→ Risk Judge 汇总三个评估 → 最终裁定 ``` **Risk Judge** 文件: `tradingagents/agents/managers/risk_manager.py` — 综合三方意见,给出最终风控建议。 **注意**: 风控评审是一个循环 — 如果 `final_decision` 为空(未达成一致),图会回到交易员节点重新决策。 ### 阶段 8:最终输出 经过以上所有阶段后,系统输出: ```python { "ticker": "600362", "date": "2026-04-30", "company_name": "江西铜业", "market_report": "...", # 技术分析报告 "sentiment_report": "...", # 情绪分析报告 "news_report": "...", # 新闻分析报告 "fundamentals_report": "...", # 基本面报告 "investment_plan": "...", # 交易决策草案 "debate_log": "...", # 辩论记录 "final_decision": "BUY", # 最终交易信号: BUY / SELL / HOLD "risk_assessment": "...", # 风控评估 "messages": [...] # 全流程消息日志 } ``` --- ## 四、完整节点流转图(Graph 内部) ``` ┌──────────────┐ │ START │ └──────┬───────┘ │ ┌────────────────┼────────────────┐ ▼ ▼ ▼ ▼ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │mkt_start │ │snt_start │ │nws_start │ │fnd_start │ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ ▼ ▼ ▼ ▼ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │mkt_analyst │ │snt_analyst │ │nws_analyst │ │fnd_analyst │ │(LLM分析) │ │(LLM分析) │ │(LLM分析) │ │(LLM分析) │ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ ▼ ▼ ▼ ▼ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │mkt_tools │ │snt_tools │ │nws_tools │ │fnd_tools │ │(调用数据) │ │(调用数据) │ │(调用数据) │ │(调用数据) │ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ ▼ ▼ ▼ ▼ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │mkt_cond │ │snt_cond │ │nws_cond │ │fnd_cond │ │(if 需继续) │ │(if 需继续) │ │(if 需继续) │ │(if 需继续) │ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ │ │ │ │ └────────────────┼────────────────┼────────────────┘ ▼ ┌──────────────┐ │ invest_judge │ (研究经理汇总) └──────┬───────┘ │ ┌───────────┴───────────┐ ▼ ▼ ┌────────────┐ ┌────────────┐ │bull_resrch │ │bear_resrch │ │(多方) │ │(空方) │ └─────┬──────┘ └─────┬──────┘ │ │ └──────────┬───────────┘ ▼ ┌──────────────┐ │ invest_judge │ (辩论裁判评估) └──────┬───────┘ │ (if 辩论未结束 → 回到 bull/bear) ▼ ┌──────────────┐ │ trader │ (交易员决策) └──────┬───────┘ ▼ ┌──────────────┐ │trader_tools │ (可能需要查询数据) └──────┬───────┘ │ ┌──────────────┼──────────────┐ ▼ ▼ ▼ ┌──────────┐ ┌──────────────┐ ┌──────────┐ │aggressive│ │conservative │ │ neutral │ │ 风控 │ │ 风控 │ │ 风控 │ └────┬─────┘ └──────┬───────┘ └────┬─────┘ │ │ │ └────────────────┼────────────────┘ ▼ ┌──────────────┐ │ risk_judge │ (风控终审) └──────┬───────┘ │ (if 未通过 → 回到 trader) ▼ ┌──────────────┐ │ final │ (输出结果) └──────────────┘ ``` --- ## 五、关键数据流路径 以"600362 市场分析"为例,追踪一次数据调用的完整路径: ``` 1. Market Analyst LLM 决定调用 get_stock_data("600362", ...) 2. LangChain @tool 装饰器触发 → agents/utils/core_stock_tools.py:28 3. 内部调用 route_to_vendor("get_stock_data", "600362", ...) → dataflows/interface.py:140 4. route_to_vendor 读取 config["data_vendors"]["core_stock_data"] → {"primary": "akshare"} 5. 按 priority 顺序尝试: a) akshare → akshare_data.get_stock_data("600362", ...) - 检测 "600362" 是6位数字 → 路由到 A 股接口 - 调用 ak.stock_zh_a_hist(symbol="600362", period="daily", ...) - 格式化 DataFrame → Markdown 表格字符串 - 成功!返回数据 ✓ 6. route_to_vendor 获得 Markdown 字符串 → 返回给 tool 7. tool 将数据嵌入 LLM context 8. Market Analyst LLM 收到数据,生成技术分析报告 9. 报告写入 state.market_report ``` 如果第5步 akshare 失败,route_to_vendor 会自动尝试 yfinance,再失败尝试 alpha_vantage,**完全透明,LLM 无感知**。 --- ## 六、耗时分布估算 基于 DeepSeek 推理速度的单次分析耗时(仅供参考): | 阶段 | LLM 调用次数 | 数据API调用 | 耗时估算 | |------|-------------|------------|----------| | 并行分析师(4个) | 8-16次 (LLM + tool) | 8-15次 | 90-180秒 | | 研究经理汇总 | 1次 | 0 | 10-20秒 | | 辩论(1轮) | 3次 (Bull/Bear/Judge) | 0 | 30-60秒 | | 交易员决策 | 1次 | 0-2次 | 15-30秒 | | 三级风控 | 4次 (3风控+1裁判) | 0 | 40-80秒 | | **合计** | **17-25次** | **8-17次** | **3-6分钟** | > **注意**: 如果 `max_debate_rounds` 设为 2 或更多,辩论耗时翻倍。数据源的 Rate Limit 状况也会影响实际耗时。 --- ## 七、与原始实现的关键差异 本项目基于开源 TradingAgents 框架,做了以下适应性修改(详见[架构文档](./architecture-and-modifications.md)): | 差异点 | 原始实现 | 当前实现 | |--------|---------|---------| | 数据源 | yfinance 为主 | **akshare 为主**,yfinance 降级为 fallback | | A股行情 | 不稳定,频繁 Rate Limit | ✅ 稳定,不限流 | | A股财务数据 | ❌ | ✅ 三大报表完整 | | 新闻源 | 英文(yfinance news) | ✅ 中文(东方财富 + CCTV) | | 港股支持 | 部分 | ✅ 完整 | | Web UI | ❌ 无 | ✅ FastAPI + 前端面板 | | 部署 | 脚本手动运行 | ✅ systemd 服务自动管理 | --- ## 八、配置调优建议 通过修改 `default_config.py` 或运行时 `set_config()` 可调整的参数: | 参数 | 默认值 | 建议范围 | 说明 | |------|--------|---------|------| | `max_debate_rounds` | 1 | 1-3 | 辩论轮次,越多越深度但越慢 | | `data_vendors.*.primary` | `"akshare"` | `"akshare"` / `"yfinance"` | 主数据源 | | `llm_provider` | `"deepseek"` | — | LLM 后端 | | `quick_thinking` | `False` | `True` / `False` | True 使用 fast model,速度更快精度略低 | --- ## 九、监控与调试 ### 查看服务日志 ```bash journalctl -u tradingagents.service -f ``` ### 查看分析任务状态 ```bash curl http://129.211.173.87:8500/api/task/{task_id} ``` ### 重启服务 ```bash sudo systemctl restart tradingagents.service ```