TradingAgents 是一个基于 LangGraph 构建的多智能体交易研究框架,它通过 Market Analyst、News Analyst、Social Analyst、Fundamentals Analyst、Bull/Bear Researcher、Trader、Risk Analysts 和 Portfolio Manager 等角色,模拟真实投研团队从数据收集、观点辩论、交易计划到风险审查和最终决策的完整流程。

原始 TradingAgents 主要面向美股市场,数据来源以 yfinance、alpha_vantage 等为主。为了让这套多智能体框架能够用于 A 股投研,我在尽量保留原有 Agent 图、状态流转、工具抽象和决策流程的基础上,新增了 A 股数据 vendor:`tradingagents/dataflows/a_share.py`,并通过 AkShare、缓存 fallback、基本面多接口字段级合并、中文输出和 CLI 市场模式适配,使其能够分析如 `600519.SH`、`000001.SZ`、`300750.SZ` 这样的 A 股代码。

本文将围绕 `examples/run_ashare_full.py` 展开,完整梳理当运行:

python examples/run_ashare_full.py

时,系统从入口配置、TradingAgentsGraph 初始化、Agent 图执行、工具路由、A 股数据获取、状态流转,到最终输出 HOLD 决策的全过程。

文章不会停留在单个函数的细枝末节,而是从项目整体架构出发,重点解释以下几个问题:

  • run_ashare_full.py 如何启动完整 A 股分析师团队?

  • A 股版本与原始 TradingAgents 相比保留了什么、改动了什么?

  • a_share.py 如何通过 AkShare、缓存和 fallback 提供 A 股行情、指标、新闻、情绪和基本面?

  • route_to_vendor() 如何把标准工具调用路由到 A 股数据实现?

  • 多个 Agent 如何通过 AgentState 协作生成市场报告、新闻报告、情绪报告、基本面报告、交易计划和最终决策?

  • 为什么最终控制台只打印 Hold,而完整流程中其实包含了大量中间报告和多智能体推理过程?

通过这篇文章,你将能够建立对 TradingAgents A 股版本的完整认知:它不是简单写一个股票分析脚本,而是在原始 TradingAgents 多智能体投研框架之上,接入了一套面向 A 股市场的数据适配层和运行入口,从而让原本偏美股的数据驱动流程具备分析 A 股标的的能力。

1. 整体流程心智图

运行:python examples/run_ashare_full.py

run_ashare_full.py:

from copy import deepcopy

from dotenv import load_dotenv

from tradingagents.default_config import DEFAULT_CONFIG
from tradingagents.graph.trading_graph import TradingAgentsGraph


load_dotenv()

config = deepcopy(DEFAULT_CONFIG)
config["market"] = "A-share"
config["llm_provider"] = "glm"
config["deep_think_llm"] = "glm-5.1"
config["quick_think_llm"] = "glm-4.7"
config["output_language"] = "Chinese"
config["data_vendors"] = {
    "core_stock_apis": "a_share",
    "technical_indicators": "a_share",
    "fundamental_data": "a_share",
    "news_data": "a_share",
}
config["a_share_data"] = {
    "price_source": "akshare",
    "news_source": "akshare",
    "fundamental_source": "akshare_or_unavailable",
    "social_source": "market_derived_or_unavailable",
    "cache_dir": "data/cache/a_share",
    "use_cache": True,
    "adjust": "qfq",
    "allow_mock": False,
    "retry_times": 2,
    "retry_sleep_seconds": 2,
    "nearby_cache_max_days": 30,
}
config["max_debate_rounds"] = 1
config["max_risk_discuss_rounds"] = 1

ta = TradingAgentsGraph(
    selected_analysts=["market", "news", "social", "fundamentals"],
    debug=True,
    config=config,
)

_, decision = ta.propagate("600519.SH", "2024-05-10")
print(decision)

第 1 层:入口脚本配置运行环境

run_ashare_full.py 先复制原版默认配置 DEFAULT_CONFIG,然后把它改成 A 股分析模式

第 2 层:启动 TradingAgentsGraph

脚本创建,仍然使用原版 TradingAgents 的 TradingAgentsGraph

TradingAgentsGraph(
    selected_analysts=["market", "news", "social", "fundamentals"],
    debug=True,
    config=config,
)

TradingAgents 官方说明里,原版框架是一个模拟真实交易公司的多智能体系统:有基本面、情绪、新闻、技术分析师,有多空研究员,有交易员,有风险管理团队,还有组合经理;这些角色共同讨论并形成交易决策。官方 README 也说明它基于 LangGraph 构建,并通过 TradingAgentsGraph().propagate() 返回交易决策。

所以A股版本在架构上仍然是:

TradingAgentsGraph
  ├─ Analyst Team
  ├─ Bull / Bear Researcher
  ├─ Trader
  ├─ Risk Management Team
  └─ Portfolio Manager

第 3 层:四个分析师先各自生成报告

脚本选择了四个 analyst:

market、news、social、fundamentals

所以完整分析大致按这个方向展开:

Market Analyst
  读取 A 股行情和技术指标
  形成市场/技术报告

News Analyst
  读取个股公告、财经新闻、大盘背景
  形成新闻报告

Social Analyst
  读取情绪数据
  在你的版本中主要基于真实行情衍生指标生成情绪摘要
  形成情绪报告

Fundamentals Analyst
  读取 A 股基本面、财务摘要、个股资料、财报字段
  形成基本面报告

第 4 层:数据工具被路由到 A 股 vendor

这层是A股版本最关键的变化。

原版 TradingAgents 中,分析师并不是直接写死访问某个数据源,而是通过工具函数取数据。A股版本把工具背后的数据 vendor 切成了 a_share

所以整体调用关系可以这样理解:

Agent 提问:
“我要看 600519.SH 的行情/新闻/基本面”

↓ 调用原版工具名

get_stock_data
get_indicators
get_news
get_global_news
get_fundamentals

↓ 根据 config["data_vendors"] 路由

a_share vendor

↓ 进入新增的TradingAgents\TradingAgents\tradingagents\dataflows\a_share.py

AkShare 在线接口
本地缓存
多源 fallback
字段级合并
中文格式化报告

这就是“最小改动”的关键:Agent 图不动,工具名尽量不动,只替换数据 vendor 的实现。

第 5 层:研究、交易、风控、组合经理给出最终决策

四个分析师报告出来之后,后半段仍然是原版 TradingAgents 的多角色决策流程:

分析师报告

Bull Researcher:多头研究员,寻找买入/看多理由

Bear Researcher:空头研究员,寻找风险/看空理由

Research Manager:研究经理,总结多空争论

Trader:交易员,把研究观点转成交易计划

Risk Analysts:风险团队,从激进/中性/保守角度评估

Portfolio Manager:组合经理,批准或拒绝交易方案

最终 decision

官方 TradingAgents README 也说明,Researcher Team 由 bullish 和 bearish researchers 组成,会通过结构化辩论权衡收益和风险;Trader 会综合分析师和研究员报告形成交易决策;风险团队评估波动、流动性等风险因素,并把评估交给 Portfolio Manager 做最终决定。

脚本最后只打印:

print(decision)

也就是最终交易决策,而不是所有中间状态。

最重要的理解:这是“数据层改造”,不是“Agent 层重写”

现在这套系统可以用一个分层图来理解:

┌────────────────────────────────────────────┐
│ run_ashare_full.py                         │
│ 固定 A 股标的、日期、LLM、vendor 配置       │
└────────────────────────────────────────────┘
                    ↓
┌────────────────────────────────────────────┐
│ TradingAgentsGraph                         │
│ 原版多智能体图:分析师、研究员、交易员、风控 │
└────────────────────────────────────────────┘
                    ↓
┌────────────────────────────────────────────┐
│ Agent Tools                                │
│ get_stock_data / get_news / get_fundamentals│
└────────────────────────────────────────────┘
                    ↓
┌────────────────────────────────────────────┐
│ a_share.py                                 │
│ A 股 vendor:AkShare、缓存、fallback、字段合并│
└────────────────────────────────────────────┘
                    ↓
┌────────────────────────────────────────────┐
│ 中文投研报告 + 多空辩论 + 风险评估 + 决策   │
└────────────────────────────────────────────┘

所以后面我们逐步看代码时,应该按这个顺序看:

1. run_ashare_full.py 入口配置
2. TradingAgentsGraph 如何接收 config
3. selected_analysts 如何决定图执行顺序
4. 工具函数如何根据 data_vendors 路由
5. a_share.py 如何提供行情、指标、新闻、情绪、基本面
6. 报告如何进入 Bull/Bear、Trader、Risk、Portfolio Manager
7. decision 如何最终打印

2.运行流程总览

运行:python examples/run_ashare_full.py

实际流程是:

1. 读取 .env
   ↓
2. 复制 DEFAULT_CONFIG
   ↓
3. 把配置改成 A-share / GLM / 中文 / a_share 数据 vendor
   ↓
4. 创建 TradingAgentsGraph
   ↓
5. TradingAgentsGraph 初始化:
      - 写入全局 dataflow config
      - 创建 LLM client
      - 创建 ToolNode
      - 创建 ConditionalLogic
      - 创建 GraphSetup
      - 编译 LangGraph 工作流
   ↓
6. 调用 ta.propagate("600519.SH", "2024-05-10")
   ↓
7. 创建初始 AgentState
   ↓
8. 按 selected_analysts 顺序执行:
      Market Analyst
      News Analyst
      Social Analyst
      Fundamentals Analyst
   ↓
9. 每个 Analyst 如需数据,会调用工具:
      get_stock_data
      get_indicators
      get_news
      get_global_news
      get_social_sentiment
      get_fundamentals
   ↓
10. 工具函数进入 route_to_vendor()
   ↓
11. 根据 config["data_vendors"] 路由到 a_share.py
   ↓
12. a_share.py 调 AkShare / 读缓存 / fallback / 格式化文本
   ↓
13. Analyst 生成四份报告:
      market_report
      news_report
      sentiment_report
      fundamentals_report
   ↓
14. Bull Researcher / Bear Researcher 辩论
   ↓
15. Research Manager 形成 investment_plan
   ↓
16. Trader 形成 trader_investment_plan
   ↓
17. Risk Analysts 讨论风险
   ↓
18. Portfolio Manager 输出 final_trade_decision
   ↓
19. SignalProcessor 从 final_trade_decision 中提取评级
   ↓
20. print(decision)

输出的decision可以验证这个流程:运行时先调用 get_stock_data,然后多次调用 get_indicators,之后进入新闻、情绪、基本面工具,最终输出 Hold。其中行情工具实际返回了 DATA_SOURCE: akshare_eastmoney,技术指标多次返回 DATA_SOURCE: akshare_sina,基本面返回 DATA_SOURCE: akshare_multi_interface

decision:

(tradingagents) PS D:\Projects\TradingAgents\TradingAgents> python examples/run_ashare_full.py
D:\Users\Administrator\anaconda3\envs\tradingagents\Lib\site-packages\langgraph\checkpoint\serde\encrypted.py:5: LangChainPendingDeprecationWarning: The default value of `allowed_objects` will change in a future version. Pass an explicit value (e.g., allowed_objects='messages' or allowed_objects='core') to suppress this warning.
  from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer
================================ Human Message =================================

600519.SH
================================== Ai Message ==================================


我来为您分析600519.SH这只A股。首先获取股票数据,然后计算相关技术指标。
Tool Calls:
  get_stock_data (call_-7637635923231894780)
 Call ID: call_-7637635923231894780
  Args:
    symbol: 600519.SH
    start_date: 2024-02-10
    end_date: 2024-05-10
================================= Tool Message =================================
Name: get_stock_data

DATA_STATUS: OK
DATA_SOURCE: akshare_eastmoney
SYMBOL: 600519.SH
REQUESTED_RANGE: 2024-02-10 to 2024-05-10
ACTUAL_RANGE: 2024-02-19 to 2024-05-10
CAN_USE_FOR_DECISION: true
数据来自 AkShare 东方财富接口。
区间起始收盘价: 1589.11
区间结束收盘价: 1632.66
区间涨跌幅: 2.74%
平均成交量: 2.75万
平均换手率: 0.22%
最大单日涨跌幅: 3.45%
最近 10 行行情:
| Date | Open | High | Low | Close | Volume | Amount | Amplitude | PctChange | Change | Turnover |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 2024-04-24 | 1590.66 | 1593.59 | 1577.01 | 1587.28 | 17086.00 | 2893555635.00 | 1.05 | 0.08 | 1.32 | 0.14 |
| 2024-04-25 | 1584.01 | 1589.28 | 1575.93 | 1586.72 | 14476.00 | 2447183879.00 | 0.84 | -0.04 | -0.56 | 0.12 |
| 2024-04-26 | 1587.68 | 1607.68 | 1587.66 | 1603.11 | 30996.00 | 5290248521.00 | 1.26 | 1.03 | 16.39 | 0.25 |
| 2024-04-29 | 1590.63 | 1621.68 | 1587.50 | 1597.68 | 41332.00 | 7072096590.00 | 2.13 | -0.34 | -5.43 | 0.33 |
| 2024-04-30 | 1598.69 | 1623.56 | 1598.68 | 1598.68 | 30760.00 | 5273902374.00 | 1.56 | 0.06 | 1.00 | 0.24 |
| 2024-05-06 | 1627.65 | 1658.68 | 1620.68 | 1653.88 | 59909.00 | 10504351712.00 | 2.38 | 3.45 | 55.20 | 0.48 |
| 2024-05-07 | 1659.47 | 1671.48 | 1650.36 | 1663.68 | 24925.00 | 4413196426.00 | 1.28 | 0.59 | 9.80 | 0.20 |
| 2024-05-08 | 1663.37 | 1663.65 | 1649.35 | 1657.65 | 14769.00 | 2603293863.00 | 0.86 | -0.36 | -6.03 | 0.12 |
| 2024-05-09 | 1651.68 | 1658.66 | 1643.68 | 1649.68 | 22387.00 | 3929804849.00 | 0.90 | -0.48 | -7.97 | 0.18 |
| 2024-05-10 | 1654.78 | 1661.56 | 1627.67 | 1632.66 | 26207.00 | 4571398242.00 | 2.05 | -1.03 | -17.02 | 0.21 |
================================== Ai Message ==================================
Tool Calls:
  get_indicators (call_-7637672756871428941)
 Call ID: call_-7637672756871428941
  Args:
    symbol: 600519.SH
    indicator: close_50_sma
    curr_date: 2024-05-10
    look_back_days: 50
================================= Tool Message =================================
Name: get_indicators

DATA_STATUS: OK
DATA_SOURCE: akshare_sina
SYMBOL: 600519.SH
REQUESTED_RANGE: 2024-01-31 to 2024-05-10
ACTUAL_RANGE: 2024-01-31 to 2024-05-10
CAN_USE_FOR_DECISION: true
数据来自 AkShare 新浪接口。
指标名称: close_50_sma -> MA20
最新指标值: 1577.6410
| Date | Close | MA20 |
| --- | --- | --- |
| 2024-04-24 | 1575.4600 | 1563.3865 |
| 2024-04-25 | 1574.9400 | 1562.6310 |
| 2024-04-26 | 1590.1800 | 1563.0230 |
| 2024-04-29 | 1585.1300 | 1563.1325 |
| 2024-04-30 | 1586.0600 | 1563.2300 |
| 2024-05-06 | 1637.4100 | 1565.0380 |
| 2024-05-07 | 1646.5300 | 1567.6435 |
| 2024-05-08 | 1640.9200 | 1569.9160 |
| 2024-05-09 | 1633.5000 | 1574.0710 |
| 2024-05-10 | 1617.6700 | 1577.6410 |
================================== Ai Message ==================================
Tool Calls:
  get_indicators (call_-7637651178955732013)
 Call ID: call_-7637651178955732013
  Args:
    symbol: 600519.SH
    indicator: close_200_sma
    curr_date: 2024-05-10
    look_back_days: 200
================================= Tool Message =================================
Name: get_indicators

DATA_STATUS: OK
DATA_SOURCE: akshare_sina
SYMBOL: 600519.SH
REQUESTED_RANGE: 2023-04-06 to 2024-05-10
ACTUAL_RANGE: 2023-04-06 to 2024-05-10
CAN_USE_FOR_DECISION: true
数据来自 AkShare 新浪接口。
指标名称: close_200_sma -> MA60
最新指标值: 1577.1782
| Date | Close | MA60 |
| --- | --- | --- |
| 2024-04-24 | 1575.4600 | 1562.2887 |
| 2024-04-25 | 1574.9400 | 1563.0800 |
| 2024-04-26 | 1590.1800 | 1564.4820 |
| 2024-04-29 | 1585.1300 | 1565.6913 |
| 2024-04-30 | 1586.0600 | 1566.7302 |
| 2024-05-06 | 1637.4100 | 1568.6353 |
| 2024-05-07 | 1646.5300 | 1570.4958 |
| 2024-05-08 | 1640.9200 | 1572.8365 |
| 2024-05-09 | 1633.5000 | 1575.1790 |
| 2024-05-10 | 1617.6700 | 1577.1782 |
================================== Ai Message ==================================
Tool Calls:
  get_indicators (call_-7637660559164306286)
 Call ID: call_-7637660559164306286
  Args:
    symbol: 600519.SH
    indicator: close_10_ema
    curr_date: 2024-05-10
    look_back_days: 30
================================= Tool Message =================================
Name: get_indicators

DATA_STATUS: OK
DATA_SOURCE: akshare_sina
SYMBOL: 600519.SH
REQUESTED_RANGE: 2024-02-10 to 2024-05-10
ACTUAL_RANGE: 2024-02-19 to 2024-05-10
CAN_USE_FOR_DECISION: true
数据来自 AkShare 新浪接口。
指标名称: close_10_ema -> MA10
最新指标值: 1608.7800
数据长度不足,部分长周期指标可能为空。
| Date | Close | MA10 |
| --- | --- | --- |
| 2024-04-24 | 1575.4600 | 1550.7460 |
| 2024-04-25 | 1574.9400 | 1554.9360 |
| 2024-04-26 | 1590.1800 | 1561.9500 |
| 2024-04-29 | 1585.1300 | 1564.8360 |
| 2024-04-30 | 1586.0600 | 1568.0920 |
| 2024-05-06 | 1637.4100 | 1576.7620 |
| 2024-05-07 | 1646.5300 | 1585.9920 |
| 2024-05-08 | 1640.9200 | 1596.9070 |
| 2024-05-09 | 1633.5000 | 1604.4360 |
| 2024-05-10 | 1617.6700 | 1608.7800 |
================================== Ai Message ==================================
Tool Calls:
  get_indicators (call_-7637674577937560569)
 Call ID: call_-7637674577937560569
  Args:
    symbol: 600519.SH
    indicator: macd
    curr_date: 2024-05-10
    look_back_days: 30
================================= Tool Message =================================
Name: get_indicators

DATA_STATUS: OK
DATA_SOURCE: akshare_sina
SYMBOL: 600519.SH
REQUESTED_RANGE: 2024-02-10 to 2024-05-10
ACTUAL_RANGE: 2024-02-19 to 2024-05-10
CAN_USE_FOR_DECISION: true
数据来自 AkShare 新浪接口。
指标名称: macd -> MACD
最新指标值: 16.2017
数据长度不足,部分长周期指标可能为空。
| Date | Close | MACD |
| --- | --- | --- |
| 2024-04-24 | 1575.4600 | -5.1591 |
| 2024-04-25 | 1574.9400 | -3.5281 |
| 2024-04-26 | 1590.1800 | -0.9942 |
| 2024-04-29 | 1585.1300 | 0.5995 |
| 2024-04-30 | 1586.0600 | 1.9155 |
| 2024-05-06 | 1637.4100 | 7.0210 |
| 2024-05-07 | 1646.5300 | 11.6685 |
| 2024-05-08 | 1640.9200 | 14.7293 |
| 2024-05-09 | 1633.5000 | 16.3675 |
| 2024-05-10 | 1617.6700 | 16.2017 |
================================== Ai Message ==================================
Tool Calls:
  get_indicators (call_-7637667156234073649)
 Call ID: call_-7637667156234073649
  Args:
    symbol: 600519.SH
    indicator: rsi
    curr_date: 2024-05-10
    look_back_days: 30
================================= Tool Message =================================
Name: get_indicators

DATA_STATUS: OK
DATA_SOURCE: akshare_sina
SYMBOL: 600519.SH
REQUESTED_RANGE: 2024-02-10 to 2024-05-10
ACTUAL_RANGE: 2024-02-19 to 2024-05-10
CAN_USE_FOR_DECISION: true
数据来自 AkShare 新浪接口。
指标名称: rsi -> RSI_14
最新指标值: 68.5238
数据长度不足,部分长周期指标可能为空。
| Date | Close | RSI_14 |
| --- | --- | --- |
| 2024-04-24 | 1575.4600 | 44.9569 |
| 2024-04-25 | 1574.9400 | 44.5239 |
| 2024-04-26 | 1590.1800 | 62.6190 |
| 2024-04-29 | 1585.1300 | 62.2556 |
| 2024-04-30 | 1586.0600 | 68.1371 |
| 2024-05-06 | 1637.4100 | 76.4161 |
| 2024-05-07 | 1646.5300 | 82.6561 |
| 2024-05-08 | 1640.9200 | 75.9583 |
| 2024-05-09 | 1633.5000 | 73.8521 |
| 2024-05-10 | 1617.6700 | 68.5238 |
================================== Ai Message ==================================
Tool Calls:
  get_indicators (call_-7637663101784941743)
 Call ID: call_-7637663101784941743
  Args:
    symbol: 600519.SH
    indicator: boll
    curr_date: 2024-05-10
    look_back_days: 30
================================= Tool Message =================================
Name: get_indicators

DATA_STATUS: OK
DATA_SOURCE: akshare_sina
SYMBOL: 600519.SH
REQUESTED_RANGE: 2024-02-10 to 2024-05-10
ACTUAL_RANGE: 2024-02-19 to 2024-05-10
CAN_USE_FOR_DECISION: true
数据来自 AkShare 新浪接口。
指标名称: boll -> MA20
最新指标值: 1577.6410
数据长度不足,部分长周期指标可能为空。
| Date | Close | MA20 |
| --- | --- | --- |
| 2024-04-24 | 1575.4600 | 1563.3865 |
| 2024-04-25 | 1574.9400 | 1562.6310 |
| 2024-04-26 | 1590.1800 | 1563.0230 |
| 2024-04-29 | 1585.1300 | 1563.1325 |
| 2024-04-30 | 1586.0600 | 1563.2300 |
| 2024-05-06 | 1637.4100 | 1565.0380 |
| 2024-05-07 | 1646.5300 | 1567.6435 |
| 2024-05-08 | 1640.9200 | 1569.9160 |
| 2024-05-09 | 1633.5000 | 1574.0710 |
| 2024-05-10 | 1617.6700 | 1577.6410 |
================================== Ai Message ==================================
Tool Calls:
  get_indicators (call_-7637663033065471717)
 Call ID: call_-7637663033065471717
  Args:
    symbol: 600519.SH
    indicator: atr
    curr_date: 2024-05-10
    look_back_days: 30
================================= Tool Message =================================
Name: get_indicators

DATA_STATUS: OK
DATA_SOURCE: akshare_sina
SYMBOL: 600519.SH
REQUESTED_RANGE: 2024-02-10 to 2024-05-10
ACTUAL_RANGE: 2024-02-19 to 2024-05-10
CAN_USE_FOR_DECISION: true
数据来自 AkShare 新浪接口。
指标名称: atr -> Volatility_20
最新指标值: 5.1703
数据长度不足,部分长周期指标可能为空。
| Date | Close | Volatility_20 |
| --- | --- | --- |
| 2024-04-24 | 1575.4600 | 5.0746 |
| 2024-04-25 | 1574.9400 | 4.9200 |
| 2024-04-26 | 1590.1800 | 4.9962 |
| 2024-04-29 | 1585.1300 | 5.0083 |
| 2024-04-30 | 1586.0600 | 5.0081 |
| 2024-05-06 | 1637.4100 | 5.8807 |
| 2024-05-07 | 1646.5300 | 5.8668 |
| 2024-05-08 | 1640.9200 | 5.8884 |
| 2024-05-09 | 1633.5000 | 5.0447 |
| 2024-05-10 | 1617.6700 | 5.1703 |
================================== Ai Message ==================================
Tool Calls:
  get_indicators (call_-7637668083947007346)
 Call ID: call_-7637668083947007346
  Args:
    symbol: 600519.SH
    indicator: vwma
    curr_date: 2024-05-10
    look_back_days: 30
================================= Tool Message =================================
Name: get_indicators

DATA_STATUS: OK
DATA_SOURCE: akshare_sina
SYMBOL: 600519.SH
REQUESTED_RANGE: 2024-02-10 to 2024-05-10
ACTUAL_RANGE: 2024-02-19 to 2024-05-10
CAN_USE_FOR_DECISION: true
数据来自 AkShare 新浪接口。
指标名称: vwma -> Volume_Ratio_5_20
最新指标值: 1.0741
数据长度不足,部分长周期指标可能为空。
| Date | Close | Volume_Ratio_5_20 |
| --- | --- | --- |
| 2024-04-24 | 1575.4600 | 0.9097 |
| 2024-04-25 | 1574.9400 | 0.8409 |
| 2024-04-26 | 1590.1800 | 0.8767 |
| 2024-04-29 | 1585.1300 | 0.9325 |
| 2024-04-30 | 1586.0600 | 0.9448 |
| 2024-05-06 | 1637.4100 | 1.1776 |
| 2024-05-07 | 1646.5300 | 1.2480 |
| 2024-05-08 | 1640.9200 | 1.1679 |
| 2024-05-09 | 1633.5000 | 1.1083 |
| 2024-05-10 | 1617.6700 | 1.0741 |
================================== Ai Message ==================================


# market_report

## 贵州茅台(600519.SH)市场分析报告

**数据来源:** AkShare东方财富接口 (2024-02-19至2024-05-10)

### 基本面表现
- **期间涨跌幅:** +2.74%
- **区间价格:** 1589.11 - 1671.48元
- **平均成交量:** 2.75万股
- **平均换手率:** 0.22%
- **最大单日波动:** 3.45%

### 技术指标分析

#### 趋势指标
- **MA20 (50日均线):** 1577.64元,股价位于均线之上,短期趋势向上
- **MA60 (200日均线):** 1577.18元,股价位于均线之上,中期趋势向好
- **MA10 (10日均线):** 1608.78元,股价位于均线之下,短期有回调压力

#### 动量指标
- **MACD:** 16.20,正值显示多头力量占优,但MACD线开始走平,动能可能减弱
- **RSI:** 68.52,处于中性偏强区间,接近超买区域(70),存在回调风险

#### 波动与成交量指标
- **ATR (波动率):** 5.17,波动率适中,股价在合理范围内波动
- **VWMA (成交量比率):** 1.07,成交量略高于平均水平,有一定买盘支撑

### 关键观察
1. **价格走势:** 股价从2月底的1589元上涨至5月初的1671元高点,随后出现回调,当前1632元
2. **趋势确认:** 股价长期均线系统多头排列,但短期均线出现死叉信号
3. **风险信号:** RSI接近超买区域,MACD动能减弱,显示上涨动能可能不足
4. **成交量:** 近期成交量放大后有所回落,显示买盘热情有所降温

### 技术面总结
贵州茅台目前处于高位震荡调整阶段,虽然长期趋势依然向好,但短期面临技术性回调压力。RSI指标的超买状态和MACD的走平都预示着股价可能需要时间来消化前期涨幅。

### 交易策略建议
基于当前技术面分析,建议采取谨慎观望策略,等待更明确的信号出现。

| 指标 | 当前值 | 信号强度 | 方向 |
|------|--------|----------|------|
| MA20 | 1577.64 | 强 | 多头 |
| MA60 | 1577.18 | 强 | 多头 |
| MA10 | 1608.78 | 中性 | 空头 |
| MACD | 16.20 | 中性 | 多头 |
| RSI | 68.52 | 弱 | 中性 |
| ATR | 5.17 | 中性 | 中性 |
| VWMA | 1.07 | 弱 | 多头 |

**FINAL TRANSACTION PROPOSAL: HOLD**
================================ Human Message =================================

Continue
================================== Ai Message ==================================


我将为您分析 `600519.SH` 的相关新闻和市场情况。让我获取最新的公司新闻和全球市场动态。
Tool Calls:
  get_news (call_-7637660078127971614)
 Call ID: call_-7637660078127971614
  Args:
    ticker: 600519.SH
    start_date: 2024-04-30
    end_date: 2024-05-10
  get_global_news (call_-7637660078127971613)
 Call ID: call_-7637660078127971613
  Args:
    curr_date: 2024-05-10
    look_back_days: 7
    limit: 5
================================= Tool Message =================================                  
Name: get_global_news

DATA_STATUS: OK
DATA_SOURCE: akshare_tencent
SYMBOL: 000300.SH
REQUESTED_RANGE: 2024-05-03 to 2024-05-10
ACTUAL_RANGE: 2024-05-06 to 2024-05-10
CAN_USE_FOR_DECISION: true
指数名称: 沪深300
区间涨跌幅: 0.23%
| Date | Open | High | Low | Close | Volume | Amount | Amplitude | PctChange | Change | Turnover |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 2024-05-06 | 3654.05 | 3668.26 | 3645.74 | 3657.88 | 20801800700.0 |  |  |  |  |  |
| 2024-05-07 | 3657.0 | 3665.68 | 3648.38 | 3659.01 | 16483428600.0 |  | 0.47295154570406156 | 0.0308922107887577 | 1.1300000000001091 |  |
| 2024-05-08 | 3650.75 | 3650.94 | 3628.7 | 3630.22 | 13003533600.0 |  | 0.6078146821134743 | -0.7868248515308873 | -28.79000000000042 |  |
| 2024-05-09 | 3630.41 | 3669.76 | 3630.41 | 3664.56 | 14655901700.0 |  | 1.0839563442436095 | 0.9459481794491742 | 34.340000000000146 |  |
| 2024-05-10 | 3669.09 | 3674.61 | 3641.76 | 3666.28 | 15072053600.0 |  | 0.8964241273167831 | 0.046936057807767106 | 1.7200000000002547 |  |
================================== Ai Message ==================================
Tool Calls:
  get_news (call_-7637676536442645627)
 Call ID: call_-7637676536442645627
  Args:
    ticker: 600519.SH
    start_date: 2024-05-01
    end_date: 2024-05-10
================================= Tool Message =================================
Name: get_news

DATA_UNAVAILABLE
DATA_STATUS: DATA_UNAVAILABLE
DATA_SOURCE: none
SYMBOL: 600519.SH
REQUESTED_RANGE: 2024-05-01 to 2024-05-10
ACTUAL_RANGE: 暂无数据
CAN_USE_FOR_DECISION: false
WARNING: 未获取到真实新闻公告。KeyError: '600519'
================================== Ai Message ==================================
Tool Calls:
  get_global_news (call_-7637670867085819615)
 Call ID: call_-7637670867085819615
  Args:
    curr_date: 2024-05-10
    look_back_days: 10
    limit: 8
================================= Tool Message =================================                  
Name: get_global_news

DATA_STATUS: OK
DATA_SOURCE: akshare_tencent
SYMBOL: 000300.SH
REQUESTED_RANGE: 2024-04-30 to 2024-05-10
ACTUAL_RANGE: 2024-04-30 to 2024-05-10
CAN_USE_FOR_DECISION: true
指数名称: 沪深300
区间涨跌幅: 1.72%
| Date | Open | High | Low | Close | Volume | Amount | Amplitude | PctChange | Change | Turnover |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 2024-04-30 | 3619.26 | 3630.71 | 3604.39 | 3604.39 | 19129689900.0 |  |  |  |  |  |
| 2024-05-06 | 3654.05 | 3668.26 | 3645.74 | 3657.88 | 20801800700.0 |  | 0.6247936544047796 | 1.4840236489392256 | 53.49000000000024 |  |
| 2024-05-07 | 3657.0 | 3665.68 | 3648.38 | 3659.01 | 16483428600.0 |  | 0.47295154570406156 | 0.0308922107887577 | 1.1300000000001091 |  |
| 2024-05-08 | 3650.75 | 3650.94 | 3628.7 | 3630.22 | 13003533600.0 |  | 0.6078146821134743 | -0.7868248515308873 | -28.79000000000042 |  |
| 2024-05-09 | 3630.41 | 3669.76 | 3630.41 | 3664.56 | 14655901700.0 |  | 1.0839563442436095 | 0.9459481794491742 | 34.340000000000146 |  |
| 2024-05-10 | 3669.09 | 3674.61 | 3641.76 | 3666.28 | 15072053600.0 |  | 0.8964241273167831 | 0.046936057807767106 | 1.7200000000002547 |  |
================================== Ai Message ==================================


## news_report

基于可用的数据源,我对 `600519.SH`(贵州茅台)进行了新闻和市场分析,以下是详细报告:

### 数据来源说明
- **公司新闻数据**: 无法获取到 `600519.SH` 的具体新闻公告,显示"DATA_UNAVAILABLE"
- **市场数据来源**: akshare_tencent(腾讯财经数据)
- **数据时间范围**: 2024-04-30 至 2024-05-10
- **数据状态**: 市场数据可用,公司新闻数据不可用

### 市场整体表现分析
根据沪深300指数表现:
- **区间涨跌幅**: +1.72%
- **整体趋势**: 震荡上行,市场情绪相对稳定
- **关键时点**: 
  - 4月30日:3604.39点
  - 5月10日:3666.28点
- **成交量变化**: 整体保持活跃,5月6日达到峰值2080亿

### 对 `600519.SH` 的分析
由于无法获取具体的公司新闻数据,分析基于以下有限信息:

**积极因素:**
1. 市场整体表现良好,为白酒板块提供支撑
2. 沪深300指数呈现震荡上行趋势
3. 成交量保持活跃,市场流动性充足

**风险因素:**
1. 缺乏公司具体新闻信息,无法评估基本面变化
2. 无法获取业绩指引、分红政策等重要信息
3. 无法了解行业政策变化对公司的影响

### 建议与风险提示
1. **建议**: 由于缺乏具体公司新闻,建议投资者关注后续发布的公司公告和业绩报告
2. **风险**: 基于有限信息进行投资决策存在较高不确定性
3. **关注重点**: 期待获取更多关于公司经营状况、行业政策等方面的具体信息

### 总结
在当前数据条件下,无法对 `600519.SH` 进行全面的基本面分析。市场整体表现积极,但缺乏公司层面的具体信息。建议投资者等待更完整的数据后再做投资决策。

| 分析项目 | 状态 | 数据可用性 | 风险等级 |
|---------|------|-----------|----------|
| 公司新闻 | 不可用 | DATA_UNAVAILABLE | 高 |
| 市场数据 | 可用 | DATA_STATUS: OK | 低 |
| 基本面分析 | 受限 | 部分可用 | 中 |
| 投资建议 | 建议观望 | 信息不足 | 高 |
================================ Human Message =================================

Continue
================================== Ai Message ==================================


我将开始分析600519.SH(贵州茅台)在过去一周(2024-05-03至2024-05-10)的投资者情绪和市场反应。
Tool Calls:
  get_social_sentiment (call_-7637633105733352731)
 Call ID: call_-7637633105733352731
  Args:
    ticker: 600519.SH
    start_date: 2024-05-03
    end_date: 2024-05-10
================================= Tool Message =================================
Name: get_social_sentiment

DATA_STATUS: OK
DATA_SOURCE: akshare_sina
SYMBOL: 600519.SH
REQUESTED_RANGE: 2024-05-03 to 2024-05-10
ACTUAL_RANGE: 2024-05-06 to 2024-05-10
CAN_USE_FOR_DECISION: true
情绪方向: neutral
情绪强度: 0.45
近 5 日涨跌幅: 暂无数据
量比(5/20): 暂无数据
最新换手率: 0.21%
最新振幅: 1.93%
摘要: 近 5 日价格和量能变化相对中性,情绪未出现明显单边。
================================== Ai Message ==================================
Tool Calls:
  get_news (call_-7637666709557472276)
 Call ID: call_-7637666709557472276
  Args:
    ticker: 600519.SH
    start_date: 2024-05-03
    end_date: 2024-05-10
================================= Tool Message =================================
Name: get_news

DATA_UNAVAILABLE
DATA_STATUS: DATA_UNAVAILABLE
DATA_SOURCE: none
SYMBOL: 600519.SH
REQUESTED_RANGE: 2024-05-03 to 2024-05-10
ACTUAL_RANGE: 暂无数据
CAN_USE_FOR_DECISION: false
WARNING: 未获取到真实新闻公告。KeyError: '600519'
================================== Ai Message ==================================


sentiment_report:

## 600519.SH(贵州茅台)投资者情绪分析报告

### 数据概览
- **数据源**: akshare_sina
- **分析期间**: 2024-05-03至2024-05-10
- **实际数据覆盖**: 2024-05-06至2024-05-10(5天数据)
- **数据可用性**: 社会情绪数据可用,新闻数据不可用

### 情绪分析结果
**情绪方向**: 中性
**情绪强度**: 0.45(中等偏弱)

### 市场表现指标
- **最新换手率**: 0.21%(相对较低,显示交投相对清淡)
- **最新振幅**: 1.93%(波动幅度适中)
- **近5日涨跌幅**: 暂无数据
- **量比(5/20)**: 暂无数据

### 情绪解读
根据akshare_sina提供的情绪数据,贵州茅台在过去5个交易日内呈现出中性偏弱的市场情绪。情绪强度为0.45,表明投资者态度相对谨慎,未出现明显的单边看涨或看跌情绪。

市场量能指标显示换手率仅为0.21%,相对较低,可能反映出投资者观望情绪较重,成交活跃度不足。振幅1.93%显示价格波动相对温和,没有出现剧烈的市场波动。

### 新闻数据情况
遗憾的是,本次分析未能获取到相关的新闻公告数据,无法通过新闻事件来佐证情绪变化的原因。这可能限制了我们对情绪驱动因素的分析深度。

### 投资者关注要点
1. **情绪中性**: 当前投资者对茅台的态度相对平衡,既未表现出强烈的乐观也未出现恐慌性抛售
2. **量能不足**: 低换手率可能暗示市场参与度不高,需要关注后续成交量变化
3. **波动温和**: 价格波动控制在合理范围内,显示相对稳定的市场表现

### 结论
基于现有情绪数据,600519.SH当前呈现中性偏弱的投资者情绪,市场表现相对平稳。建议投资者继续关注后续成交量变化以及可能影响股价的重要新闻事件。

| 指标 | 数值 | 说明 |
|------|------|------|
| 情绪方向 | 中性 | 投资者态度相对平衡 |
| 情绪强度 | 0.45 | 中等偏弱水平 |
| 数据覆盖期间 | 2024-05-06至2024-05-10 | 实际5个交易日数据 |
| 换手率 | 0.21% | 交投相对清淡 |
| 振幅 | 1.93% | 波动幅度适中 |
| 新闻数据 | 不可用 | 无法获取相关新闻公告 |
================================ Human Message =================================

Continue
================================== Ai Message ==================================


我需要先获取600519.SH的基本面数据来进行分析。让我调用相关工具来获取信息。
Tool Calls:
  get_fundamentals (call_-7637656367276223522)
 Call ID: call_-7637656367276223522
  Args:
    ticker: 600519.SH
    curr_date: 2024-05-10
================================= Tool Message =================================                  
Name: get_fundamentals

DATA_STATUS: OK
DATA_SOURCE: akshare_multi_interface
SYMBOL: 600519.SH
REPORT_PERIOD: 20240331
DATA_SOURCES: stock_balance_sheet_by_report_em, stock_cash_flow_sheet_by_report_em, stock_financial_abstract, stock_financial_abstract_new_ths, stock_financial_analysis_indicator_em, stock_individual_basic_info_xq, stock_individual_info_em, stock_individual_spot_xq, stock_profit_sheet_by_report_em
MISSING_FIELDS: 无
ERRORS: {"stock_zh_a_spot_em": "ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))"}
CAN_USE_FOR_DECISION: true
| 字段 | 数值 | 来源 |
|---|---|---|
| 股票名称 | 贵州茅台 | stock_individual_info_em |
| 行业 | 白酒Ⅱ | stock_individual_info_em |
| 地区 | 贵州省 | stock_individual_basic_info_xq |
| 上市日期 | 2001-08-27 | stock_individual_info_em |
| 市盈率 PE | 15.778 | stock_individual_spot_xq |
| 市净率 PB | 6.347 | stock_individual_spot_xq |
| 总市值 | 1719354482492.85 | stock_individual_info_em |
| 流通市值 | 1719354482492.85 | stock_individual_info_em |
| ROE | 10.5700 | stock_financial_abstract_new_ths |
| 每股收益 EPS | 19.16 | stock_profit_sheet_by_report_em |
| 营收 | 46484738134.23 | stock_profit_sheet_by_report_em |
| 净利润 | 24065262374.15 | stock_profit_sheet_by_report_em |
| 毛利率 | 92.6133 | stock_financial_abstract_new_ths |
| 净利率 | 54.3573 | stock_financial_abstract_new_ths |
| 资产负债率 | 12.9543 | stock_financial_abstract_new_ths |
| 流动比率 | 6.4810 | stock_financial_abstract_new_ths |
| 经营活动现金流 | 9187422415.09 | stock_cash_flow_sheet_by_report_em |
| 营收同比 | 18.0435812731 | stock_profit_sheet_by_report_em |
| 净利润同比 | 15.7268480818 | stock_profit_sheet_by_report_em |
| 总资产 | 285524543268.38 | stock_balance_sheet_by_report_em |
| 总负债 | 36987774717.85 | stock_balance_sheet_by_report_em |
| 净资产 | 239731785910.55 | stock_balance_sheet_by_report_em |
| 财务摘要 | 营业收入: 46484738134.23;归母净利润: 24065262374.15;毛利率: 92.6133;资产负债率: 12.9543 | merged_summary |
================================== Ai Message ==================================
Tool Calls:
  get_balance_sheet (call_-7637665506966629330)
 Call ID: call_-7637665506966629330
  Args:
    ticker: 600519.SH
    curr_date: 2024-05-10
================================= Tool Message =================================
Name: get_balance_sheet

DATA_STATUS: DATA_UNAVAILABLE
DATA_SOURCE: none
SYMBOL: 600519.SH
CAN_USE_FOR_DECISION: false
说明: 第一版暂未单独提供 A 股资产负债表明细接口,请优先参考 fundamentals_report。
================================== Ai Message ==================================
Tool Calls:
  get_cashflow (call_-7637673306627237677)
 Call ID: call_-7637673306627237677
  Args:
    ticker: 600519.SH
    curr_date: 2024-05-10
================================= Tool Message =================================
Name: get_cashflow

DATA_STATUS: DATA_UNAVAILABLE
DATA_SOURCE: none
SYMBOL: 600519.SH
CAN_USE_FOR_DECISION: false
说明: 第一版暂未单独提供 A 股现金流明细接口,请优先参考 fundamentals_report。
================================== Ai Message ==================================
Tool Calls:
  get_income_statement (call_-7637666709557474897)
 Call ID: call_-7637666709557474897
  Args:
    ticker: 600519.SH
    curr_date: 2024-05-10
================================= Tool Message =================================
Name: get_income_statement

DATA_STATUS: DATA_UNAVAILABLE
DATA_SOURCE: none
SYMBOL: 600519.SH
CAN_USE_FOR_DECISION: false
说明: 第一版暂未单独提供 A 股利润表明细接口,请优先参考 fundamentals_report。
================================== Ai Message ==================================


根据获取的数据,我对600519.SH(贵州茅台)进行基本面分析:

## 公司概况
- **股票名称**:贵州茅台
- **行业**:白酒Ⅱ
- **地区**:贵州省
- **上市日期**:2001-08-27
- **报告期**:2024年3月31日

## 估值分析
- **市盈率(PE)**:15.78倍
- **市净率(PB)**:6.35倍
- **总市值**:1.72万亿元
- **流通市值**:1.72万亿元

## 盈利能力分析
- **每股收益(EPS)**:19.16元
- **净资产收益率(ROE)**:10.57%
- **毛利率**:92.61%
- **净利率**:54.36%
- **净利润**:240.65亿元
- **营收**:464.85亿元

## 增长性分析
- **营收同比**:18.04%
- **净利润同比**:15.73%

## 财务健康状况
- **资产负债率**:12.95%
- **流动比率**:6.48倍
- **总资产**:2,855.25亿元
- **总负债**:369.88亿元
- **净资产**:2,397.32亿元
- **经营活动现金流**:91.87亿元

## 综合评价

**优势:**
1. **极强的盈利能力**:毛利率高达92.61%,净利率54.36%,在白酒行业中处于绝对领先地位
2. **优秀的财务状况**:资产负债率仅12.95%,流动比率6.48倍,财务风险极低
3. **持续增长**:营收和净利润均保持双位数增长,显示出良好的发展势头
4. **品牌价值**:作为白酒行业的龙头企业,拥有强大的品牌溢价能力
5. **现金流充足**:经营活动现金流91.87亿元,现金储备充足

**关注点:**
1. **估值相对较高**:PB 6.35倍,PE 15.78倍,相对于白酒行业平均水平估值偏高
2. **增长放缓迹象**:净利润增速15.73%相比前几年有所放缓

**投资建议:**
贵州茅台作为白酒行业的龙头企业,具有极强的品牌优势、盈利能力和财务稳健性。虽然当前估值相对较高,但其护城河深厚,业绩增长稳定,长期投资价值依然突出。考虑到公司基本面优秀,建议**持有**,可关注其估值回调机会。

| 字段 | 数值 |
|---|---|
| 股票名称 | 贵州茅台 |
| 行业 | 白酒Ⅱ |
| 地区 | 贵州省 |
| 上市日期 | 2001-08-27 |
| 市盈率 PE | 15.778 |
| 市净率 PB | 6.347 |
| 总市值 | 1719354482492.85 |
| 流通市值 | 1719354482492.85 |
| ROE | 10.5700 |
| 每股收益 EPS | 19.16 |
| 营收 | 46484738134.23 |
| 净利润 | 24065262374.15 |
| 毛利率 | 92.6133 |
| 净利率 | 54.3573 |
| 资产负债率 | 12.9543 |
| 流动比率 | 6.4810 |
| 经营活动现金流 | 9187422415.09 |
| 营收同比 | 18.0435812731 |
| 净利润同比 | 15.7268480818 |
| 总资产 | 285524543268.38 |
| 总负债 | 36987774717.85 |
| 净资产 | 239731785910.55 |
| 财务摘要 | 营业收入: 46484738134.23;归母净利润: 24065262374.15;毛利率: 92.6133;资产负债率: 12.9543 |
================================ Human Message =================================

Continue
================================ Human Message =================================

Continue
================================ Human Message =================================

Continue
================================ Human Message =================================

Continue
================================== Ai Message ==================================

**Action**: Hold

**Reasoning**: 贵州茅台 represents one of China's highest-quality businesses with exceptional margins (92.61% gross, 54.36% net) and strong brand moat, but the OCF-to-net profit gap (38% conversion rate) raises earnings quality concerns. The stock trades at 6.35x PB with decelerating growth and faces significant macro headwinds from China's property crisis, unemployment, and anti-corruption campaigns targeting its core customer base. The current valuation already reflects much of the business quality, and the near-term risk/reward doesn't favor increasing exposure at current levels.

**Position Sizing**: Maintain current position size - do not add or trim

FINAL TRANSACTION PROPOSAL: **HOLD**
================================== Ai Message ==================================

**Action**: Hold

**Reasoning**: 贵州茅台 represents one of China's highest-quality businesses with exceptional margins (92.61% gross, 54.36% net) and strong brand moat, but the OCF-to-net profit gap (38% conversion rate) raises earnings quality concerns. The stock trades at 6.35x PB with decelerating growth and faces significant macro headwinds from China's property crisis, unemployment, and anti-corruption campaigns targeting its core customer base. The current valuation already reflects much of the business quality, and the near-term risk/reward doesn't favor increasing exposure at current levels.

**Position Sizing**: Maintain current position size - do not add or trim

FINAL TRANSACTION PROPOSAL: **HOLD**
================================== Ai Message ==================================

**Action**: Hold

**Reasoning**: 贵州茅台 represents one of China's highest-quality businesses with exceptional margins (92.61% gross, 54.36% net) and strong brand moat, but the OCF-to-net profit gap (38% conversion rate) raises earnings quality concerns. The stock trades at 6.35x PB with decelerating growth and faces significant macro headwinds from China's property crisis, unemployment, and anti-corruption campaigns targeting its core customer base. The current valuation already reflects much of the business quality, and the near-term risk/reward doesn't favor increasing exposure at current levels.

**Position Sizing**: Maintain current position size - do not add or trim

FINAL TRANSACTION PROPOSAL: **HOLD**
================================== Ai Message ==================================

**Action**: Hold

**Reasoning**: 贵州茅台 represents one of China's highest-quality businesses with exceptional margins (92.61% gross, 54.36% net) and strong brand moat, but the OCF-to-net profit gap (38% conversion rate) raises earnings quality concerns. The stock trades at 6.35x PB with decelerating growth and faces significant macro headwinds from China's property crisis, unemployment, and anti-corruption campaigns targeting its core customer base. The current valuation already reflects much of the business quality, and the near-term risk/reward doesn't favor increasing exposure at current levels.

**Position Sizing**: Maintain current position size - do not add or trim

FINAL TRANSACTION PROPOSAL: **HOLD**
================================== Ai Message ==================================

**Action**: Hold

**Reasoning**: 贵州茅台 represents one of China's highest-quality businesses with exceptional margins (92.61% gross, 54.36% net) and strong brand moat, but the OCF-to-net profit gap (38% conversion rate) raises earnings quality concerns. The stock trades at 6.35x PB with decelerating growth and faces significant macro headwinds from China's property crisis, unemployment, and anti-corruption campaigns targeting its core customer base. The current valuation already reflects much of the business quality, and the near-term risk/reward doesn't favor increasing exposure at current levels.

**Position Sizing**: Maintain current position size - do not add or trim

FINAL TRANSACTION PROPOSAL: **HOLD**
Hold

2.1 第一段代码:examples/run_ashare_full.py

这个文件是 A股版本完整流程的入口。

源码核心是:

from copy import deepcopy

from dotenv import load_dotenv

from tradingagents.default_config import DEFAULT_CONFIG
from tradingagents.graph.trading_graph import TradingAgentsGraph


load_dotenv()

config = deepcopy(DEFAULT_CONFIG)
config["market"] = "A-share"
config["llm_provider"] = "glm"
config["deep_think_llm"] = "glm-5.1"
config["quick_think_llm"] = "glm-4.7"
config["output_language"] = "Chinese"
config["data_vendors"] = {
    "core_stock_apis": "a_share",
    "technical_indicators": "a_share",
    "fundamental_data": "a_share",
    "news_data": "a_share",
}
...
ta = TradingAgentsGraph(
    selected_analysts=["market", "news", "social", "fundamentals"],
    debug=True,
    config=config,
)

_, decision = ta.propagate("600519.SH", "2024-05-10")
print(decision)

1. load_dotenv()

位置:examples/run_ashare_full.py:9

作用是加载 .env 文件。

A股版本里 LLM provider 设置成了 GLM,所以这里通常依赖 .env 中的 API key,例如智谱 GLM 的环境变量。它不直接影响 A 股数据逻辑,但会影响后面所有 Agent 的 LLM 调用。

2. config = deepcopy(DEFAULT_CONFIG)

位置:examples/run_ashare_full.py:11

这里不是直接修改 DEFAULT_CONFIG,而是复制一份出来。

原因是 DEFAULT_CONFIG 是全局默认配置,后续你可能还要保留美股、CLI、其他示例脚本。如果直接修改原对象,容易污染其他运行流程。

A股版本这样做是合理的:

config = deepcopy(DEFAULT_CONFIG)

含义是:

拿一份原始 TradingAgents 默认配置
然后只针对本次运行覆盖市场、模型、数据源和 A 股参数

3. 切换市场模式

位置:examples/run_ashare_full.py:12

config["market"] = "A-share"

这个字段本身不是所有逻辑的唯一开关,但它代表本次运行语义上是 A 股。

真正决定工具走 A 股数据源的是后面的:

config["data_vendors"] = {
"core_stock_apis": "a_share",
"technical_indicators": "a_share",
"fundamental_data": "a_share",
"news_data": "a_share",
}

也就是说:

market = A-share
表示这次任务是 A 股分析

data_vendors = a_share
才真正决定工具函数进入 a_share.py

说明:A 股模式下会自动切换这四类 vendor 到 a_share

4. 指定 LLM provider 和模型

位置:examples/run_ashare_full.py:13-15

config["llm_provider"] = "glm"
config["deep_think_llm"] = "glm-5.1"
config["quick_think_llm"] = "glm-4.7"

这里有两个模型:

deep_think_llm → 用于更重的判断节点
quick_think_llm → 用于分析师、工具调用、辩论等较快节点

后面进入 TradingAgentsGraph.__init__() 时,会根据这三个配置创建两个 LLM client:

self.deep_thinking_llm
self.quick_thinking_llm

A股版本里:

Research Manager 和 Portfolio Manager 通常用 deep_thinking_llm
Market / News / Social / Fundamentals / Trader / Risk Analysts 通常用 quick_thinking_llm

5. 设置输出语言

位置:examples/run_ashare_full.py:16

config["output_language"] = "Chinese"

这个字段会被 get_language_instruction() 读取。

在 A股版本的 tradingagents/agents/utils/agent_utils.py 中:

def get_language_instruction() -> str:
    from tradingagents.dataflows.config import get_config
    lang = get_config().get("output_language", "English")
    if lang.strip().lower() == "english":
        return ""
    return f" Write your entire response in {lang}."

也就是说,如果配置是Chinese,就会在 Agent prompt 后面追加:

Write your entire response in Chinese.

这就是为什么输出的decision里分析师报告大多是中文。

不过你也可以看到最终某些 Trader / Portfolio Manager 输出里仍夹杂英文,这是因为部分内部 debate / structured render prompt 本身仍是英文,且 Trader 节点没有显式使用 get_language_instruction()。这不是数据层问题,而是 prompt 层语言约束不完全统一的问题。

6. 最关键配置:data_vendors

位置:examples/run_ashare_full.py:17-22

config["data_vendors"] = {
    "core_stock_apis": "a_share",
    "technical_indicators": "a_share",
    "fundamental_data": "a_share",
    "news_data": "a_share",
}

这是 A股版本和原始 TradingAgents 的核心差异之一。

它的含义是:

数据类别 工具 A股版本路由
core_stock_apis get_stock_data get_ashare_stock_data
technical_indicators get_indicators get_ashare_indicator
fundamental_data get_fundamentals get_ashare_fundamentals
news_data get_news / get_global_news / get_social_sentiment get_ashare_news / get_ashare_market_news / get_ashare_social_sentiment

注意:Agent 看到的工具名仍是原来的抽象工具名,比如 get_stock_dataget_indicators。真正换掉的是背后的 vendor 实现。

这正是 A股版本“最小改动”的核心:

不重写 Agent
不重写 TradingAgentsGraph
不绕过 LangGraph
只把工具后面的数据实现切到 a_share.py

7. A 股数据专属配置:a_share_data

位置:examples/run_ashare_full.py:23-35

config["a_share_data"] = {
    "price_source": "akshare",
    "news_source": "akshare",
    "fundamental_source": "akshare_or_unavailable",
    "social_source": "market_derived_or_unavailable",
    "cache_dir": "data/cache/a_share",
    "use_cache": True,
    "adjust": "qfq",
    "allow_mock": False,
    "retry_times": 2,
    "retry_sleep_seconds": 2,
    "nearby_cache_max_days": 30,
}

这段配置只给 a_share.py 使用。

逐项解释:

配置 含义
price_source = akshare 行情优先用 AkShare
news_source = akshare 新闻公告优先用 AkShare
fundamental_source = akshare_or_unavailable 基本面尽量用 AkShare,失败则返回不可用,不造假
social_source = market_derived_or_unavailable 情绪来自行情衍生指标,不伪造社区数据
cache_dir = data/cache/a_share A 股缓存根目录
use_cache = True 允许使用缓存
adjust = qfq 前复权
allow_mock = False 禁止 mock 假数据
retry_times = 2 每个在线接口最多尝试 2 次
retry_sleep_seconds = 2 重试间隔 2 秒
nearby_cache_max_days = 30 附近日期缓存最多允许相差 30 天

这段配置体现了A 股数据原则:行情优先在线拉取,成功后写缓存;失败时回退真实缓存;不生成假行情数据。

8. 控制辩论轮数

位置:examples/run_ashare_full.py:36-37

config["max_debate_rounds"] = 1
config["max_risk_discuss_rounds"] = 1

这两个参数控制后半段讨论深度。

tradingagents/graph/conditional_logic.py 中:

if state["investment_debate_state"]["count"] >= 2 * self.max_debate_rounds:
    return "Research Manager"

也就是说:

max_debate_rounds = 1
→ Bull / Bear 最多各说一轮左右
→ count 达到 2 后进入 Research Manager

风险讨论类似:

if state["risk_debate_state"]["count"] >= 3 * self.max_risk_discuss_rounds:
    return "Portfolio Manager"

所以:

max_risk_discuss_rounds = 1
→ Aggressive / Conservative / Neutral 各一轮左右
→ 然后交给 Portfolio Manager

这让 run_ashare_full.py 既能跑完整团队,又不会无限辩论。

2.2 第二段代码:创建 TradingAgentsGraph

入口文件接着执行:

ta = TradingAgentsGraph(
    selected_analysts=["market", "news", "social", "fundamentals"],
    debug=True,
    config=config,
)

位置:examples/run_ashare_full.py:39-43

这一步不是开始分析股票,而是搭建整套多智能体工作流

1.selected_analysts

selected_analysts=["market", "news", "social", "fundamentals"]

这决定前半段 Analyst Team 的顺序。

A股版本这次顺序是:

Market Analyst
→ News Analyst
→ Social Analyst
→ Fundamentals Analyst
→ Bull Researcher

这和默认顺序略有不同。TradingAgentsGraph.__init__() 默认参数里是:

selected_analysts=["market", "social", "news", "fundamentals"]

run_ashare_full.py 显式传入了:

["market", "news", "social", "fundamentals"]

所以实际运行中是先新闻、再情绪。decision也验证了这一点:Market 报告之后,下一段进入 get_newsget_global_news,再之后才进入 get_social_sentiment

2. debug=True

debug=True

这个字段非常重要。

TradingAgentsGraph._run_graph() 中:

if self.debug:
    trace = []
    for chunk in self.graph.stream(init_agent_state, **args):
        if len(chunk["messages"]) == 0:
            pass
        else:
            chunk["messages"][-1].pretty_print()
            trace.append(chunk)
    final_state = trace[-1]
else:
    final_state = self.graph.invoke(init_agent_state, **args)

位置:tradingagents/graph/trading_graph.py:318-328

所以:

debug=True
→ graph.stream(...)
→ 每个节点的最后一条 message 都 pretty_print()
→ 你会在终端看到 Human Message / Ai Message / Tool Message

这就是为什么你的decision里有大量这样的结构:

====================== Human Message =======================
600519.SH

======================== Ai Message =========================
Tool Calls:
get_stock_data ...

======================= Tool Message ========================
Name: get_stock_data
DATA_STATUS: OK
...

这些不是手动打印的,而是 LangGraph stream + pretty_print() 打出来的。

2.3 第三段代码:TradingAgentsGraph.__init__()

文件:tradingagents/graph/trading_graph.py

核心初始化流程在 __init__() 中。

1. 保存配置并写入 dataflow 全局配置

位置:tradingagents/graph/trading_graph.py:68-73

self.debug = debug
self.config = config or DEFAULT_CONFIG
self.callbacks = callbacks or []

set_config(self.config)

最关键的是:

set_config(self.config)

它会调用:

tradingagents/dataflows/config.py

里面有:

_config: Optional[Dict] = None

def set_config(config: Dict):
    global _config
    if _config is None:
        _config = default_config.DEFAULT_CONFIG.copy()
    _config.update(config)

def get_config() -> Dict:
    if _config is None:
        initialize_config()
    return _config.copy()

这说明 A股版本的配置是通过一个模块级 _config 存起来的。

后面 route_to_vendor()get_language_instruction()a_share.py 中的 _get_runtime_config() 都会通过 get_config() 读取同一份运行配置。

所以这里是一个关键转折点:

run_ashare_full.py 里的局部 config
经过 set_config()
变成 dataflows 层可见的全局运行配置

如果没有这一步,后面的工具函数不会知道当前应该走 a_share

2. 创建结果目录和缓存目录

位置:tradingagents/graph/trading_graph.py:75-77

os.makedirs(self.config["data_cache_dir"], exist_ok=True)
os.makedirs(self.config["results_dir"], exist_ok=True)

注意这里创建的是通用缓存目录和结果目录:

data_cache_dir
results_dir

A 股自己的缓存目录 data/cache/a_share 是在 a_share.py 内部根据 a_share_data["cache_dir"] 创建的。

也就是说有两层目录:

TradingAgents 通用缓存 / 结果目录
A 股数据 vendor 自己的 cache_dir

A 股缓存目录包括 prices、news、social、fundamentals、indices。

3. 创建两个 LLM client

位置:tradingagents/graph/trading_graph.py:79-100

deep_client = create_llm_client(
    provider=self.config["llm_provider"],
    model=self.config["deep_think_llm"],
    base_url=self.config.get("backend_url"),
    **llm_kwargs,
)

quick_client = create_llm_client(
    provider=self.config["llm_provider"],
    model=self.config["quick_think_llm"],
    base_url=self.config.get("backend_url"),
    **llm_kwargs,
)

self.deep_thinking_llm = deep_client.get_llm()
self.quick_thinking_llm = quick_client.get_llm()

结合入口配置,这里实际等价于:

deep_thinking_llm:
provider = glm
model = glm-5.1

quick_thinking_llm:
provider = glm
model = glm-4.7

后续 GraphSetup 里不同节点会使用不同 LLM:

Market / News / Social / Fundamentals → quick_thinking_llm
Bull / Bear → quick_thinking_llm
Research Manager → deep_thinking_llm
Trader → quick_thinking_llm
Risk Analysts → quick_thinking_llm
Portfolio Manager → deep_thinking_llm

这套设计的意图是:

工具调用和普通分析用快模型
最终裁决和综合判断用深模型

4. 创建 memory log

位置:tradingagents/graph/trading_graph.py:102

self.memory_log = TradingMemoryLog(self.config)

这个对象有两个作用:

1. 本次运行开始前,读取同一 ticker 的历史经验
2. 本次运行结束后,把最终决策写入 memory log

_run_graph() 里:

past_context = self.memory_log.get_past_context(company_name)
...
self.memory_log.store_decision(...)

所以 A股版本仍保留原始 TradingAgents 的“历史决策反思 / memory”机制。

但要注意:_fetch_returns() 目前仍用 yfinanceSPY 计算历史收益,这对 A 股 ticker 不一定适配。它只用于 resolve pending memory entries,不影响本次 600519.SH 的主分析流程。

5. 创建工具节点 _create_tool_nodes()

位置:tradingagents/graph/trading_graph.py:155-190

return {
    "market": ToolNode([
        get_stock_data,
        get_indicators,
    ]),
    "social": ToolNode([
        get_social_sentiment,
        get_news,
    ]),
    "news": ToolNode([
        get_news,
        get_global_news,
        get_insider_transactions,
    ]),
    "fundamentals": ToolNode([
        get_fundamentals,
        get_balance_sheet,
        get_cashflow,
        get_income_statement,
    ]),
}

这就是 A股版本里 Analyst 可以调用哪些工具的根源。

四组工具分别是:

ToolNode 可用工具
market get_stock_data, get_indicators
news get_news, get_global_news, get_insider_transactions
social get_social_sentiment, get_news
fundamentals get_fundamentals, get_balance_sheet, get_cashflow, get_income_statement

2.4 第四段代码:GraphSetup.setup_graph()

文件:tradingagents/graph/setup.py

这个文件负责把节点连成 LangGraph。

1. 根据 selected_analysts 创建 Analyst 节点

位置:tradingagents/graph/setup.py:49-75

if "market" in selected_analysts:
    analyst_nodes["market"] = create_market_analyst(self.quick_thinking_llm)
    delete_nodes["market"] = create_msg_delete()
    tool_nodes["market"] = self.tool_nodes["market"]

if "social" in selected_analysts:
    analyst_nodes["social"] = create_social_media_analyst(self.quick_thinking_llm)
    ...

if "news" in selected_analysts:
    analyst_nodes["news"] = create_news_analyst(self.quick_thinking_llm)
    ...

if "fundamentals" in selected_analysts:
    analyst_nodes["fundamentals"] = create_fundamentals_analyst(self.quick_thinking_llm)
    ...

这里有三个要点。

第一,只有 selected_analysts 里出现的 analyst 才会被加入图。

第二,四个 analyst 都用 quick_thinking_llm

第三,每个 analyst 都有一个对应的 Msg Clear xxx 节点,这个节点用于清空消息历史,避免上一个 analyst 的工具调用消息污染下一个 analyst。

2. 创建后半段决策节点

位置:tradingagents/graph/setup.py:77-87

bull_researcher_node = create_bull_researcher(self.quick_thinking_llm)
bear_researcher_node = create_bear_researcher(self.quick_thinking_llm)
research_manager_node = create_research_manager(self.deep_thinking_llm)
trader_node = create_trader(self.quick_thinking_llm)

aggressive_analyst = create_aggressive_debator(self.quick_thinking_llm)
neutral_analyst = create_neutral_debator(self.quick_thinking_llm)
conservative_analyst = create_conservative_debator(self.quick_thinking_llm)
portfolio_manager_node = create_portfolio_manager(self.deep_thinking_llm)

这里可以看到,A股版本保留了原始 TradingAgents 的完整后半段组织结构:

Bull Researcher
Bear Researcher
Research Manager
Trader
Aggressive Analyst
Neutral Analyst
Conservative Analyst
Portfolio Manager

3. 把 Analyst 串起来

位置:tradingagents/graph/setup.py:110-135

核心逻辑是:

first_analyst = selected_analysts[0]
workflow.add_edge(START, f"{first_analyst.capitalize()} Analyst")

for i, analyst_type in enumerate(selected_analysts):
    current_analyst = f"{analyst_type.capitalize()} Analyst"
    current_tools = f"tools_{analyst_type}"
    current_clear = f"Msg Clear {analyst_type.capitalize()}"

    workflow.add_conditional_edges(
        current_analyst,
        getattr(self.conditional_logic, f"should_continue_{analyst_type}"),
        [current_tools, current_clear],
    )
    workflow.add_edge(current_tools, current_analyst)

    if i < len(selected_analysts) - 1:
        next_analyst = f"{selected_analysts[i+1].capitalize()} Analyst"
        workflow.add_edge(current_clear, next_analyst)
    else:
        workflow.add_edge(current_clear, "Bull Researcher")

这个逻辑非常关键。

它表示每个 Analyst 都有两种可能:

如果 LLM 生成了 tool_calls
→ 进入 tools_xxx
→ 工具返回后再回到当前 Analyst

如果 LLM 没有 tool_calls
→ 当前 Analyst 报告完成
→ 进入 Msg Clear xxx
→ 下一个 Analyst

也就是说,一个 Analyst 不是只运行一次,而是可能循环多次:

Market Analyst
→ 请求 get_stock_data
→ tools_market 执行
→ 回到 Market Analyst
→ 请求 get_indicators
→ tools_market 执行
→ 回到 Market Analyst
→ 生成 market_report
→ Msg Clear Market
→ News Analyst

decision正好体现了这一点:Market Analyst 先调用 get_stock_data,然后连续调用多个 get_indicators,最后才生成 market_report

4. 把研究员、交易员、风控、组合经理串起来

位置:tradingagents/graph/setup.py:136-180

流程是:

Bull Researcher ↔ Bear Researcher

Research Manager

Trader

Aggressive Analyst ↔ Conservative Analyst ↔ Neutral Analyst

Portfolio Manager

END

源码中:

workflow.add_conditional_edges(
    "Bull Researcher",
    self.conditional_logic.should_continue_debate,
    {
        "Bear Researcher": "Bear Researcher",
        "Research Manager": "Research Manager",
    },
)

workflow.add_edge("Research Manager", "Trader")
workflow.add_edge("Trader", "Aggressive Analyst")
...
workflow.add_edge("Portfolio Manager", END)

这里的含义是:

分析师报告不是最终答案
它们会被 Bull/Bear 研究员拿去辩论
辩论结果交给 Research Manager
Research Manager 交给 Trader
Trader 再交给风险团队
最终由 Portfolio Manager 输出最终决策

2.5 第五段代码:propagate() 真正开始运行

入口文件最后调用:

_, decision = ta.propagate("600519.SH", "2024-05-10")

位置:examples/run_ashare_full.py:45

1. propagate() 设置 ticker

文件:tradingagents/graph/trading_graph.py

位置:tradingagents/graph/trading_graph.py:266-276

def propagate(self, company_name, trade_date):
    self.ticker = company_name

    self._resolve_pending_entries(company_name)

这里:

company_name = "600519.SH"
trade_date = "2024-05-10"

虽然参数名叫 company_name,但实际传的是股票代码。A股版本通过 build_instrument_context() 强调要保留这个完整 ticker,不要把 600519.SH 改写掉。

2. _run_graph() 创建初始状态

位置:tradingagents/graph/trading_graph.py:304-311

past_context = self.memory_log.get_past_context(company_name)
init_agent_state = self.propagator.create_initial_state(
    company_name, trade_date, past_context=past_context
)
args = self.propagator.get_graph_args()

进入 tradingagents/graph/propagation.py

return {
    "messages": [("human", company_name)],
    "company_of_interest": company_name,
    "trade_date": str(trade_date),
    "past_context": past_context,
    "investment_debate_state": ...,
    "risk_debate_state": ...,
    "market_report": "",
    "fundamentals_report": "",
    "sentiment_report": "",
    "news_report": "",
}

所以初始状态是:

messages:
human: 600519.SH

company_of_interest:
600519.SH

trade_date:
2024-05-10

market_report:
""

news_report:
""

sentiment_report:
""

fundamentals_report:
""

这也解释了为什么 decision 第一条 Human Message 就是:

600519.SH

3. debug 模式下流式执行

位置:tradingagents/graph/trading_graph.py:318-326

for chunk in self.graph.stream(init_agent_state, **args):
    if len(chunk["messages"]) == 0:
        pass
    else:
        chunk["messages"][-1].pretty_print()
        trace.append(chunk)
final_state = trace[-1]

这里每一个 chunk 是图中某个节点执行后的状态片段。

因为用了 stream_mode: values,所以每次都能拿到当前状态中的 messages。pretty_print() 会把 Human / AI / Tool Message 打出来。

decision就是这个调试流的完整控制台打印。

4. 运行结束后保存状态并提取信号

位置:tradingagents/graph/trading_graph.py:330-349

self.curr_state = final_state

self._log_state(trade_date, final_state)

self.memory_log.store_decision(
ticker=company_name,
trade_date=trade_date,
final_trade_decision=final_state["final_trade_decision"],
)

return final_state, self.process_signal(final_state["final_trade_decision"])

这里有三个动作:

1. 保存 final_state 到 self.curr_state
2. 写 full_states_log_2024-05-10.json
3. 把 final_trade_decision 写入 memory log
4. 调 process_signal() 提取最终评级

process_signal() 调的是:

return self.signal_processor.process_signal(full_signal)

SignalProcessor 里:

return parse_rating(full_signal)

也就是说,最终打印的 decision 不是完整的 Portfolio Manager 长文本,而是从里面解析出的评级。

最终输出是:Hold

这说明 parse_rating()final_trade_decision 里解析出了 Hold

2.6 第六段代码:工具如何路由到 A股版本

这是 A股版本最关键的一段。

以 Market Analyst 的 get_stock_data 为例。

1. Agent 调用的是抽象工具

文件:tradingagents/agents/utils/core_stock_tools.py

@tool
def get_stock_data(symbol, start_date, end_date) -> str:
    return route_to_vendor("get_stock_data", symbol, start_date, end_date)

也就是说,Agent 只知道:

我要调用 get_stock_data

它不知道底层是东方财富、AkShare、yfinance 还是 Alpha Vantage。

2. route_to_vendor() 读取当前配置

文件:tradingagents/dataflows/interface.py

核心逻辑是:

category = get_category_for_method(method)
runtime_config = get_config()
vendor_config = get_vendor(category, method)
primary_vendors = [v.strip() for v in vendor_config.split(',')]

对于:

route_to_vendor("get_stock_data", "600519.SH", "2024-02-10", "2024-05-10")

它先找到:

method = get_stock_data
category = core_stock_apis

然后读取:

config["data_vendors"]["core_stock_apis"]

由于入口文件设置成:

"core_stock_apis": "a_share"

所以:

vendor_config = a_share
primary_vendors = ["a_share"]

3. VENDOR_METHODS 决定最终函数

同一个文件里有:

VENDOR_METHODS = {
    "get_stock_data": {
        "alpha_vantage": get_alpha_vantage_stock,
        "yfinance": get_YFin_data_online,
        "a_share": get_ashare_stock_data,
    },
    "get_indicators": {
        "alpha_vantage": get_alpha_vantage_indicator,
        "yfinance": get_stock_stats_indicators_window,
        "a_share": get_ashare_indicator,
    },
    ...
}

所以 A股版本的路由结果是:

get_stock_data
→ get_ashare_stock_data

get_indicators
→ get_ashare_indicator

get_news
→ get_ashare_news

get_global_news
→ get_ashare_market_news

get_social_sentiment
→ get_ashare_social_sentiment

get_fundamentals
→ get_ashare_fundamentals

并且 route_to_vendor() 里还有一个 A股版本专门处理:

if vendor == "a_share" and "config" not in kwargs:
    kwargs = dict(kwargs)
    kwargs["config"] = runtime_config

这一步非常重要。它把完整运行配置传给 a_share.py,所以 a_share.py 能读到:

adjust = qfq
retry_times = 2
cache_dir = data/cache/a_share
nearby_cache_max_days = 30
allow_mock = False

2.7 第七段代码:Market Analyst 为什么会先取行情再取指标

文件:tradingagents/agents/analysts/market_analyst.py

核心 prompt 有一条硬规则:

Always call get_stock_data first, then call get_indicators with exact indicator names from the list above.

并且支持指标列表包括:

close_50_sma
close_200_sma
close_10_ema
macd
macds
macdh
rsi
boll
boll_ub
boll_lb
atr
vwma

这解释了 decision 里 Market Analyst 的行为:

1. get_stock_data
2. get_indicators(close_50_sma)
3. get_indicators(close_200_sma)
4. get_indicators(close_10_ema)
5. get_indicators(macd)
6. get_indicators(rsi)
7. get_indicators(boll)
8. get_indicators(atr)
9. get_indicators(vwma)
10. 生成 market_report

运行输出正是按照这个顺序。

2.8 第八段代码:A股行情数据怎么取

真正的数据函数在:

tradingagents/dataflows/a_share.py

核心是:

get_ashare_stock_data() → get_price_df_with_fallback()

get_price_df_with_fallback() 的在线源顺序是:

online_sources = [
    ("akshare_eastmoney", "eastmoney_error", lambda: fetch_price_from_eastmoney(...)),
    ("akshare_sina", "sina_error", lambda: fetch_price_from_sina(...)),
    ("akshare_tencent", "tencent_error", lambda: fetch_price_from_tencent(...)),
]

如果在线源成功:

write_csv_cache(df, cache_path)
meta["data_status"] = "OK"
meta["data_source"] = source_name
meta["can_use_for_decision"] = True
return df, meta

如果三个在线源都失败:

先查 exact_cache
再查 nearby_cache
最后返回 DATA_UNAVAILABLE

这个逻辑是“东方财富 -> 新浪 -> 腾讯 -> 精确缓存 -> 附近日期缓存”

实际运行中,get_stock_data 走到了:

DATA_SOURCE: akshare_eastmoney

说明东方财富接口成功了。

但技术指标多次走到了:

DATA_SOURCE: akshare_sina

说明在那些指标请求对应的日期区间内,东方财富接口可能失败或被跳过,fallback 到新浪成功。

2.9 第九段代码:News / Social / Fundamentals 的真实执行

1. News Analyst

News Analyst 工具有:

tools = [get_news, get_global_news]

prompt 要求:

公司新闻用 get_news
市场和政策背景用 get_global_news

运行结果里:

get_news → DATA_UNAVAILABLE,KeyError: '600519'
get_global_news → DATA_STATUS: OK,DATA_SOURCE: akshare_tencent,SYMBOL: 000300.SH

这说明公司新闻接口没有拿到有效数据,但市场背景用沪深 300 指数补上了。

A股版本的 get_global_news 实际不是传统意义上的“全球新闻”,而是通过:

get_ashare_market_news → get_ashare_index_data("000300.SH", ...)

给 News Analyst 提供 A 股市场背景。

2. Social Analyst

Social Analyst 工具有:

tools = [get_social_sentiment, get_news]

prompt 要求先调用:

get_social_sentiment

再用新闻交叉验证情绪来源。

运行输出里确实出现:

Name: get_social_sentiment

DATA_STATUS: OK
DATA_SOURCE: akshare_sina
SYMBOL: 600519.SH
情绪方向: neutral
情绪强度: 0.45

这说明 A股版本 Social Analyst 已经不是单纯新闻工具,而是接上了get_ashare_social_sentiment

3. Fundamentals Analyst

Fundamentals Analyst 工具有:

tools = [
    get_fundamentals,
    get_balance_sheet,
    get_cashflow,
    get_income_statement,
]

真实输出中:

get_fundamentals
→ DATA_STATUS: OK
→ DATA_SOURCE: akshare_multi_interface
→ REPORT_PERIOD: 20240331
→ MISSING_FIELDS: 无

并返回 PE、PB、ROE、EPS、营收、净利润、毛利率、资产负债率、经营现金流等字段。

而:

get_balance_sheet
get_cashflow
get_income_statement

返回的是:

DATA_UNAVAILABLE
第一版暂未单独提供 A 股资产负债表 / 现金流 / 利润表明细接口
请优先参考 fundamentals_report

这说明 A股版本当前真正的基本面核心是:

get_ashare_fundamentals()

而不是三个单独财务报表工具。

2.10 主干代码的核心结论

到这里,我们已经把主干代码串起来了:

examples/run_ashare_full.py
负责配置 A股版本运行参数

TradingAgentsGraph.__init__()
负责创建 LLM、工具节点、条件逻辑和图结构

GraphSetup.setup_graph()
负责把分析师、工具、研究员、交易员、风控和组合经理连接成 LangGraph

propagate()
负责创建初始状态、流式执行图、保存状态、提取最终评级

agent utils 工具函数
负责把 get_stock_data 等抽象工具转交给 route_to_vendor

route_to_vendor()
负责根据 data_vendors 把工具调用路由到 a_share.py

a_share.py
负责真正获取 A 股行情、指标、新闻、情绪和基本面数据

decision
验证了实际执行顺序和源码设计一致

最重要的一句话是:

A股版本的核心不是重写多智能体框架,而是通过 data_vendors = a_share,把原始 TradingAgents 的抽象工具层接到了 a_share.py

3. A股版本数据层核心:a_share.py

下面进入 A股版本数据层核心:tradingagents/dataflows/a_share.py

这一层是 A股版本和原始 TradingAgents 差异最大的地方。前面我们已经讲过,run_ashare_full.py 通过 data_vendors = a_share 把原始工具层转到 A 股实现;现在要看的就是:这些 A 股实现到底怎样取数据、怎样 fallback、怎样格式化给 Agent 使用。

3.1 a_share.py 的整体认知

一句话概括:

a_share.py 是 A股版本的数据供应商模块,它负责把 TradingAgents 的标准数据请求转换成 A 股可用的数据报告。

它不负责多智能体决策,也不负责图执行。它只负责一件事:

Agent 想要数据

工具层把请求路由到 a_share.py

a_share.py 获取、清洗、兜底、格式化 A 股数据

返回文本报告给 Agent 阅读

A股版本新增了 tradingagents/dataflows/a_share.py 作为 A 股数据 vendor,并且 A 股行情采用 AkShare 多源 fallback,基本面采用多接口字段级合并。

3.2 a_share.py 在项目中的位置

它处在这个位置:

TradingAgentsGraph

Analyst Agent

标准工具函数

route_to_vendor()

a_share.py

AkShare / cache / fallback / 格式化报告

所以可以把它理解成:

不是 Agent
不是工具入口
不是 LangGraph 节点
而是 A 股 vendor 实现

例如:

Market Analyst 调 get_stock_data
→ route_to_vendor 发现 core_stock_apis = a_share
→ 进入 a_share.py 的 get_ashare_stock_data

Fundamentals Analyst 调 get_fundamentals
→ route_to_vendor 发现 fundamental_data = a_share
→ 进入 a_share.py 的 get_ashare_fundamentals

A 股模式下,Market、News、Social、Fundamentals 四类 Agent 使用的工具最终都会落到 a_share.py 对应函数上。

3.3 a_share.py 内部可以分成六个功能区

从项目理解角度看,不需要记每个函数,只需要知道它大体分成六块。

1. 代码和日期标准化
2. 缓存和配置管理
3. 行情数据获取与 fallback
4. 技术指标计算
5. 新闻、市场背景、情绪数据
6. 基本面多接口字段级合并

下面按这六块讲。

第一块:代码和日期标准化

A 股数据接口很麻烦的一点是:同一只股票,不同数据源要求的代码格式不同。

内部统一格式是:

600519.SH
000001.SZ
300750.SZ

但不同 AkShare 接口需要不同格式:

东方财富接口:600519
新浪接口:sh600519
腾讯接口:sh600519
东方财富财报接口:SH600519
雪球相关接口:SH600519

所以 a_share.py 第一件事就是把输入代码标准化,再按目标接口转换。

比如用户或脚本传入:600519.SH

模块内部会根据需要转换成:

600519
sh600519
SH600519

这一层的意义是:Agent 和工具层不用关心 A 股代码格式差异。

Agent 只传:600519.SH

剩下由 a_share.py 自己适配。

第二块:缓存和配置管理

A股版本有专门缓存目录:

data/cache/a_share/prices
data/cache/a_share/news
data/cache/a_share/social
data/cache/a_share/fundamentals
data/cache/a_share/indices

这说明 A股版本的数据缓存不是随便混在原始美股数据缓存里,而是单独放在 a_share 下。

run_ashare_full.py 里设置了:

adjust = qfq
use_cache = True
retry_times = 2
retry_sleep_seconds = 2
nearby_cache_max_days = 30
allow_mock = False

a_share.py 会读取这些配置。

这几个配置决定了数据层行为:

配置 作用
adjust = qfq 行情使用前复权
use_cache = True 允许使用本地缓存
retry_times = 2 在线接口失败时重试
nearby_cache_max_days = 30 允许查找 30 天内附近缓存
allow_mock = False 禁止生成假数据

这体现了 A股版本的一个重要原则:

宁愿明确告诉 Agent 数据不可用
也不生成假行情、假新闻、假基本面

A股版本行情优先在线拉取,成功后再缓存;获取失败时尽量回退到真实缓存;不再生成假行情数据。

第三块:行情数据获取与 fallback

这是 a_share.py 最核心的一块。

Market Analyst 调用:get_stock_data

最终会进入:get_ashare_stock_data

它背后的核心流程是:

请求 A 股行情

尝试东方财富
↓ 失败
尝试新浪
↓ 失败
尝试腾讯
↓ 失败
尝试精确缓存
↓ 失败
尝试附近日期缓存
↓ 失败
返回 DATA_UNAVAILABLE

源码中的 get_price_df_with_fallback() 明确按 akshare_eastmoneyakshare_sinaakshare_tencent 三个在线源依次尝试;成功后写入缓存并标记 DATA_STATUS = OKCAN_USE_FOR_DECISION = true;如果在线源失败,会继续查精确缓存和附近日期缓存。

1. 为什么要多源 fallback

A 股数据源经常出现这些情况:

某个接口临时不可用
某个接口字段变化
某个接口对日期区间有限制
某个 AkShare 版本缺少腾讯接口
网络连接不稳定

所以 A股版本不是只依赖一个接口,而是:

东方财富优先
新浪兜底
腾讯再兜底
缓存最后兜底

这样可以显著提高完整流程跑通的概率。

运行结果也验证了这种设计:行情主数据来自 akshare_eastmoney,但技术指标使用的历史行情多次来自 akshare_sina,说明不同阶段实际命中了不同数据源。

2. DATA_STATUSCAN_USE_FOR_DECISION 很关键

a_share.py 返回给 Agent 的不是简单数据表,而是带状态的数据报告。

例如:

DATA_STATUS: OK
DATA_SOURCE: akshare_eastmoney
CAN_USE_FOR_DECISION: true

或者:

DATA_STATUS: NEARBY_CACHE
DATA_SOURCE: nearby_cache
CAN_USE_FOR_DECISION: false
WARNING: 使用附近日期缓存,仅供历史参考,不代表目标日期最新行情。

附近缓存虽然能让 Agent 看到一些历史数据,但会明确标记:

CAN_USE_FOR_DECISION: false

这点非常重要。它防止 Agent 把“非目标日期数据”当成可靠决策依据。源码里附近缓存命中时明确把 can_use_for_decision 设为 False,并附带 warning。

3. 行情返回给 Agent 的形式

get_ashare_stock_data 最终返回的不是 DataFrame,而是一段文本报告,里面包括:

数据状态
数据来源
股票代码
请求日期区间
实际数据区间
是否可用于决策
区间起始收盘价
区间结束收盘价
区间涨跌幅
平均成交量
平均换手率
最大单日涨跌幅
最近 10 行行情表

源码中 get_ashare_stock_data 会组织这些字段,并把最近 10 行行情转换成 markdown 表格。

这说明它的目标不是给程序继续做量化回测,而是给 LLM 提供一份可读、可解释、带来源和可信度标记的数据摘要。

第四块:技术指标计算

Market Analyst 不只取行情,还会取技术指标。

标准工具是:get_indicators

A股版本实际进入:get_ashare_indicator

它的思路是:

先取一段历史行情

在本地用 pandas / numpy 计算指标

返回最近 10 行指标值

也就是说,A股版本不是从外部接口单独下载 MACD、RSI、布林带,而是基于行情数据自己算。

源码中 _enrich_indicators() 会计算 MA、收益率、波动率、量比、RSI、MACD、布林带等指标。

1. 技术指标在项目里的作用

这些指标主要服务 Market Analyst,让它生成:

趋势判断
动量判断
波动判断
成交量判断
短期回调风险判断

decision中 Market Analyst 就是基于这些指标写出了:

均线分析
MACD 分析
RSI 分析
波动率分析
成交量分析
最终 HOLD 建议

2. 指标别名兼容原始 TradingAgents

原始 TradingAgents 的 Market Analyst 会请求类似:

close_50_sma
close_200_sma
close_10_ema
macd
rsi
boll
atr
vwma

A股版本用别名表把这些名字映射到自己计算的指标。

例如:

macd -> MACD
rsi -> RSI_14
atr -> Volatility_20
vwma -> Volume_Ratio_5_20

源码里 get_ashare_indicator 会先把原始指标名映射成 A 股内部指标名,再返回最新指标值和最近 10 行数据。

这里有一个后面可以优化的点:close_50_sma 当前映射到 MA20close_200_sma 当前映射到 MA60,这是一种兼容性处理,但语义并不完全一致。它不会导致程序崩溃,但会让报告里出现“MA20 被解释为 50 日均线”这类表达偏差。

第五块:新闻、市场背景和情绪

这一块服务 News Analyst 和 Social Analyst。

1. 个股新闻:get_ashare_news

News Analyst 调用:get_news

A股版本进入:get_ashare_news

它会尝试从 AkShare 获取:

个股公告
个股新闻

然后整理成:

日期
标题
来源
链接
类型

如果取不到,就返回 DATA_UNAVAILABLE,不会编造新闻。

运行结果中,个股新闻没有成功获取,返回了:

DATA_UNAVAILABLE
WARNING: 未获取到真实新闻公告。KeyError: '600519'

这说明 A股版本的数据原则被严格执行了:没有真实新闻就明确告诉 Agent 不可用。

2. 市场背景:get_ashare_market_news

标准工具名是:get_global_news

但在 A股版本里,它不是传统的“全球新闻”,而是更像:A 股大盘环境摘要

它主要通过沪深 300 指数数据来提供市场背景。

源码中 get_ashare_index_data 会取指数行情,并返回指数名称、区间涨跌幅和最近行情表;指数数据当前主要通过腾讯历史行情接口获取。

运行结果里也能看到:

SYMBOL: 000300.SH
指数名称: 沪深300
DATA_SOURCE: akshare_tencent

所以这里要理解成:

原始工具名叫 get_global_news
A股版本实际提供的是 A股市场背景

3. 情绪:get_ashare_social_sentiment

Social Analyst 调用:get_social_sentiment

A股版本进入:get_ashare_social_sentiment

这一版主要基于真实行情衍生指标生成情绪摘要,不依赖伪造股吧/雪球数据。

它的逻辑可以理解成:

先取行情

计算近 5 日收益、量比、换手率、振幅

根据价格和量能判断情绪方向

返回 positive / negative / neutral

这不是严格的社交媒体情绪,而是“市场行为情绪”。

优点是:

真实
可解释
不伪造
与行情一致

限制是:

不代表股吧、雪球、新闻评论等真实舆论
短窗口下有些指标可能为空

运行结果中,因为实际数据窗口只有 2024-05-06 到 2024-05-10,近 5 日收益和 5/20 量比不足以稳定计算,所以最后返回了中性情绪。

第六块:基本面多接口字段级合并

这是 a_share.py 中最有价值、也最体现 A股版本改造特点的一块。

Fundamentals Analyst 调用:get_fundamentals

A股版本进入:get_ashare_fundamentals

A 股基本面改成了多接口字段级合并,主要来源包括财务摘要、财务指标、资产负债表、现金流量表、利润表、个股信息等多个 AkShare 接口。

1. 为什么基本面要多接口合并

A 股基本面数据不像美股那样可以相对稳定地从一两个接口拿全。

不同字段分散在不同接口里:

股票名称、行业、地区、上市日期
可能来自个股资料接口

PE、PB、市值
可能来自实时行情或雪球接口

ROE、毛利率、净利率、资产负债率
可能来自财务摘要接口

营收、净利润、EPS
可能来自利润表接口

总资产、总负债、净资产
可能来自资产负债表接口

经营现金流
可能来自现金流量表接口

所以 A股版本不是问一个接口“把基本面都给我”,而是:

多个接口都试一遍
每个字段从最合适的来源里取
最后合成一张基本面摘要表

2. 字段级合并的结果是什么

它最终给 Fundamentals Analyst 的不是原始财报大表,而是一张投研摘要表,例如:

股票名称
行业
地区
上市日期
PE
PB
总市值
ROE
EPS
营收
净利润
毛利率
净利率
资产负债率
流动比率
经营现金流
营收同比
净利润同比
总资产
总负债
净资产
财务摘要

实际输出中,get_fundamentals 成功返回:

DATA_STATUS: OK
DATA_SOURCE: akshare_multi_interface
REPORT_PERIOD: 20240331
MISSING_FIELDS: 无
CAN_USE_FOR_DECISION: true

并且每个字段后面都有来源,例如 PE 来自 stock_individual_spot_xq,营收和净利润来自 stock_profit_sheet_by_report_em,总资产和总负债来自 stock_balance_sheet_by_report_em

这说明 A股版本的基本面模块工作得比较完整。

3. 它返回的不只是数值,还有可信度信息

基本面结果会包含:

DATA_STATUS
DATA_SOURCE
SYMBOL
REPORT_PERIOD
DATA_SOURCES
MISSING_FIELDS
ERRORS
CAN_USE_FOR_DECISION
字段表格

源码中基本面结果会根据可用字段数量判断 DATA_UNAVAILABLEOKPARTIAL,并把字段、数值和来源整理成 markdown 表格返回。

这对 LLM 很重要。因为它不仅知道“数值是多少”,还知道:

哪些字段缺失
哪些接口失败
哪些字段来自哪个来源
这份数据能不能用于决策

4. 三张明细财报目前是占位

虽然 Fundamentals Analyst 会调用:

get_balance_sheet
get_cashflow
get_income_statement

但 A股版本目前这三个函数只是占位,会返回:DATA_UNAVAILABLE
说明:第一版暂未单独提供 A 股资产负债表 / 现金流 / 利润表明细接口,请优先参考 fundamentals_report。

源码里这三个函数明确返回 DATA_UNAVAILABLE,并提示优先参考 fundamentals_report

所以当前阶段要记住:

A股版本基本面核心 = get_ashare_fundamentals
不是三张完整财报明细

3.4 a_share.py 返回给 Agent 的统一格式

虽然不同数据类型逻辑不同,但 a_share.py 有一个很统一的输出风格:

DATA_STATUS
DATA_SOURCE
SYMBOL
REQUESTED_RANGE / REPORT_PERIOD
ACTUAL_RANGE
CAN_USE_FOR_DECISION
WARNING / ERRORS
markdown 表格或摘要

这个格式的作用是让 Agent 不只是看到数据,还看到数据质量。

例如:

行情 OK,可以用于决策
新闻不可用,不能用于决策
情绪是基于行情衍生,不是社交媒体真实评论
基本面字段完整,可以用于决策
附近缓存只供参考,不能用于决策

这对多智能体决策很关键,因为后面的 Bull / Bear / Trader / Risk Analyst 都会基于这些报告继续推理。

3.5 a_share.py 和原始 TradingAgents 的关系

原始 TradingAgents 的数据源偏美股:

yfinance
alpha_vantage
Finnhub / Reddit / Google News 等

A股版本不是把这些全部删除,而是在 vendor 层新增了:a_share

不删除原版美股逻辑,也不绕过 TradingAgentsGraph

所以整体关系是:

原始 TradingAgents:
Agent 图 + 工具抽象 + 美股 vendor

A股版本:
Agent 图 + 工具抽象 + 美股 vendor + a_share vendor

这使得项目可以根据配置切换:

美股模式 → yfinance / alpha_vantage

A 股模式 → a_share.py

3.6 用一张图总结 a_share.py

a_share.py

├─ 股票代码 / 日期标准化
│ └─ 统一 600519.SH,并转换为各接口格式

├─ 配置 / 缓存管理
│ └─ cache_dir、qfq、retry、nearby cache、allow_mock

├─ 行情模块
│ └─ 东方财富 → 新浪 → 腾讯 → 精确缓存 → 附近缓存

├─ 技术指标模块
│ └─ 基于行情计算 MA、MACD、RSI、布林带、量比、波动率

├─ 新闻 / 市场背景模块
│ ├─ 个股新闻公告
│ └─ 沪深300指数作为 A 股市场背景

├─ 情绪模块
│ └─ 基于价格、量能、换手率、振幅生成市场行为情绪

└─ 基本面模块
└─ 多 AkShare 接口字段级合并,生成 fundamentals_report

3.7 这一层需要形成的核心认知

不需要记住 a_share.py 每个函数怎么写,只需要记住这几个结论:

1. a_share.py 是 A股版本的数据 vendor,不是 Agent,也不是图执行器。

2. 它接收 route_to_vendor 转来的标准工具请求。

3. 它负责把 A 股代码、日期、接口格式、缓存路径统一处理好。

4. 行情模块最重要的是多源 fallback:
东方财富 → 新浪 → 腾讯 → 精确缓存 → 附近缓存。

5. 技术指标不是外部接口返回,而是基于行情本地计算。

6. 新闻模块拿不到真实新闻时会返回 DATA_UNAVAILABLE,不会编造。

7. Social 情绪是行情衍生情绪,不是伪造社交媒体情绪。

8. 基本面是多接口字段级合并,这是 A股版本最重要的数据工程改造之一。

9. 所有结果都会带 DATA_STATUS、DATA_SOURCE、CAN_USE_FOR_DECISION,帮助 Agent 判断数据可信度。

10. A股版本通过 a_share.py 接入 A 股数据,同时保留原始 TradingAgents 的美股 vendor 和多智能体图。

所以,a_share.py 在整个项目里的意义就是:

它让原始 TradingAgents 的“智能体大脑”能够读懂 A 股数据。

4.工具路由层的整体认知

上一阶段我们讲的是:a_share.py = A股版本的数据供应商

这一阶段要讲的是:interface.py + agents/utils/*.py = 把 Agent 的工具请求路由到正确数据供应商

它处在项目中间层:

Agent

工具函数 get_stock_data / get_indicators / get_news / get_fundamentals

route_to_vendor()

根据 config["data_vendors"] 选择供应商

a_share.py / yfinance / alpha_vantage

所以它的作用不是取数据,而是决定谁来取数据

4.1 为什么需要工具路由层

原始 TradingAgents 面向美股,数据源主要是:

yfinance
alpha_vantage

A股版本新增了:

a_share

但项目不能因为支持 A 股就把所有 Agent 都重写一遍。否则 Market Analyst、News Analyst、Fundamentals Analyst 都要重新改,维护成本很高。

所以 A股版本采用的是一种更干净的设计:

Agent 仍然调用原来的工具名
底层根据配置决定用哪个 vendor 实现

例如 Market Analyst 仍然只知道:

get_stock_data
get_indicators

它不需要知道后面到底是:

yfinance
alpha_vantage
AkShare 东方财富
AkShare 新浪
AkShare 腾讯

A股版本只是在配置里把四类数据 vendor 改成了 a_share

config["data_vendors"] = {
    "core_stock_apis": "a_share",
    "technical_indicators": "a_share",
    "fundamental_data": "a_share",
    "news_data": "a_share",
}

这个配置在 run_ashare_full.py 里已经明确设置。

4.2 工具路由层的三层结构

这一层可以拆成三层理解。

第 1 层:Agent 工具
第 2 层:route_to_vendor 路由器
第 3 层:vendor 实现函数

第 1 层:Agent 工具

Agent 看到的是这些工具:

get_stock_data
get_indicators
get_news
get_global_news
get_social_sentiment
get_fundamentals
get_balance_sheet
get_cashflow
get_income_statement

这些工具是给 LLM 用的“标准接口”。

比如 Market Analyst 不会直接调用:get_ashare_stock_data

它调用的是:get_stock_data

News Analyst 不会直接调用:get_ashare_news

它调用的是:get_news

Fundamentals Analyst 不会直接调用:get_ashare_fundamentals

它调用的是:get_fundamentals

第 2 层:route_to_vendor()

这些工具本身不真正取数据,它们会把请求交给:route_to_vendor()

可以把 route_to_vendor() 理解成一个“数据供应商调度器”。

它主要做三件事:

1. 判断当前调用属于哪类数据
2. 读取 config["data_vendors"] 里的供应商配置
3. 调用对应 vendor 的具体实现函数

比如:

get_stock_data
→ 属于 core_stock_apis
→ 当前配置 core_stock_apis = a_share
→ 调用 get_ashare_stock_data

再比如:

get_indicators
→ 属于 technical_indicators
→ 当前配置 technical_indicators = a_share
→ 调用 get_ashare_indicator

这就是为什么 A股版本只要改配置,就能让原本的 Agent 工具走到 A 股数据实现。

第 3 层:vendor 实现函数

真正干活的是 vendor 函数。

在 A股版本里,核心对应关系是:

Agent 工具 A股版本实际函数
get_stock_data get_ashare_stock_data
get_indicators get_ashare_indicator
get_news get_ashare_news
get_global_news get_ashare_market_news
get_social_sentiment get_ashare_social_sentiment
get_fundamentals get_ashare_fundamentals
get_balance_sheet get_ashare_balance_sheet
get_cashflow get_ashare_cashflow
get_income_statement get_ashare_income_statement

这张表就是 A股版本数据层和 Agent 工具层之间的桥。

4.3 这套路由机制的关键好处

4.3.1 保留原始 TradingAgents 的 Agent 设计

A股版本没有让 Market Analyst 学会“东方财富接口怎么调”,也没有让 Fundamentals Analyst 学会“AkShare 财报字段怎么合并”。

Agent 只负责分析。

数据层负责取数。

路由层负责分发。

这让整个项目结构比较清晰:

Agent:我要什么数据
Tool:标准工具名
Router:找哪个 vendor
Vendor:具体怎么取数据

4.3.2 美股和 A 股可以共存

A股版本不删除原版美股逻辑,也不绕过 TradingAgentsGraph

这意味着:

如果 data_vendors 配成 alpha_vantage / yfinance
→ 走原始美股流程

如果 data_vendors 配成 a_share
→ 走 A 股流程

A股版本不是把原始 TradingAgents 改成只能分析 A 股,而是在原来的 vendor 体系里新增了一个供应商。

这也是为什么 CLI 里可以选择 A Share / QuantAgentLab,并在 A 股模式下自动把四类 vendor 切到 a_share

4.3.3 Agent 的 prompt 和工具调用可以尽量复用

原始 TradingAgents 的 Agent prompt 大体还能保留。

比如 Market Analyst 依然可以说:

先调用 get_stock_data
再调用 get_indicators

A股版本只需要保证:

get_stock_data → A 股行情
get_indicators → A 股技术指标

这样原版多智能体结构就能继续使用。

实际输出也证明了这一点:运行时 Market Analyst 先调用 get_stock_data,再调用多次 get_indicators;工具返回的数据源已经变成了 akshare_eastmoneyakshare_sina

4.4 结合 output.txt 看真实路由过程

从运行结果看,工具路由是这样发生的。

4.4.1 Market Analyst 阶段

Market Analyst 发起:get_stock_data

路由后进入:get_ashare_stock_data

最终取到:

DATA_SOURCE: akshare_eastmoney

说明这次行情数据由 A股版本的 AkShare 东方财富接口返回。

然后 Market Analyst 发起多次:get_indicators

路由后进入:get_ashare_indicator

实际返回中可以看到:

DATA_SOURCE: akshare_sina
指标名称: close_50_sma -> MA20

说明技术指标也是通过 A股版本取到行情后计算出来的,只是这次指标行情数据来自新浪接口。

4.4.2 News Analyst 阶段

News Analyst 发起:

get_news
get_global_news

在 A股版本中:

get_news
→ get_ashare_news

get_global_news
→ get_ashare_market_news

decision输出里,公司新闻 get_news 返回了:

DATA_UNAVAILABLE
WARNING: 未获取到真实新闻公告。KeyError: '600519'

get_global_news 返回了:

SYMBOL: 000300.SH
指数名称: 沪深300
DATA_SOURCE: akshare_tencent

这说明:个股新闻没有取到,但市场背景通过沪深 300 指数补上了。

4.4.3 Social Analyst 阶段

Social Analyst 发起:

get_social_sentiment

在 A股版本中:

get_social_sentiment
→ get_ashare_social_sentiment

输出里显示:

情绪方向: neutral
情绪强度: 0.45
DATA_SOURCE: akshare_sina

Social Analyst 第一版主要基于真实行情衍生指标生成情绪摘要,不依赖伪造股吧/雪球数据。

4.4.4 Fundamentals Analyst 阶段

Fundamentals Analyst 发起:

get_fundamentals
get_balance_sheet
get_cashflow
get_income_statement

在 A股版本中:

get_fundamentals
→ get_ashare_fundamentals

get_balance_sheet
→ get_ashare_balance_sheet

get_cashflow
→ get_ashare_cashflow

get_income_statement
→ get_ashare_income_statement

其中最核心的是 get_ashare_fundamentals,它做多接口字段级合并;A 股基本面主要来源包括财务摘要、财务指标、资产负债表、现金流量表、利润表、个股资料等多个 AkShare 接口。

4.5 这一层在项目中的意义

工具路由层是 A股版本最重要的“兼容层”。

如果没有这一层,你要支持 A 股,大概率只能硬改每个 Agent:

Market Analyst 改成直接调 AkShare
News Analyst 改成直接调 AkShare
Fundamentals Analyst 改成直接调 AkShare
Social Analyst 改成直接调行情衍生情绪

这样项目会变得很混乱。

但现在的结构是:

Agent 不变
工具名基本不变
图结构基本不变
只通过 vendor 配置切换数据源

所以整体架构比较干净:

原始 TradingAgents 的智能体框架
+
A股版本的数据 vendor
+
route_to_vendor 路由机制
=
可分析 A 股的 TradingAgents

这就是 A股版本“最小改动”的核心工程思想。

4.6 到目前为止,项目主流程已经可以完整串起来

现在你可以这样理解整个项目:

run_ashare_full.py
负责指定:A 股、GLM、中文、a_share vendor、分析标的和日期

TradingAgentsGraph
负责创建:多智能体图、LLM、工具节点、状态流转

Agent
负责思考:我现在需要什么数据、我要生成什么报告

工具函数
负责暴露标准接口:get_stock_data、get_news、get_fundamentals 等

route_to_vendor
负责判断:当前应该用 yfinance、alpha_vantage 还是 a_share

a_share.py
负责执行:AkShare 调用、缓存 fallback、指标计算、基本面合并

Researcher / Trader / Risk / Portfolio Manager
负责决策:多空讨论、交易计划、风险评估、最终 HOLD/BUY/SELL

到这里,你已经有了三个关键模块的整体认识:

1. run_ashare_full.py:启动器
2. a_share.py:A 股数据供应商
3. interface.py / tools:工具路由层

5. TradingAgentsGraph + GraphSetup 图执行层

这一层解决的问题是:

为什么运行后会按 Market → News → Social → Fundamentals → Bull/Bear → Trader → Risk → Portfolio Manager 这个顺序走?
为什么每个 Analyst 会反复调用工具?
为什么工具调用后又回到同一个 Analyst?
为什么中间会出现 Human Message: Continue?
为什么最后只打印 Hold?

5.1 图执行层在项目里的位置

到目前为止,我们已经讲了三层:

run_ashare_full.py
负责启动 A股版本

工具路由层
负责把 get_stock_data / get_news 等工具路由到 a_share.py

a_share.py
负责真实获取 A 股数据

现在进入的是更上层:

TradingAgentsGraph + GraphSetup
负责组织所有 Agent 的执行顺序

它可以理解成整个项目的“导演”。

数据层负责给数据
Agent 负责分析和判断
Graph 负责安排谁先说、谁后说、什么时候调用工具、什么时候进入下一阶段

A股版本没有绕过原始 TradingAgents 的图结构。README 里也说明,A股版本保留原有 Agent 图、CLI、状态流转、Bull/Bear Researcher、Trader、Risk Management、Portfolio Manager。

5.2 入口脚本怎样启动图

run_ashare_full.py 中真正启动图的是这段:

ta = TradingAgentsGraph(
    selected_analysts=["market", "news", "social", "fundamentals"],
    debug=True,
    config=config,
)

_, decision = ta.propagate("600519.SH", "2024-05-10")
print(decision)

这里有三个关键信息:

selected_analysts = ["market", "news", "social", "fundamentals"]
debug = True
propagate("600519.SH", "2024-05-10")

也就是说,这次图执行的前半段分析师顺序是:

Market Analyst
→ News Analyst
→ Social Analyst
→ Fundamentals Analyst

这和你实际输出完全一致:先出现 get_stock_data 和多次 get_indicators,然后进入 get_news / get_global_news,再进入 get_social_sentiment,最后进入 get_fundamentals

5.3 TradingAgentsGraph 的职责

TradingAgentsGraph 不是某一个 Agent,而是整个流程的总控类。

它主要做六件事:

1. 接收 config
2. 把 config 写入全局数据配置
3. 创建 LLM
4. 创建工具节点 ToolNode
5. 创建图结构 GraphSetup
6. 执行 propagate()

可以把它理解成:

TradingAgentsGraph
= 配置管理器
+ LLM 初始化器
+ 工具节点管理器
+ LangGraph 工作流管理器
+ 最终结果处理器

在 A股版本中,TradingAgentsGraph 本身没有变成“A 股专用”。它还是原始 TradingAgents 的图执行器。A股版本的变化主要通过 configa_share vendor 注入进去。

5.4 图里有哪些节点

A股版本完整流程里有两大类节点。

第一类:分析师节点

也就是前半段:

Market Analyst
News Analyst
Social Analyst
Fundamentals Analyst

它们负责生成四份报告:

market_report
news_report
sentiment_report
fundamentals_report

每个分析师都有自己的工具:

分析师 工具
Market Analyst get_stock_data, get_indicators
News Analyst get_news, get_global_news
Social Analyst get_social_sentiment, get_news
Fundamentals Analyst get_fundamentals, get_balance_sheet, get_cashflow, get_income_statement

第二类:决策节点

也就是后半段:

Bull Researcher
Bear Researcher
Research Manager
Trader
Aggressive Risk Analyst
Conservative Risk Analyst
Neutral Risk Analyst
Portfolio Manager

它们负责从四份报告走向最终交易决策:

四份分析师报告

多空辩论

研究经理总结

交易员制定计划

风险团队评估

组合经理最终裁决

5.5 图的核心执行顺序

整体图结构可以理解成这样:

START

Market Analyst ↔ tools_market

Msg Clear Market

News Analyst ↔ tools_news

Msg Clear News

Social Analyst ↔ tools_social

Msg Clear Social

Fundamentals Analyst ↔ tools_fundamentals

Msg Clear Fundamentals

Bull Researcher ↔ Bear Researcher

Research Manager

Trader

Aggressive Risk Analyst → Conservative Risk Analyst → Neutral Risk Analyst


Portfolio Manager

END

前半段是“收集信息并生成报告”。

后半段是“围绕报告进行投资决策”。

5.6 为什么 Analyst 会反复调用工具

这是 LangGraph 图里最关键的机制。

以 Market Analyst 为例,它不是一次性完成的,而是一个循环:

Market Analyst 思考

如果需要数据,就生成 tool call

进入 tools_market

工具执行完,把结果返回给 Market Analyst

Market Analyst 继续思考

如果还需要指标,再生成 tool call

再次进入 tools_market

直到不再调用工具

生成 market_report

进入下一个 Analyst

所以你的输出里会看到:

Market Analyst
→ get_stock_data
→ get_indicators close_50_sma
→ get_indicators close_200_sma
→ get_indicators close_10_ema
→ get_indicators macd
→ get_indicators rsi
→ get_indicators boll
→ get_indicators atr
→ get_indicators vwma
→ market_report

这不是程序重复执行出错,而是 Agent 在逐步补全它认为需要的数据。实际输出中确实先调用行情,再连续调用多个技术指标,最后才生成 market_report

5.7 tools_xxx 节点的作用

每个 Analyst 都配一个工具节点:

Market Analyst ↔ tools_market
News Analyst ↔ tools_news
Social Analyst ↔ tools_social
Fundamentals Analyst ↔ tools_fundamentals

这些工具节点本身不思考,只执行工具调用。

例如:

Market Analyst 说:
我要调用 get_stock_data

tools_market 做:
执行 get_stock_data
返回 Tool Message

Market Analyst 再读 Tool Message:
继续判断是否还要调用 get_indicators

所以工具节点像是“执行器”,而 Analyst 是“决策者”。

5.8 条件逻辑:什么时候继续工具,什么时候进入下一个 Analyst

每个 Analyst 后面都有一个判断:

如果最后一条 AI Message 里有 tool_calls
→ 去对应 tools_xxx

如果没有 tool_calls
→ 当前报告完成
→ 去 Msg Clear xxx
→ 进入下一个 Analyst

这就是为什么:

Market Analyst 会一直循环到它不再调用工具
News Analyst 会一直循环到它不再调用工具
Social Analyst 会一直循环到它不再调用工具
Fundamentals Analyst 会一直循环到它不再调用工具

本质上,图并不是写死“每个 Agent 调几次工具”。

它是让 LLM 自己决定:

我还需要数据吗?
如果需要,就调用工具。
如果不需要,就输出报告。

5.9 为什么中间会出现 Human Message: Continue

decision里看到多次:

=========================== Human Message ============================

Continue

这不是用户真的输入了 Continue

它来自 Msg Clear 节点。

每个 Analyst 完成后,系统会清理当前 messages,避免上一个 Analyst 的长对话、工具调用、工具结果污染下一个 Analyst。

但是 LangGraph / LangChain 消息流里不能完全没有消息,所以它会放一个占位消息:

Human Message: Continue

它的意义是:

上一个 Analyst 阶段结束
消息历史被清理
下一个 Agent 可以继续

所以你看到的 Continue 实际上是阶段切换标志。

输出中,market_report 之后立刻出现 Human Message: Continue,然后进入 News Analyst;这正好说明 Market 阶段已经结束并切到下一阶段。

5.10 状态对象:整个图靠什么传递信息

图里真正被传递的不是单纯字符串,而是一个状态对象。

可以理解为:AgentState

它里面有几类信息:

messages
company_of_interest
trade_date

market_report
news_report
sentiment_report
fundamentals_report

investment_debate_state
investment_plan
trader_investment_plan

risk_debate_state
final_trade_decision

past_context

这点非常重要。

因为 Msg Clear 会清掉 messages,但不会清掉这些报告字段。

也就是说:

消息历史可以清
但 market_report / news_report / sentiment_report / fundamentals_report 会保留在状态里

所以后面的 Bull Researcher、Bear Researcher、Trader、Risk Analyst 仍然能看到前面四个分析师的报告。

这也是为什么项目需要状态对象,而不是简单靠聊天记录一路传下去。

5.11 四个 Analyst 报告怎样进入后半段决策

当前半段结束时,状态里已经有四份核心报告:

market_report
news_report
sentiment_report
fundamentals_report

然后图进入:

Bull Researcher

从这里开始,系统不再主要取数据,而是开始围绕已有报告做投资判断。

5.11.1 Bull Researcher

Bull Researcher 的任务是:

站在多头视角
寻找买入、持有、看多的理由

它会倾向于关注:

基本面强项
估值合理性
趋势向好
市场情绪支撑
风险可控

5.11.2 Bear Researcher

Bear Researcher 的任务是:

站在空头视角
寻找风险、下跌、回避的理由

它会倾向于关注:

估值偏高
增长放缓
新闻缺失
情绪不足
技术面回调
宏观风险

5.11.3 多空辩论轮数

入口脚本里设置:

config["max_debate_rounds"] = 1

所以多空辩论不会很长,大致就是:

Bull 说一轮
Bear 说一轮
然后交给 Research Manager

这让完整流程更快,也让示例更容易跑完。入口脚本确实设置了 max_debate_rounds = 1max_risk_discuss_rounds = 1

5.11.4 Research Manager

Research Manager 的任务是:

综合 Bull 和 Bear 的争论
形成一个更平衡的 investment_plan

它不是简单投票,而是把多空双方观点压缩成一个研究结论。

5.12 Trader:把研究结论转成交易计划

Research Manager 之后进入 Trader。

Trader 的角色不是再做基础研究,而是回答:

基于现在这些报告和研究结论,交易上应该怎么做?

它会形成:

trader_investment_plan

通常包括:

Action: Buy / Hold / Sell
Reasoning
Position sizing
Entry / exit considerations
Risk notes

最终输出里已经可以看到这种结构:

Action: Hold
Reasoning: ...
Position Sizing: Maintain current position size - do not add or trim
FINAL TRANSACTION PROPOSAL: HOLD

5.13 风险团队:从不同风险偏好审查 Trader 计划

Trader 之后进入风险团队。

风险团队不是一个人,而是三个角色:

Aggressive Risk Analyst
Conservative Risk Analyst
Neutral Risk Analyst

它们分别代表不同风险偏好。

5.13.1 Aggressive Risk Analyst

偏激进,可能会说:

如果基本面好,风险可控,可以接受更高仓位

5.13.2 Conservative Risk Analyst

偏保守,可能会说:

新闻数据缺失、估值偏高、短期回调风险存在,不宜加仓

5.13.3 Neutral Risk Analyst

偏中性,负责平衡两边:

基本面强,但短期风险也明显,因此维持持有更合适

5.13.4 风险讨论轮数

入口脚本里设置:

config["max_risk_discuss_rounds"] = 1

所以风险讨论也不会无限循环,三个风险角色大致各说一轮后进入 Portfolio Manager。

5.14 Portfolio Manager:最终裁决

最后进入:Portfolio Manager

Portfolio Manager 拿到的信息最多,包括:

market_report
news_report
sentiment_report
fundamentals_report
investment_plan
trader_investment_plan
risk_debate_state
past_context

它的任务是输出:final_trade_decision

也就是最终交易决策文本。

在结果里,最终文本多次出现:

Action: Hold
FINAL TRANSACTION PROPOSAL: HOLD

最后 print(decision) 打印的是:

Hold

5.15 为什么最后只打印 Hold

这是因为入口脚本写的是:

_, decision = ta.propagate("600519.SH", "2024-05-10")
print(decision)

propagate() 返回两个东西:

final_state
decision

第一个是完整状态,里面包含所有报告、辩论、交易计划和最终裁决。

第二个是经过信号处理后的简化结果。

也就是说:

final_trade_decision:
一大段 Portfolio Manager 的最终说明

decision:
从最终说明中抽取出的 Buy / Hold / Sell

脚本只打印第二个,所以最终控制台最后一行是:

Hold

5.16 结合decision看完整图执行

实际运行轨迹可以这样对应源码流程:

Human Message: 600519.SH

Market Analyst

get_stock_data

get_indicators 多次

market_report

Human Message: Continue

News Analyst

get_news
get_global_news

news_report

Human Message: Continue

Social Analyst

get_social_sentiment
get_news

sentiment_report

Human Message: Continue

Fundamentals Analyst

get_fundamentals
get_balance_sheet
get_cashflow
get_income_statement

fundamentals_report

Bull / Bear / Research Manager / Trader / Risk / Portfolio Manager

FINAL TRANSACTION PROPOSAL: HOLD

print(decision)

Hold

实际输出中,Market 阶段确实先生成 market_report,之后出现 Continue 并进入新闻阶段;新闻阶段返回公司新闻不可用和沪深300市场数据;随后进入 Social 阶段,调用 get_social_sentiment;最后基本面阶段返回 akshare_multi_interface 的多接口合并结果,并输出最终 Hold

5.17 这一层和 A股版本的关系

这一层本质上不是 A 股专属。

TradingAgentsGraph + GraphSetup 是原始 TradingAgents 的核心框架。

A股版本对它的使用方式是:

保留图执行结构
保留多智能体角色
保留状态流转
保留 Bull/Bear/Trader/Risk/Portfolio Manager

只通过 config 和 a_share vendor 改变数据来源

这就是 A股版本“最小改动”的关键。

A股版本目标是让原有多智能体框架支持 A 股投研与决策,同时保留原版美股 / yfinance / alpha_vantage 流程。

5.18 用一句话总结图执行层

TradingAgentsGraph 是整个项目的流程编排器;GraphSetup 把各个 Agent 和工具节点连成 LangGraph;ConditionalLogic 决定什么时候调用工具、什么时候进入下一阶段;AgentState 保存所有报告和决策状态;最终 Portfolio Manager 输出完整决策,SignalProcessor 再把它压缩成 Hold

可以把项目主流程完整理解成:

run_ashare_full.py
配置 A 股、GLM、中文、分析师顺序和数据 vendor

TradingAgentsGraph
初始化 LLM、工具节点、状态和图结构

GraphSetup
连接 Market / News / Social / Fundamentals / Research / Trader / Risk / PM

Analyst 阶段
循环调用工具,生成四份报告

Research 阶段
Bull / Bear 辩论,Research Manager 总结

Trading 阶段
Trader 制定交易计划

Risk 阶段
三类风险角色评估

Portfolio Manager
输出最终交易决策

SignalProcessor
提取 Buy / Hold / Sell

print(decision)

6. Agent 角色层

上一阶段我们讲的是:

TradingAgentsGraph + GraphSetup
= 谁先执行、谁后执行、工具节点怎么循环、状态怎么流转

这一阶段讲的是:

每个 Agent 到底负责什么?
它读什么信息?
它调用哪些工具?
它产出什么结果?
这些结果怎样影响最终 HOLD?

6.1 Agent 角色层在整个项目中的位置

到目前为止,A股版本主流程可以分成这几层:

run_ashare_full.py

TradingAgentsGraph / GraphSetup

Agent 角色层

工具层 get_stock_data / get_news / get_fundamentals ...

route_to_vendor

a_share.py

AkShare / 缓存 / fallback / 字段合并

这一层的核心是:

Agent 不是数据接口,也不是简单函数。
Agent 是“带角色设定的 LLM 节点”。

它们根据自己的角色,决定:
1. 要调用哪些工具;
2. 怎样解读工具结果;
3. 要把什么内容写入 AgentState;
4. 后续 Agent 应该基于哪些报告继续推理。

A股版本保留了原始 TradingAgents 的 Agent 图、状态流转、Bull/Bear Researcher、Trader、Risk Management、Portfolio Manager,同时新增 A 股数据 vendor 并切换数据源。

6.2 Agent 可以分成三组

整个流程里的 Agent 可以分成三组:

第一组:信息采集型 Agent
Market Analyst
News Analyst
Social Analyst
Fundamentals Analyst

第二组:观点辩论型 Agent
Bull Researcher
Bear Researcher
Research Manager

第三组:决策审查型 Agent
Trader
Aggressive Risk Analyst
Conservative Risk Analyst
Neutral Risk Analyst
Portfolio Manager

它们的职责不是平级的。

前四个 Analyst 负责“看事实”。

中间的 Researcher 负责“形成投资观点”。

最后 Trader / Risk / Portfolio Manager 负责“转成交易动作”。

第一组:四个 Analyst

这一组是完整流程的数据基础。

它们直接调用工具,拿到 A 股行情、新闻、情绪和基本面,然后生成四份报告:

market_report
news_report
sentiment_report
fundamentals_report

这四份报告会一直保存在 AgentState 中,供后面的 Bull/Bear、Trader、Risk、Portfolio Manager 使用。

Market Analyst:市场与技术面分析师

Market Analyst 的任务是回答:

这只股票近期价格走势如何?
趋势是向上、向下还是震荡?
成交量有没有配合?
技术指标是否支持买入、持有或卖出?

它使用的工具是:

get_stock_data
get_indicators

A股版本中,这两个工具最终落到 a_share.py,主要通过东方财富、 新浪、腾讯和本地缓存获取行情数据。Market Analyst 使用 get_stock_dataget_indicators,A 股实现位于 a_share.py,主要来源包括 AkShare 东方财富、 新浪、腾讯和缓存。

在decision里,Market Analyst 的真实行为是:

先调用 get_stock_data
再连续调用多个 get_indicators
最后生成 market_report

例如它先拿到 600519.SH 的行情,数据源是 akshare_eastmoney;之后又多次调用技术指标,数据源多次是 akshare_sina

所以 Market Analyst 最终产出的是:

market_report

这份报告给后续流程提供:

价格趋势
均线位置
MACD / RSI / 波动率
成交量变化
技术面交易倾向

在这次运行里,Market Analyst 的结论偏谨慎,提出的是 HOLD 倾向。

News Analyst:新闻与市场环境分析师

News Analyst 的任务是回答:

这家公司近期有没有重大公告或新闻?
外部市场环境是否支持股价?
大盘走势、政策环境、新闻事件是否带来风险或机会?

它使用的工具是:

get_news
get_global_news

在 A股版本里:

get_news
→ 个股公告 / 个股新闻

get_global_news
→ A 股市场背景,当前主要用沪深300指数数据表示

News Analyst 使用 get_newsget_global_news,A 股实现包括 get_ashare_newsget_ashare_market_news

这次运行中,News Analyst 遇到了一个典型情况:

公司新闻:DATA_UNAVAILABLE
市场背景:可用,来自沪深300指数

最终输出里,公司新闻接口返回 DATA_UNAVAILABLE,但 get_global_news 成功返回了沪深300数据,数据源是 akshare_tencent

这说明 News Analyst 生成 news_report 时会受到两个影响:

1. 公司层面新闻不足 → 信息不完整,增加不确定性;
2. 市场整体表现可用 → 可以判断大盘背景对标的的影响。

所以这次 news_report 没有给出强烈买入信号,而是强调:

公司新闻数据不可用;
市场整体表现相对积极;
但缺乏公司层面的新闻支撑;
建议观望。

Social Analyst:情绪分析师

Social Analyst 的任务是回答:

市场对这只股票的态度是积极、消极还是中性?
有没有明显的情绪偏向?
这种情绪是否能支持交易动作?

它使用的工具主要是:

get_social_sentiment

A股版本中,Social Analyst 的情绪不是伪造股吧、雪球或社交媒体内容,而是基于真实行情衍生指标生成情绪摘要。Social Analyst 的第一版主要基于真实行情衍生指标生成情绪摘要,不依赖伪造股吧/雪球数据。

所以这里的“情绪”更准确地说是:

市场行为情绪

它主要来自:

近几日涨跌幅
量能变化
换手率
振幅

运行结果里,Social Analyst 调用了 get_social_sentiment,返回:

情绪方向: neutral
情绪强度: 0.45

并且新闻数据依旧不可用。

所以 Social Analyst 的结论是:

情绪中性偏弱;
没有明显单边看涨或看跌;
量能和新闻不足以支持激进操作。

这会强化后续的 HOLD 判断。

Fundamentals Analyst:基本面分析师

Fundamentals Analyst 的任务是回答:

公司质地如何?
盈利能力如何?
估值是否合理?
资产负债表是否稳健?
业绩增长是否支持当前价格?

它使用的工具是:

get_fundamentals
get_balance_sheet
get_cashflow
get_income_statement

Fundamentals Analyst 使用这些工具,A 股实现主要是 get_ashare_fundamentals,数据来源包括财务摘要、财务指标、资产负债表、现金流量表、利润表、个股资料等多个 AkShare 接口。

在这次运行中,真正发挥作用的是:

get_fundamentals

它返回:

DATA_STATUS: OK
DATA_SOURCE: akshare_multi_interface
REPORT_PERIOD: 20240331
MISSING_FIELDS: 无
CAN_USE_FOR_DECISION: true

这说明基本面数据质量相对较好。

而另外三个工具:

get_balance_sheet
get_cashflow
get_income_statement

返回的是 DATA_UNAVAILABLE,提示第一版暂未单独提供 A 股明细报表接口,应优先参考 fundamentals_report

所以 Fundamentals Analyst 主要基于 get_fundamentals 的多接口合并结果,得出:

贵州茅台盈利能力强;
毛利率、净利率、ROE、现金流和资产负债结构优秀;
但估值较高、增长可能放缓;
更适合持有而不是追高加仓。

四个 Analyst 报告如何共同塑造后续判断

四个 Analyst 不是各自独立结束,而是共同形成后续决策的输入。

可以把它们理解成四个视角:

报告 视角 这次运行的大致倾向
market_report 技术面 长期趋势尚可,短期有回调压力
news_report 新闻与市场环境 市场背景尚可,但公司新闻不可用
sentiment_report 市场行为情绪 中性偏弱
fundamentals_report 公司基本面 公司质量强,但估值和增长需谨慎

所以进入 Bull/Bear 阶段之前,系统已经形成一个比较清晰的局面:

基本面强;
技术面不差但短期回调;
新闻信息不足;
情绪没有明显看多;
估值不便宜。

这组输入天然更容易导向:

HOLD

而不是强烈 BUYSELL

第二组:研究员与研究经理

四个 Analyst 完成后,系统进入研究讨论阶段。

这一阶段的重点不是再取数据,而是围绕已有报告形成投资观点。

Bull Researcher:多头研究员

Bull Researcher 的任务是:

从积极角度解释这家公司为什么值得买入或持有。

它会优先放大这些信息:

基本面优秀
品牌护城河强
盈利能力强
现金流和资产结构稳健
行业龙头地位突出
长期价值仍然存在

在贵州茅台这个案例中,多头最容易抓住的是:

毛利率高
净利率高
ROE 好
品牌护城河强
资产负债率低
营收和净利润仍在增长

所以 Bull Researcher 很可能会支持:

至少不应该轻易卖出

Bear Researcher:空头研究员

Bear Researcher 的任务是:

从风险角度解释为什么不应该买入,甚至应该谨慎或卖出。

它会优先放大这些信息:

估值不低
增长放缓
短期技术面有回调压力
新闻数据缺失
市场情绪不强
宏观或消费环境压力

在这次最终输出里,也确实出现了类似风险点:

估值已经反映较多优质基本面;
增长边际放缓;
宏观环境和消费环境存在压力;
当前风险收益比不支持加仓。

最终输出明确给出了 Action: HoldFINAL TRANSACTION PROPOSAL: HOLD

Research Manager:研究经理

Bull 和 Bear 争论后,Research Manager 的作用是:

综合多空双方观点,形成更平衡的投资计划。

它不是单纯选择“多头赢”或“空头赢”,而是把双方观点压缩成:

当前最合理的投资判断是什么?

在这次案例中,Research Manager 很可能会形成这样的中间判断:

贵州茅台是高质量公司;
但短期数据不足以支持加仓;
估值和技术面带来压力;
因此倾向持有等待。

这会传给 Trader。

第三组:Trader、Risk Team、Portfolio Manager

这一组负责把研究观点转成最终交易动作。

Trader:交易员

Trader 的任务是:

把研究经理的观点转成交易计划。

它关心的是:

现在应该买、卖还是持有?
是否加仓?
是否减仓?
仓位如何处理?
短期风险如何控制?

所以 Trader 的输出通常会更接近操作语言:

Action
Reasoning
Position Sizing
FINAL TRANSACTION PROPOSAL

输出中已经能看到这种结构:

Action: Hold
Position Sizing: Maintain current position size - do not add or trim
FINAL TRANSACTION PROPOSAL: HOLD

这说明 Trader 或后续决策节点已经把研究观点转成了明确操作建议:

不加仓
不减仓
维持持有

Aggressive Risk Analyst:激进风险分析师

这个角色不是单纯“看多”,而是从激进风险偏好的角度审查交易计划。

它可能会说:

如果公司质量足够高,短期波动可以接受;
如果长期基本面强,可以适度容忍估值;
如果回调只是短期技术压力,可以继续持有。

在贵州茅台案例里,激进风险分析师可能支持继续持有,甚至在回调时关注机会。

Conservative Risk Analyst:保守风险分析师

这个角色会更强调:

估值风险
短期回调风险
信息缺失风险
宏观压力
现金流质量疑问

最终输出里出现了:

OCF-to-net profit gap
valuation already reflects much of the business quality
near-term risk/reward doesn't favor increasing exposure

这些就是偏保守风险审查会关注的问题。

Neutral Risk Analyst:中性风险分析师

中性风险分析师负责平衡激进和保守观点。

它通常会把结果推向:

既不激进买入,也不恐慌卖出

在这次案例中,最自然的平衡结果就是:

HOLD

因为:

基本面太强,不适合简单卖出;
但估值、技术和新闻不确定性又不支持积极买入。

Portfolio Manager:组合经理

Portfolio Manager 是最后一个节点。

它拿到的信息最完整:

四份 Analyst 报告
多空研究讨论
Research Manager 结论
Trader 交易计划
风险团队讨论
历史记忆 past_context

然后它输出:

final_trade_decision

这个输出通常是一段完整说明。

run_ashare_full.py 最后打印的是经过信号处理后的简化结果,所以最终输出的是:

Hold

而不是完整的 final_trade_decision。decision最后也确实是多段 FINAL TRANSACTION PROPOSAL: HOLD 后,最终打印 Hold

6.3 Agent 之间不是“接力聊天”,而是“共享状态”

这里非常重要。

表面上看,Agent 像是在一个接一个聊天:

Market 说完,News 说;
News 说完,Social 说;
Social 说完,Fundamentals 说;
然后 Bull/Bear/Trader/Risk/PM 继续。

但真实机制更像是:

每个 Agent 读 AgentState
每个 Agent 写 AgentState
后面的 Agent 继续读取前面写入的字段

也就是说,关键不是聊天记录,而是状态字段:

market_report
news_report
sentiment_report
fundamentals_report
investment_debate_state
investment_plan
trader_investment_plan
risk_debate_state
final_trade_decision

这解释了为什么中间可以清理 messages,但后面的 Agent 仍然知道前面分析结果。

因为报告已经写入状态,不依赖聊天历史本身。

6.4 A股版本中 Agent 层的关键变化

A股版本没有重写所有 Agent,但 Agent 层确实有几处适配意义。

6.4.1 数据工具变成 A 股工具

Agent 仍然调用标准工具名,但工具结果已经变成 A 股数据。

例如:

Market Analyst 仍然调用 get_stock_data
但拿到的是 600519.SH 的 A 股行情

A 股模式下会自动切换四类 vendor:core_stock_apistechnical_indicatorsfundamental_datanews_data 都会切到 a_share

6.4.2 输出语言倾向中文

A股版本默认输出中文,这让四个 Analyst 报告更适合 A 股投研语境。

decision中可以看到,Market、News、Social、Fundamentals 的报告主体都是中文。

不过最终交易决策部分仍然夹杂英文,例如:

Action: Hold
Reasoning
Position Sizing
FINAL TRANSACTION PROPOSAL

这说明部分后半段 Agent 的 prompt 或输出格式仍保留了原始 TradingAgents 的英文结构。这个不影响运行,但如果追求完整中文化,后续可以优化 Trader、Risk、Portfolio Manager 的 prompt。

6.4.3 Social Analyst 的含义发生变化

原始社交情绪分析更偏:

社交媒体
公众情绪
新闻评论
讨论热度

A股版本的 Social Analyst 当前更偏:

基于行情衍生的市场行为情绪

并且它不依赖伪造股吧/雪球数据。

这在投研上是更诚实的,但要注意命名上的差异:

它叫 Social Analyst,
但当前结果更像 Market-derived Sentiment Analyst。

6.4.4 Fundamentals Analyst 的输入质量明显增强

A股版本最扎实的改造之一是基本面多接口字段级合并。

这让 Fundamentals Analyst 不再只依赖单一接口,而是可以拿到较完整的:

估值
盈利能力
成长性
资产负债情况
现金流
财务摘要
字段来源
缺失字段
错误信息

这次 600519.SH 的基本面结果就是 DATA_STATUS: OK,且 MISSING_FIELDS: 无

所以在最终 HOLD 结论中,基本面其实是支持“不要卖出”的关键力量。

6.4.5 用 600519.SH 这次运行串起来看

这次完整 Agent 逻辑可以概括成:

Market Analyst:
技术面中长期还可以,但短期有回调压力。
→ 不支持追高买入。

News Analyst:
大盘环境还可以,但公司新闻不可用。
→ 信息不足,倾向谨慎。

Social Analyst:
市场行为情绪中性,强度不高。
→ 没有明显情绪驱动。

Fundamentals Analyst:
公司质量非常强,盈利能力和财务结构优秀。
→ 不支持轻易卖出。

Bull Researcher:
强调贵州茅台的质量、品牌和盈利能力。

Bear Researcher:
强调估值、增长放缓、宏观压力和短期风险。

Research Manager:
综合后认为更适合持有等待。

Trader:
转成交易动作:维持仓位,不加不减。

Risk Team:
审查后认为当前风险收益比不支持加仓,也不需要卖出。

Portfolio Manager:
最终裁决 HOLD。

SignalProcessor:
从最终文本中提取 Hold。

print(decision):
输出 Hold。

这就是decision中最后得到 Hold 的逻辑链条。

6.5 这一层需要形成的核心认知

可以这样理解 Agent 层:

Analyst 不是为了直接做最终决策,
而是为了生成不同维度的事实报告。

Researcher 不是为了取新数据,
而是为了围绕事实报告进行多空论证。

Trader 不是为了再分析公司,
而是为了把研究结论转成交易计划。

Risk Team 不是为了重新做投资判断,
而是为了审查 Trader 的计划是否风险合理。

Portfolio Manager 是最终裁决者,
它综合所有上游内容输出 final_trade_decision。

所以完整逻辑是:

数据 → 报告 → 观点 → 计划 → 风险审查 → 最终决策

而不是:

某一个 Agent 直接决定买卖

这是 TradingAgents 相比普通单 Agent 股票分析最大的区别。

7.状态与结果层

这一层解决的问题是:

Agent 之间到底靠什么传递信息?
为什么清理 messages 后,后面的 Agent 仍然知道前面的报告?
final_state 和 decision 有什么区别?
为什么最后 print 出来的只是 Hold?
运行日志和完整状态保存在哪里?

7.1状态层在整体流程中的位置

前面讲过:

数据层 a_share.py
负责取 A 股数据

工具路由层
负责把 get_stock_data 等工具路由到 a_share

Agent 角色层
负责生成报告、辩论、交易计划和风险判断

图执行层
负责安排执行顺序

现在的“状态与结果层”负责把这些东西串起来:

每个 Agent 的输出

写入 AgentState

后续 Agent 从 AgentState 读取

最终形成 final_state

从 final_state["final_trade_decision"] 提取 decision

print(decision)

入口脚本最后确实只保留了 propagate() 返回的第二个值,并打印它:

_, decision = ta.propagate("600519.SH", "2024-05-10")
print(decision)

这就是为什么最终控制台最后一行是简化后的 Hold,而不是完整分析报告。

7.2 AgentState 是什么

可以把 AgentState 理解成整套流程的“共享工作台”。

它里面不是只有聊天消息,而是保存了整个投研流程的关键中间结果:

基础信息:
company_of_interest
trade_date
past_context

消息:
messages

四份分析师报告:
market_report
news_report
sentiment_report
fundamentals_report

研究员阶段:
investment_debate_state
investment_plan

交易员阶段:
trader_investment_plan

风险阶段:
risk_debate_state

最终结果:
final_trade_decision

所以你可以把它看成:

AgentState = 当前这次股票分析任务的完整状态容器

它不是某个 Agent 私有的,而是在整个图里一路传递。

7.3 messages 和报告字段不是一回事

这是理解项目流程的关键。

表面上,decision中是一串聊天消息:

Human Message
Ai Message
Tool Message
Ai Message
...

但真正让后续 Agent 继续工作的,不只是 messages,而是状态字段。

例如 :

Market Analyst 完成后,它会把结果写入market_report

News Analyst 完成后写入news_report

Social Analyst 完成后写入sentiment_report

Fundamentals Analyst 完成后写入fundamentals_report

运行输出里可以看到,Market 阶段生成了 market_report,News 阶段生成了 news_report,Social 阶段生成了 sentiment_report,Fundamentals 阶段生成了基本面分析报告;这些就是后续 Bull/Bear、Trader、Risk、Portfolio Manager 的主要输入。

所以:

messages 是过程对话
report 字段是阶段成果

7.4 为什么可以清理 messages

输出中可以看到多次:

Human Message: Continue

这其实是阶段切换时的占位消息。

原因是每个 Analyst 阶段可能产生大量工具调用和工具返回,如果一直把全部 messages 带到下一个 Analyst,会出现两个问题:

1. 上下文太长,浪费 token;
2. 后一个 Analyst 可能被前一个 Analyst 的工具调用细节干扰。

所以图里有 Msg Clear MarketMsg Clear NewsMsg Clear SocialMsg Clear Fundamentals 这些清理节点。

清理的是:messages

保留的是:market_report、news_report、sentiment_report、fundamentals_report

这就是为什么清理消息不会导致信息丢失。

可以理解为:

聊天记录可以删
阶段报告不能删

7.5 初始状态怎么创建

ta.propagate("600519.SH", "2024-05-10") 开始时,系统会先创建一个初始状态。

它大致包含:

messages:
human: 600519.SH

company_of_interest:
600519.SH

trade_date:
2024-05-10

past_context:
从 memory log 里读取的历史上下文

market_report:
空字符串

news_report:
空字符串

sentiment_report:
空字符串

fundamentals_report:
空字符串

investment_debate_state:
空的多空辩论状态

risk_debate_state:
空的风险讨论状态

这解释了为什么decision开头第一条就是:

Human Message: 600519.SH

然后 Market Analyst 从这个初始状态开始工作。

7.6 每个阶段怎样更新状态

整个状态更新过程可以这样理解:

初始状态

Market Analyst 写入 market_report

News Analyst 写入 news_report

Social Analyst 写入 sentiment_report

Fundamentals Analyst 写入 fundamentals_report

Bull/Bear 写入 investment_debate_state

Research Manager 写入 investment_plan

Trader 写入 trader_investment_plan

Risk Analysts 写入 risk_debate_state

Portfolio Manager 写入 final_trade_decision

也就是说,整个项目不是“一个长 prompt 一次性生成结果”,而是一个逐步累积状态的流程。

这和普通单 Agent 分析有很大区别:

普通单 Agent:
一次性读数据,一次性输出结论

TradingAgents:
多个 Agent 分阶段更新同一个状态对象

7.7 final_state 是什么

propagate() 执行完后,第一个返回值是:final_state

它是整个流程结束时的完整状态。

里面包括:

股票代码
交易日期
四份分析师报告
多空辩论记录
研究经理结论
交易员计划
风险讨论记录
最终组合经理决策

如果你想调试或研究整套流程,final_statedecision 更有价值。

因为 decision 只是最后提取出的评级,而 final_state 包含完整过程。

入口脚本现在写的是:

_, decision = ta.propagate(...)

这表示它故意丢弃了第一个返回值。

如果要保留完整状态,可以改成:

final_state, decision = ta.propagate("600519.SH", "2024-05-10")

这样你就可以查看:

final_state["market_report"]
final_state["news_report"]
final_state["sentiment_report"]
final_state["fundamentals_report"]
final_state["final_trade_decision"]

7.8 decision 是什么

第二个返回值是:decision

它不是完整报告,而是从:

final_state["final_trade_decision"]

中提取出来的核心评级。

所以流程是:

Portfolio Manager 输出完整 final_trade_decision

SignalProcessor / parse_rating 提取 Buy / Hold / Sell 等评级

返回 decision

print(decision)

在你的实际运行结果里,完整文本里多次出现:

Action: Hold
FINAL TRANSACTION PROPOSAL: HOLD

最后脚本打印的简化结果是:

Hold

这和 run_ashare_full.pyprint(decision) 对应。

7.9 为什么输出里最终决策重复出现多次

decision里最后有多段重复的:

Action: Hold
Reasoning: ...
Position Sizing: ...
FINAL TRANSACTION PROPOSAL: HOLD

这和 debug=True 有关。

debug=True 时,系统会用流式方式执行图,并把每个阶段的最后一条 message 打印出来。

如果某些后续状态更新没有新增新的消息,或者最后一条 message 仍然是同一条 Portfolio Manager / final decision 消息,那么调试打印可能会重复打印同一条最终消息。

所以这里要区分:

重复打印 ≠ 重复做了多次最终决策

它更像是 debug stream 的显示结果。

真正最终用于 print(decision) 的还是最后的 final_trade_decision 经过解析后的 Hold

7.10 完整状态日志保存在哪里

运行结束后,系统会把完整状态写到结果目录。

源码逻辑是按:

results_dir / ticker / TradingAgentsStrategy_logs / full_states_log_<trade_date>.json

保存。

也就是说,这次理论上会对应类似:

<results_dir>/600519.SH/TradingAgentsStrategy_logs/full_states_log_2024-05-10.json

这个 JSON 里会保存:

market_report
sentiment_report
news_report
fundamentals_report
investment_debate_state
trader_investment_decision
risk_debate_state
investment_plan
final_trade_decision

CLI 运行日志和报告仍走原有机制,A 股模式会写到用户目录下的 ~/.tradingagents/logs/ashare;而 A 股数据缓存本身则在 data/cache/a_share 下面分 prices、news、social、fundamentals、indices 等目录。

这里要区分两种“保存”:

数据缓存:
data/cache/a_share/...
保存行情、新闻、情绪、基本面原始或整理数据

运行结果日志:
results_dir / ticker / TradingAgentsStrategy_logs / ...
保存这次完整 Agent 流程结果

7.11 memory log 的作用

除了写完整状态日志,系统还会把最终决策写入 memory log。

它的作用是:

下一次分析同一只股票时,
系统可以把过去的决策经验作为 past_context 注入。

也就是说,A股版本保留了原始 TradingAgents 的“记忆 / 反思”机制。

流程大概是:

本次开始前:
读取过去同 ticker 的 memory context
放入 AgentState["past_context"]

本次结束后:
把 final_trade_decision 写入 memory log
等未来运行时作为历史经验

这让系统不是完全孤立地分析每一次任务。

不过需要注意:A股版本的数据层已经适配了 A 股,但 memory outcome 里的收益率评估逻辑如果仍沿用原始美股实现,后续可能还需要进一步 A 股化。这个不影响当前 run_ashare_full.py 的主流程,但影响长期回测式反思质量。

7.12 状态层如何解释这次 600519.SH 的结果

这次完整状态大致是这样逐步形成的:

初始状态:
company_of_interest = 600519.SH
trade_date = 2024-05-10

Market 阶段:
写入 market_report
结论:长期趋势尚可,短期有回调压力

News 阶段:
写入 news_report
结论:大盘背景可用,公司新闻不可用,信息不完整

Social 阶段:
写入 sentiment_report
结论:情绪中性,强度 0.45

Fundamentals 阶段:
写入 fundamentals_report
结论:基本面强,盈利能力好,但估值和增长需谨慎

Research 阶段:
写入 investment_debate_state 和 investment_plan
结论:多空都有理由,偏向谨慎持有

Trader 阶段:
写入 trader_investment_plan
结论:维持仓位,不加不减

Risk 阶段:
写入 risk_debate_state
结论:风险收益比不支持加仓

Portfolio Manager:
写入 final_trade_decision
结论:HOLD

SignalProcessor:
从 final_trade_decision 提取 Hold

print(decision):
输出 Hold

这就是状态层视角下的完整闭环。

7.13 这一层需要形成的核心认知

可以把状态与结果层理解成:

AgentState 是整个流程的共享黑板。

每个 Agent 不只是“说一句话”,
而是在黑板上写入自己的阶段成果。

messages 可以被清理,
但报告字段会保留下来。

final_state 是整块黑板的最终状态,
decision 是从最终决策文本中抽取出来的简化评级。

run_ashare_full.py 只打印 decision,
所以最终输出只看到 Hold。

一句话总结:

A股版本的完整运行结果不是只有 HoldHold 只是最终评级。真正有价值的是 final_state,里面保存了从行情、新闻、情绪、基本面到多空辩论、交易计划、风险审查和最终裁决的完整链路。

8. CLI 与脚本运行方式层

这一层解决的问题是:

A股版本有哪些入口?
run_ashare_full.py 和 CLI 有什么区别?
为什么一个是硬编码流程,一个是交互式流程?
A Share / QuantAgentLab 市场模式在 CLI 中起什么作用?
不同入口适合什么使用场景?

8.1 A股版本目前有三类运行入口

A股版本主要有三个入口:

1. python examples/run_ashare_market.py
2. python examples/run_ashare_full.py
3. tradingagents 或 python -m cli.main analyze

可以直接跑最小 A 股示例 run_ashare_market.py,也可以跑完整 A 股分析师团队 run_ashare_full.py,还可以使用 CLI;如果没有安装命令入口,也可以用 python -m cli.main analyze

这三个入口的关系可以这样理解:

run_ashare_market.py = 最小验证入口

run_ashare_full.py = 固定参数的完整 A 股团队入口

CLI = 交互式通用入口,可选美股或 A 股

入口一:run_ashare_market.py

这个脚本适合做:

A 股数据链路最小测试

它通常只选择最少的 analyst,例如只跑 Market Analyst,用来确认:

A 股代码能不能识别
AkShare 能不能取到行情
a_share vendor 是否能正常路由
技术指标是否能返回
LLM 是否能生成基本市场报告

如果你刚安装完项目,或者刚改完 a_share.py,最适合先跑这个脚本。

它的意义不是生成完整投资决策,而是验证:

A股版本是否能跑通最小闭环

可以理解成:

最低成本冒烟测试

入口二:run_ashare_full.py

这就是我们一直在分析的入口。

它适合做:

固定标的、固定日期、固定模型、固定 analyst 顺序的完整 A 股投研流程

它直接写死了:

market = A-share
llm_provider = glm
deep_think_llm = glm-5.1
quick_think_llm = glm-4.7
output_language = Chinese
data_vendors = a_share
selected_analysts = market, news, social, fundamentals
ticker = 600519.SH
trade_date = 2024-05-10

这些配置都在 run_ashare_full.py 里。

所以它不是交互式工具,而是一个可复现的完整示例脚本

run_ashare_full.py 的特点

它的特点是:

不需要用户交互
参数固定
分析路径固定
适合调试完整图流程
适合写教程
适合复现实验结果

decision就是通过这个脚本跑出来的。输出中可以看到完整流程从 600519.SH 开始,先调用 get_stock_data,再多次调用 get_indicators,然后进入新闻、情绪、基本面和最终决策。

所以 run_ashare_full.py 的价值是:

它是 A股版本完整工作流的最清晰样板

后面如果想改标,只需要改:

ta.propagate("600519.SH", "2024-05-10")

例如改成:

ta.propagate("300750.SZ", "2024-05-10")

如果想换模型,就改:

config["llm_provider"]
config["deep_think_llm"]
config["quick_think_llm"]

如果想减少成本,可以减少 analyst 或辩论轮数。

入口三:CLI

CLI 是交互式入口。

CLI 可以通过tradingagents启动;如果没有安装命令入口,也可以:

python -m cli.main analyze

CLI 的特点是:

不需要改代码
通过界面选择参数
可以选择市场类型
可以选择 ticker
可以选择日期
可以选择 LLM provider
可以选择 analyst

A 股 CLI 操作流程是:

1. Market Type 选择 A Share / QuantAgentLab
2. Ticker 输入 600519.SH、000001.SZ、300750.SZ,也支持纯 6 位代码
3. 选择分析日期,例如 2024-05-10
4. 选择 LLM provider,例如 deepseek
5. 选择 analyst,最小可用建议先选 market

8.2 CLI 中的 A Share / QuantAgentLab 是什么

这是 A股版本在 CLI 中新增的市场模式。

它的作用不是单纯改一个显示名称,而是触发一组配置切换。

当你在 CLI 里选择:

A Share / QuantAgentLab

A 股模式会自动切换:

core_stock_apis = a_share
technical_indicators = a_share
fundamental_data = a_share
news_data = a_share

这意味着 CLI 和 run_ashare_full.py 本质上使用的是同一套 A 股数据机制:

CLI 选择 A Share

data_vendors 切到 a_share

工具调用进入 route_to_vendor

route_to_vendor 进入 a_share.py

AkShare / 缓存 / fallback / 字段合并

所以:

run_ashare_full.py 是手动硬编码 data_vendors = a_share
CLI 是通过界面选择 A Share 后自动设置 data_vendors = a_share

这是两者最重要的区别。

8.3 CLI 和脚本的关系

可以用一张表理解。

维度 run_ashare_full.py CLI
使用方式 运行脚本 交互式选择
是否改代码 需要改脚本参数 不需要
标的 写死 600519.SH 用户输入
日期 写死 2024-05-10 用户选择
模型 写死 GLM 用户选择
Analyst 写死四个 analyst 用户选择
适合场景 调试、教程、复现 日常使用、多标的分析
数据源切换 脚本里设置 data_vendors 选择市场模式后自动设置
输出 控制台 debug 流 + 最终 decision CLI UI + 日志/报告

所以:

想理解项目流程,用 run_ashare_full.py。
想日常跑不同股票,用 CLI。
想快速验证行情工具,用 run_ashare_market.py。

8.4 为什么 A股版本还保留美股模式

A股版本不是把原始 TradingAgents 改成只支持 A 股。

不删除原版美股逻辑
不绕过 TradingAgentsGraph
如果要回到原版美股模式,CLI 中把 Market Type 选回 US Stock 即可

这说明项目结构是:

同一个 TradingAgentsGraph
同一套 Agent
同一套工具抽象

根据 Market Type / data_vendors 不同:
美股模式 → yfinance / alpha_vantage
A 股模式 → a_share

所以 A股版本的定位是:

扩展原始 TradingAgents
而不是替换原始 TradingAgents


8.5 数据保存和日志保存的区别

A股版本有两类保存路径,容易混淆。

A 股数据缓存

这是 a_share.py 使用的缓存目录。

TradingAgents/data/cache/a_share/prices
TradingAgents/data/cache/a_share/news
TradingAgents/data/cache/a_share/social
TradingAgents/data/cache/a_share/fundamentals
TradingAgents/data/cache/a_share/indices

这些目录保存的是数据:

行情 CSV
新闻 JSON
情绪 JSON
基本面 JSON
指数数据

它服务的是:

数据获取 fallback

例如在线接口失败时,a_share.py 可以查缓存。

CLI / Graph 运行日志和报告

CLI 运行日志和报告仍走原有机制,A 股模式会写到用户目录下的:

~/.tradingagents/logs/ashare

这些保存的是运行过程或结果:

分析师报告
运行日志
最终交易决策
完整状态

它服务的是:

复盘和查看运行结果

所以要区分:

data/cache/a_share = 给数据层 fallback 用

~/.tradingagents/logs/ashare 或 results_dir = 给用户看报告和日志用


8.6 不同入口适合什么阶段

如果你在开发或学习 A股版本,建议按这个顺序使用。

第一步:最小数据测试

python -c "from tradingagents.dataflows.a_share import get_ashare_stock_data; print(get_ashare_stock_data('600519.SH','2024-03-01','2024-05-10'))"

这个直接测试 a_share.py,不经过 Agent,也不经过 LangGraph。

适合确认:

AkShare 是否可用
A 股代码是否能识别
行情接口是否能返回
缓存是否能写入

第二步:最小 Agent 测试

运行:

python examples/run_ashare_market.py

适合确认:

TradingAgentsGraph 是否能启动
Market Analyst 是否能调用工具
route_to_vendor 是否能路由到 a_share
LLM 是否能生成市场报告

第三步:完整团队测试

运行:

python examples/run_ashare_full.py

适合确认:

Market / News / Social / Fundamentals 是否能完整跑
Bull / Bear / Trader / Risk / Portfolio Manager 是否能跑
最终是否能输出 decision

decision就是这个阶段的结果。


第四步:日常交互使用

运行:

tradingagents

或者:

python -m cli.main analyze

然后选择 A Share / QuantAgentLab

适合:

不改代码地分析不同 A 股股票
尝试不同 analyst 组合
尝试不同模型 provider
调整分析日期

8.7 脚本入口和 CLI 入口背后的共同点

虽然运行方式不同,但背后共同点是:

最终都会创建 TradingAgentsGraph
最终都会设置 config
最终都会调用 propagate(ticker, date)
最终都会让 Agent 调用工具
最终都会经 route_to_vendor 进入对应 vendor
最终都会输出 decision

差别只是:

脚本:在代码里写死 config
CLI:用户在交互界面里选择 config

所以理解了 run_ashare_full.py,再看 CLI 其实就很自然:

CLI 只是把手写配置变成了交互式配置

8.8 这一层需要形成的核心认知

你可以这样理解 A股版本的运行入口:

a_share.py 最小测试:测数据层

run_ashare_market.py:测最小 Agent + A 股数据

run_ashare_full.py:测完整 A 股多智能体投研链路

CLI:用于日常交互式分析,可在美股和 A 股之间切换

A Share / QuantAgentLab 模式的本质是:

把原始 TradingAgents 的数据 vendor 切换为 a_share,
同时保留原来的 Agent 图、工具抽象和决策流程。

9. A股版本与原始 TradingAgents 的完整差异总结

这一层的目标是:

哪些东西沿用了原始 TradingAgents?
哪些东西是 A股版本新增的?
哪些东西是轻微修改过的?
哪些地方目前还是第一版占位?
A股版本现在的优势和限制在哪里?

9.1 先给整体结论

A股版本不是重写了 TradingAgents,而是在原始 TradingAgents 的基础上做了一个 A 股市场适配层

可以这样理解:

原始 TradingAgents:
多智能体投研决策框架 + 美股数据 vendor

A股版本:
原始多智能体投研决策框架 + A 股数据 vendor + A 股 CLI 市场模式 + 中文输出倾向 + A 股缓存和 fallback

A股版本是基于原版 TradingAgents 的最小改动版,目标是让原有多智能体框架支持 A 股投研与决策,同时保留原版美股 / yfinance / alpha_vantage 流程。

所以最核心的区别是:

原始 TradingAgents 主要解决:多智能体如何协作做交易决策

A股版本额外解决:这些 Agent 如何可靠地拿到 A 股数据


9.2 完全保留的部分

A股版本保留了原始 TradingAgents 的主体结构。

保留 TradingAgentsGraph

A股版本仍然通过:

TradingAgentsGraph(...)
ta.propagate(...)

启动完整流程。

也就是说,它没有绕过原始图执行器TradingAgentsGraph。

保留多智能体组织结构

A股版本保留了:

Market Analyst
News Analyst
Social Analyst
Fundamentals Analyst

Bull Researcher
Bear Researcher
Research Manager

Trader

Aggressive Risk Analyst
Conservative Risk Analyst
Neutral Risk Analyst

Portfolio Manager

所以 A股版本不是“写了一个 A 股分析脚本”,而是“让原来的多智能体投研公司可以分析 A 股”。

保留工具抽象

Agent 仍然调用这些标准工具:

get_stock_data
get_indicators
get_news
get_global_news
get_social_sentiment
get_fundamentals
get_balance_sheet
get_cashflow
get_income_statement

A股版本没有让 Agent 直接调用:

AkShare
东方财富
新浪
腾讯

这保证了项目结构仍然是:

Agent 只关心“我要什么数据”
Vendor 负责“怎么取这个数据”

保留状态流转机制

A股版本仍然使用:

AgentState
messages
market_report
news_report
sentiment_report
fundamentals_report
investment_debate_state
risk_debate_state
final_trade_decision

也就是说,多智能体流程不是靠一个长 prompt,而是靠状态逐步累积。

保留美股逻辑

不删除原版美股逻辑
如果要回到原版美股模式,CLI 中把 Market Type 选回 US Stock 即可

所以 A股版本不是替代原版,而是扩展原版。


9.3 新增的部分

A股版本新增的核心内容主要有五类。

新增 a_share.py

这是最重要的新增文件。

它负责:

A 股代码标准化
AkShare 接口调用
行情多源 fallback
本地缓存读写
技术指标计算
新闻公告获取
市场背景获取
行情衍生情绪
基本面多接口字段级合并

新增 A 股数据 vendor:TradingAgents/tradingagents/dataflows/a_share.py

这是 A股版本的数据核心。

新增 A 股 vendor 路由

A股版本在 vendor 映射里新增:a_share

让这些工具可以路由到 A 股实现:

get_stock_data -> get_ashare_stock_data
get_indicators -> get_ashare_indicator
get_news -> get_ashare_news
get_global_news -> get_ashare_market_news
get_social_sentiment -> get_ashare_social_sentiment
get_fundamentals -> get_ashare_fundamentals

这使得 A股版本不需要重写 Agent,只需要在 config["data_vendors"] 中切换供应商。

新增 A 股缓存目录

A 股缓存目录:

TradingAgents/data/cache/a_share/prices
TradingAgents/data/cache/a_share/news
TradingAgents/data/cache/a_share/social
TradingAgents/data/cache/a_share/fundamentals
TradingAgents/data/cache/a_share/indices

这些缓存服务于:

行情失败 fallback
新闻缓存
情绪缓存
基本面缓存
指数背景缓存

这对 A 股数据源非常重要,因为 AkShare 接口和网络状态可能不稳定。

新增 A Share / QuantAgentLab CLI 模式

CLI 新增:A Share / QuantAgentLab

并且选择这个市场模式后,会自动切换:

core_stock_apis = a_share
technical_indicators = a_share
fundamental_data = a_share
news_data = a_share

这说明 A股版本不只是脚本示例,还接入了交互式 CLI。

新增示例脚本

A股版本新增了至少两个示例:

examples/run_ashare_market.py
examples/run_ashare_full.py

run_ashare_market.py = 直接跑最小 A 股示例
run_ashare_full.py = 跑完整 A 股分析师团队

这两个脚本分别适合最小验证和完整流程演示

9.4 轻微修改的部分

A股版本还对原始框架做了一些轻微但关键的适配。

配置体系中增加 A 股相关参数

run_ashare_full.py 中新增:

config["market"] = "A-share"
config["output_language"] = "Chinese"
config["data_vendors"] = {...}
config["a_share_data"] = {...}

其中 a_share_data 包括:

price_source
news_source
fundamental_source
social_source
cache_dir
use_cache
adjust
allow_mock
retry_times
retry_sleep_seconds
nearby_cache_max_days

这些参数定义了 A股版本的数据行为。

工具路由层支持 a_share

原始工具名保留,但工具路由层新增了 a_share 这个 vendor。

这样原始 get_stock_data在美股模式下可以继续走:yfinance / alpha_vantage

在 A 股模式下可以走:a_share.py

这属于非常关键的“最小改动”。

Social Analyst 工具发生了适配

A股版本中 Social Analyst 可以调用:

get_social_sentiment
get_news

decision里也确认了 Social 阶段实际调用了 get_social_sentiment,返回了 A股版本的行情衍生情绪。

这说明 A股版本不是简单把 Social Analyst 仍当新闻分析,而是接入了 A 股情绪工具。

输出语言倾向中文

run_ashare_full.py 设置:

config["output_language"] = "Chinese"

因此 Analyst 报告主体基本是中文。

不过后半段 Trader / Portfolio Manager 输出仍可能出现英文结构,比如:

Action
Reasoning
Position Sizing
FINAL TRANSACTION PROPOSAL

这说明当前中文化主要覆盖前半段或部分 Agent,后半段 prompt 仍有原始英文格式残留。

9.5 当前第一版占位或不完整的部分

A股版本已经能跑完整流程,但仍有一些明显的一版特征。

个股新闻接口不稳定

现在的运行结果中,600519.SHget_news 返回:

DATA_UNAVAILABLE
WARNING: 未获取到真实新闻公告。KeyError: '600519'

这说明新闻接口目前存在不稳定或代码格式适配问题。

不过 A股版本处理得比较诚实:没有编造新闻,而是明确返回不可用。

get_global_news 在 A 股模式下其实是市场指数背景

原始工具名叫:get_global_news

但 A股版本里它更像:get_ashare_market_news

实际返回沪深300指数表现,而不是全球宏观新闻。

这不是错误,但需要在理解上区分:

工具名沿用原版
语义在 A 股模式下发生了本地化转换

输出中 get_global_news 返回的是 000300.SH 沪深300数据。

Social 情绪不是严格社交媒体情绪

第一版主要基于真实行情衍生指标生成情绪摘要
不依赖伪造股吧/雪球数据

所以当前 Social Analyst 的数据更准确地说是市场行为情绪,而不是真实社交平台舆情

这点在投研解释时需要说明。

三张财报明细接口目前是占位

现在的输出中:

get_balance_sheet
get_cashflow
get_income_statement

都返回了:

DATA_UNAVAILABLE
说明:第一版暂未单独提供 A 股资产负债表 / 现金流 / 利润表明细接口,请优先参考 fundamentals_report。

所以当前基本面核心是:get_ashare_fundamentals

而不是三张完整明细表。

技术指标别名存在语义偏差

当前 A股版本为了兼容原始 TradingAgents 的指标名,把一些指标做了映射:

close_50_sma -> MA20
close_200_sma -> MA60
close_10_ema -> MA10

这会导致 LLM 可能把 MA20 解释成 50 日均线。

现在的输出中就出现了类似:

MA20 (50日均线)

这属于报告解释层面的准确性问题,后续可以优化。

后半段决策输出没有完全中文化

最终输出里有:

Action: Hold
Reasoning
Position Sizing
FINAL TRANSACTION PROPOSAL

这说明后半段 Agent 的 prompt 仍保留英文格式。它不影响运行,但如果 A股版本目标是中文投研产品,后续可以进一步本地化。

Memory / 收益评估可能仍偏美股逻辑

A股版本保留 memory log 和历史决策机制,但如果收益评估部分仍使用原始美股 ticker / yfinance / SPY 逻辑,那么长期反思质量可能不完全适配 A 股。

这个对单次 run_ashare_full.py 影响不大,但对后续“多次运行后基于历史经验改进决策”会有影响。

9.6 A股版本目前的优势

架构改动克制

A股版本没有推翻原始 TradingAgents,而是:

保留图结构
保留 Agent
保留工具抽象
保留美股 vendor
新增 A 股 vendor

这让项目可维护性比较好。

数据可信度意识强

A股版本每类数据都会返回:

DATA_STATUS
DATA_SOURCE
CAN_USE_FOR_DECISION
WARNING / ERRORS

这对 LLM 很重要,因为它可以知道:

哪些数据可靠
哪些数据不可用
哪些只能参考
哪些不该用于决策

行情 fallback 比较实用

A 股行情采用:东方财富 → 新浪 → 腾讯 → 精确缓存 → 附近日期缓存

这比只依赖单一接口更稳健。README 也明确写了这条 fallback 链。

不生成假数据

这是非常重要的原则。

行情优先在线拉取,成功后再缓存;
获取失败时尽量回退到真实缓存;
不再生成假行情数据。

这比“为了让 Agent 有东西分析而编造数据”可靠得多。

基本面字段级合并很有价值

A 股基本面数据分散在多个接口中。A股版本通过多接口字段级合并,让 Fundamentals Analyst 能拿到较完整的:

估值
盈利能力
成长性
资产负债
现金流
字段来源
缺失字段
接口错误

这次 600519.SH 的基本面返回 MISSING_FIELDS: 无,说明这部分设计实际有效。

CLI 和脚本都能用

A股版本同时支持:

脚本硬编码运行
CLI 交互式运行

这对开发、测试和日常使用都比较方便。

9.7 A股版本目前的限制

依赖 AkShare 接口稳定性

A股版本大量依赖 AkShare。

AkShare 本身接口可能受:

源站变化
字段变化
网络问题
版本差异
接口限流

影响。

A股版本通过 fallback 和缓存缓解了这个问题,但不能完全消除。

新闻质量还不够

运行中个股新闻没有取到,说明新闻模块还需要增强。

后续可以考虑:

东方财富公告
巨潮资讯
交易所公告
公司公告 PDF
财经新闻源
行业新闻
政策新闻

并做更好的日期过滤和代码匹配。

Social Analyst 目前不是社交舆情

当前 Social 情绪是行情衍生,不是社交平台抓取。

这不是坏事,但需要命名和 prompt 更清楚。

后续可以选择继续叫 market-derived sentiment或者真正接入东方财富股吧、雪球、同花顺热度等

技术指标映射需要修正

后续可以把:

close_50_sma
close_200_sma

真正计算为 MA50 / MA200,或者修改 Market Analyst prompt 让它直接请求:

MA20
MA60
MA10
RSI_14
MACD
Bollinger

否则报告解释可能继续出现偏差。

后半段 prompt 需要中文化和 A 股本土化

目前前半段分析比较中文,但最终决策仍有英文格式。

后续可以针对:

Research Manager
Trader
Risk Analysts
Portfolio Manager

统一中文输出风格,并加入 A 股特有约束:

T+1
涨跌停
A 股交易时段
北向资金
行业政策
估值分位
流动性
财报披露节奏

风险与交易计划还不够 A 股化

当前 Trader / Risk Team 的逻辑更像通用股票分析。

后续可以加入:

A 股仓位建议
止盈止损
涨跌停风险
流动性风险
板块轮动
市场风格
融资融券
沪深港通
财报窗口风险

这样 A股版本会更像本土投研系统,而不只是“能分析 A 股代码”。

9.8 未来优化方向

基于当前 A股版本,后续优化可以分为五条线。

数据线

增强新闻公告接口
补全三张财报明细
增强指数和行业数据
接入板块/行业行情
接入北向资金、资金流、龙虎榜
增加估值分位和历史比较

Agent 线

Market Analyst 改用更适合 A 股的指标
News Analyst 加入公告和政策解读
Social Analyst 明确市场行为情绪或接入真实舆情
Fundamentals Analyst 增加行业比较
Risk Analyst 增加 A 股交易制度风险
Portfolio Manager 输出更本土化决策格式

Prompt 线

统一中文输出
减少英文结构残留
明确 DATA_UNAVAILABLE 不能强行推断
明确 CAN_USE_FOR_DECISION=false 的数据只能参考
明确 A 股交易制度和限制

路由与配置线

按市场自动选择 vendor
支持多个 A 股 vendor 优先级
不同 analyst 可配置不同数据源
CLI 中暴露更多 A 股参数

评估与记忆线

A 股 ticker 收益率评估
用沪深300或中证全指替代 SPY
支持 A 股交易日历
历史决策复盘
不同市场单独 memory namespace

最终差异总表

模块 原始 TradingAgents A股版本
核心图结构 LangGraph 多智能体图 保留
Agent 角色 Analyst / Researcher / Trader / Risk / PM 保留
工具抽象 get_stock_data 等标准工具 保留
美股数据 yfinance / alpha_vantage 等 保留
A 股数据 无或不完整 新增 a_share.py
行情 美股数据源 AkShare 东方财富 / 新浪 / 腾讯 + 缓存
技术指标 原始指标体系 A 股行情本地计算
新闻 原始新闻工具 A 股公告/新闻 + 大盘背景
情绪 社交/新闻情绪 行情衍生情绪,不伪造社交数据
基本面 美股基本面接口 多 AkShare 接口字段级合并
CLI 原始市场选择 新增 A Share / QuantAgentLab
输出语言 通用/英文为主 A 股模式默认中文
缓存 原始缓存机制 新增 data/cache/a_share
决策流程 多空辩论 + 风控 + PM 保留
仍待完善 美股框架成熟 新闻、社交舆情、财报明细、中文化、A 股交易制度

9.9 这一层的核心认知

现在可以把 A股版本理解成:

一个保留原始 TradingAgents 多智能体决策框架,
但新增 A 股数据供应、缓存 fallback、基本面字段合并和 CLI 市场模式的扩展版本。

它的最大价值是:

让原始 TradingAgents 的多智能体投研流程可以分析 A 股。

它当前最强的地方是:

行情 fallback
基本面多接口字段级合并
不伪造数据
保持原框架兼容

它当前最需要继续完善的是:

新闻公告稳定性
真实舆情
三张财报明细
技术指标语义
后半段中文化
A 股交易制度和风险本土化

10. 总结:从美股多智能体框架到 A 股投研系统

到这里,对 run_ashare_full.py 背后的完整项目流程有了比较完整的认识:从入口配置、图执行、Agent 角色、工具路由、A 股数据供应、状态流转、最终结果,到它和原始 TradingAgents 的差异。

通过对 run_ashare_full.py 的完整梳理,可以看到,A股版本的核心并不是重写 TradingAgents,而是在尽量保留原始多智能体框架的基础上,为其接入了一套适配 A 股市场的数据供应与运行机制。

原始 TradingAgents 已经具备完整的多智能体投研决策链路:Market Analyst 负责市场和技术面,News Analyst 负责新闻和市场环境,Social Analyst 负责情绪判断,Fundamentals Analyst 负责基本面分析;随后 Bull/Bear Researcher 展开多空辩论,Research Manager 汇总研究观点,Trader 形成交易计划,Risk Analysts 进行风险审查,最终由 Portfolio Manager 给出交易决策。A股版本保留了这套 Agent 图、状态流转和决策逻辑,没有绕过 TradingAgentsGraph,也没有破坏原始美股流程。

A股版本真正的改造重点在数据层和入口层。通过新增 tradingagents/dataflows/a_share.py,系统可以将原本面向美股的数据请求转换成 A 股数据请求;通过 route_to_vendor()data_vendors = a_share,原有的 get_stock_dataget_indicatorsget_newsget_social_sentimentget_fundamentals 等工具可以在不改变 Agent 调用方式的情况下路由到 A 股实现。这样,Agent 仍然按照原来的方式“思考”和“调用工具”,但工具背后返回的已经是 A 股行情、技术指标、新闻公告、市场情绪和基本面数据。

在数据获取上,A股版本采用了更加稳健的工程设计。行情数据通过 AkShare 接入东方财富、 新浪、腾讯等来源,并提供精确缓存和附近日期缓存作为 fallback;技术指标基于真实行情本地计算;新闻和公告在不可用时明确返回 DATA_UNAVAILABLE,不伪造数据;情绪分析使用行情衍生指标生成市场行为情绪;基本面则通过多个 AkShare 接口进行字段级合并,形成适合 LLM 阅读的基本面摘要表。每一类数据结果都会带有 DATA_STATUSDATA_SOURCECAN_USE_FOR_DECISION,让后续 Agent 能够判断数据是否可靠、是否适合用于决策。

从运行结果看,python examples/run_ashare_full.py 完整执行了从 600519.SH 输入到最终 Hold 输出的全过程。系统先生成市场报告、新闻报告、情绪报告和基本面报告,再经过多空研究、交易计划、风险讨论和组合经理裁决,最终从 final_trade_decision 中提取出简化评级并打印。需要注意的是,最终控制台输出的 Hold 只是最终信号,真正有价值的是整个 final_state,其中包含了各阶段报告、辩论过程、交易计划、风险评估和最终决策依据。

整体来看,A股版本可以被理解为:在原始 TradingAgents 的多智能体投研“大脑”之上,接入了一套 A 股市场的数据感知系统。它目前已经能够跑通完整 A 股分析师团队,并在行情、基本面、缓存 fallback 和中文报告方面具备较好的实用性;同时也还有进一步完善空间,例如增强新闻公告稳定性、补全三张财报明细、修正技术指标语义、接入真实社交舆情、进一步中文化后半段 Agent 输出,并加入更多 A 股交易制度和风险约束。

因此,A股版本的价值不只是“让 TradingAgents 能跑 A 股代码”,而是提供了一个清晰的改造范式:在不破坏原有多智能体框架的前提下,通过数据 vendor、工具路由、缓存机制和本土化 prompt,让一个原本偏美股的智能体投研系统逐步演化为适用于 A 股市场的投研决策平台。

Logo

更多推荐