19 KiB
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,存在以下问题:
- 国内访问不稳定: yfinance 对非美股数据支持有限,频繁触发 Rate Limit
- A 股数据质量差: yfinance 的 A 股 OHLCV 数据常常缺失或不准确
- 新闻源偏西式: yfinance 的新闻来源主要是英文媒体,对 A 股分析不友好
- 无国内数据源: 缺少针对中国市场的本地化数据适配
解决方案: 集成 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 市场检测
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 可正常解析。
| 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 之前设置环境变量解决:
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 实现:
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 路径:
akshare→ 抛出AlphaVantageRateLimitError(触发 fallback)yfinance→ 获取数据(成功)✓
5.5.3 数据源分类优化
将 akshare 明确归入 all_available_vendors,确保它在所有 data_vendors 分类组中可用:
all_available_vendors = ["akshare", "yfinance", "alpha_vantage"]
5.6 default_config.py 修改
# 修改前
"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 异步任务机制
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 链尝试 |