TradingAgents金融股票分析的最小实现

一、整体架构概览

系统分为五个层级:

  1. 数据层 :定义 FinancialDataAgentState 两个 TypedDict,作为 Agent 之间传递的共享状态。

  2. 分析层:三位独立分析师(基本面、情绪、技术)并行或顺序产出基础报告。

  3. 决策层:多空研究员分别基于基础报告构建论据,然后通过"辩论裁判"得到初步结论。

  4. 执行层:交易员生成具体提案(方向、仓位、止损),风控审核提案合规性。

  5. 最终决策层:投资组合经理综合所有中间结果,输出最终评级(买入/持有/卖出)。

整个流程是一个 顺序 + 扇出(技术分析结果同时发给多空双方) 的有向无环图,最终汇聚到决策节点。

二、核心模块详解(可作博客章节)

1. 大模型配置(兼容阿里云百炼)
python 复制代码
llm = ChatOpenAI(
    model=MODEL_NAME,
    api_key=API_KEY,
    base_url=BASE_URL,
    temperature=0.7,
)
  • 利用阿里云百炼的 兼容模式/compatible-mode/v1),可以直接使用 OpenAI SDK 调用通义千问模型。

  • 环境变量 DASHSCOPE_API_KEY 存储密钥,避免硬编码。

2. 状态管理(LangGraph 核心)
python 复制代码
class AgentState(TypedDict):
    ticker: str
    data: FinancialData
    fundamental_report: str
    sentiment_report: str
    technical_report: str
    bull_argument: str
    bear_argument: str
    debate_result: str
    trader_proposal: str
    risk_assessment: str
    final_decision: str
  • 每个节点函数接收 state 字典,返回需要更新的字段(增量更新)。

  • LangGraph 自动合并返回结果到全局状态。

3. 分析师节点(纯逻辑 + 小部分 LLM)
  • fundamental_analyst:使用 LLM 生成基本面分析(估值、盈利、风险)。

  • sentiment_analyst:基于情绪得分进行规则判断(>50 看多,< -50 看空)。

  • technical_analyst:基于 RSI 指标规则判断(>70 超买,<30 超卖)。

亮点:混合使用 LLM 和传统规则,降低不必要的 API 调用。

4. 多空辩论机制
  • bull_researcher / bear_researcher:分别基于相同的三份报告,要求 LLM 扮演"看多/看空研究员"构建论据。

  • debate:作为裁判,综合两方观点给出最终倾向(买入/卖出/持有)。

这种"双角色辩论 + 第三方裁判"的模式,可以有效抑制大模型的 立场偏见,提升中立性。

5. 交易员与风控
  • trader_agent:根据辩论结论生成具体交易提案(方向、仓位、止损位)。

  • risk_manager:审核提案,结合股价和 PE 给出"允许/限制/否决"。

风控节点是合规性检查的关键,可在此扩展更多指标(如最大回撤、行业敞口等)。

6. 最终决策(投资组合经理)
  • 综合情绪报告、风控意见和交易提案,输出最终评级并做简短总结。

三、LangGraph 工作流构建(重点技术点)

python 复制代码
workflow = StateGraph(AgentState)

workflow.add_node("fundamental", fundamental_analyst)
# ... 添加所有节点

workflow.set_entry_point("fundamental")
workflow.add_edge("fundamental", "sentiment")
workflow.add_edge("sentiment", "technical")
workflow.add_edge("technical", "bull")
workflow.add_edge("technical", "bear")   # fan-out
workflow.add_edge("bull", "debate")
workflow.add_edge("bear", "debate")
# ... 后续顺序边

workflow.add_edge("pm", END)
  • 扇出 (fan-out)technical 节点的输出同时流向 bullbear,LangGraph 会自动并行执行这两个节点(若硬件支持)。

  • 汇聚debate 节点需要等待 bullbear 都完成才会执行。

  • 顺序边:后续节点逐一串联,形成决策链。

这种 声明式图结构 比传统的函数调用链更易于修改、扩展和调试。


四、技术亮点与可改进点(供博客深入讨论)

✅ 亮点
  1. 角色分工清晰:每个 Agent 只负责单一任务,符合单一职责原则。

  2. 状态驱动:所有 Agent 通过共享状态通信,解耦了直接函数调用。

  3. 混合推理:部分节点使用规则(情绪、RSI),部分使用 LLM,平衡了成本与灵活性。

  4. 可观测性:LangGraph 内置支持流式输出、节点重试、断点调试(需额外配置)。

整体最小代码的实现》

python 复制代码
import os
from typing import TypedDict
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END

# ==================== 配置阿里云百炼大模型 ====================
# 方式1:从环境变量获取 API Key(推荐)
# 在终端执行: export DASHSCOPE_API_KEY="你的阿里云API Key"
# 方式2:直接填写(不推荐提交到代码仓库)
API_KEY = os.getenv("DASHSCOPE_API_KEY", "your-api-key-here")
BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1"
MODEL_NAME = "qwen-plus"  # 可选: qwen-turbo, qwen-max, qwen-plus

llm = ChatOpenAI(
    model=MODEL_NAME,
    api_key=API_KEY,
    base_url=BASE_URL,
    temperature=0.7,
)

# ==================== 定义数据结构 ====================
class FinancialData(TypedDict):
    price: float
    pe: float
    roe: float
    sentiment_score: int  # -100 到 100
    rsi: float

class AgentState(TypedDict):
    ticker: str
    data: FinancialData
    fundamental_report: str
    sentiment_report: str
    technical_report: str
    bull_argument: str
    bear_argument: str
    debate_result: str
    trader_proposal: str
    risk_assessment: str
    final_decision: str

# ==================== 1. 三位分析师 ====================
def fundamental_analyst(state: AgentState):
    data, ticker = state["data"], state["ticker"]
    prompt = f"""请对股票{ticker}进行基本面分析:
    - PE(市盈率): {data['pe']} 倍
    - ROE(净资产收益率): {data['roe']}%
    请从估值水平、盈利质量、潜在风险三个方面分析,最后给出看多或看空的倾向。"""
    return {"fundamental_report": llm.invoke(prompt).content}

def sentiment_analyst(state: AgentState):
    data, ticker = state["data"], state["ticker"]
    score = data["sentiment_score"]
    if score > 50:
        result = "强烈看多"
    elif score < -50:
        result = "强烈看空"
    else:
        result = "中性"
    return {"sentiment_report": f"{ticker}市场情绪得分 {score},结论:{result}"}

def technical_analyst(state: AgentState):
    data, ticker = state["data"], state["ticker"]
    rsi = data["rsi"]
    if rsi > 70:
        result = "超买(可能回调)"
    elif rsi < 30:
        result = "超卖(可能反弹)"
    else:
        result = "中性"
    return {"technical_report": f"{ticker} RSI = {rsi:.1f},处于{result}区域"}

# ==================== 2. 多空研究员辩论 ====================
def bull_researcher(state: AgentState):
    prompt = f"""你是一名看多研究员。基于以下信息,构建强有力的看多论据:
    - 基本面分析: {state['fundamental_report']}
    - 情绪分析: {state['sentiment_report']}
    - 技术面分析: {state['technical_report']}
    请用事实和逻辑支持买入该股票的理由。"""
    return {"bull_argument": llm.invoke(prompt).content}

def bear_researcher(state: AgentState):
    prompt = f"""你是一名看空研究员。基于以下信息,构建强有力的看空论据:
    - 基本面分析: {state['fundamental_report']}
    - 情绪分析: {state['sentiment_report']}
    - 技术面分析: {state['technical_report']}
    请用事实和逻辑支持卖出或回避该股票的理由。"""
    return {"bear_argument": llm.invoke(prompt).content}

def debate(state: AgentState):
    prompt = f"""请综合以下多空双方观点,做出最终裁决:
    【多方观点】{state['bull_argument']}
    【空方观点】{state['bear_argument']}
    请给出明确的结论:买入、卖出 或 持有,并简要说明理由。"""
    return {"debate_result": llm.invoke(prompt).content}

# ==================== 3. 交易员提案 ====================
def trader_agent(state: AgentState):
    prompt = f"""根据辩论结论:{state['debate_result']}
    生成具体的交易提案,包含:
    - 买卖方向(买入/卖出/观望)
    - 建议仓位(占总资金百分比)
    - 止损位(价格或百分比)
    请以清晰列表形式输出。"""
    return {"trader_proposal": llm.invoke(prompt).content}

# ==================== 4. 风控审核 ====================
def risk_manager(state: AgentState):
    prompt = f"""审核以下交易提案,并结合当前股价 ${state['data']['price']} 和 PE {state['data']['pe']} 倍:
    {state['trader_proposal']}
    请输出:允许执行 / 限制执行(说明限制条件) / 否决(说明风险原因)。"""
    return {"risk_assessment": llm.invoke(prompt).content}

# ==================== 5. 投资组合经理最终决策 ====================
def portfolio_manager(state: AgentState):
    prompt = f"""这是最终决策阶段,请综合所有信息:
    - 情绪分析:{state['sentiment_report']}
    - 风控审核意见:{state['risk_assessment']}
    - 交易员提案:{state['trader_proposal']}
    给出最终评级(买入/卖出/持有),并做简短总结。"""
    return {"final_decision": llm.invoke(prompt).content}

# ==================== 构建工作流(LangGraph) ====================
workflow = StateGraph(AgentState)

workflow.add_node("fundamental", fundamental_analyst)
workflow.add_node("sentiment", sentiment_analyst)
workflow.add_node("technical", technical_analyst)
workflow.add_node("bull", bull_researcher)
workflow.add_node("bear", bear_researcher)
workflow.add_node("debate", debate)
workflow.add_node("trader", trader_agent)
workflow.add_node("risk", risk_manager)
workflow.add_node("pm", portfolio_manager)

workflow.set_entry_point("fundamental")
workflow.add_edge("fundamental", "sentiment")
workflow.add_edge("sentiment", "technical")
workflow.add_edge("technical", "bull")
workflow.add_edge("technical", "bear")
workflow.add_edge("bull", "debate")
workflow.add_edge("bear", "debate")
workflow.add_edge("debate", "trader")
workflow.add_edge("trader", "risk")
workflow.add_edge("risk", "pm")
workflow.add_edge("pm", END)

app = workflow.compile()

# ==================== 交互式输入测试 ====================
def interactive_input():
    print("\n===== 多 Agent 股票分析系统(阿里通义千问)=====")
    ticker = input("请输入股票代码(例如 NVDA,AAPL):").strip().upper()
    try:
        price = float(input("当前股价:"))
        pe = float(input("市盈率 PE:"))
        roe = float(input("净资产收益率 ROE(%):"))
        sentiment = int(input("市场情绪得分(-100 到 100,正数积极,负数消极):"))
        rsi = float(input("RSI 指标(0-100):"))
    except ValueError:
        print("输入格式错误,请使用数字。")
        return None

    return {
        "ticker": ticker,
        "data": {
            "price": price,
            "pe": pe,
            "roe": roe,
            "sentiment_score": sentiment,
            "rsi": rsi,
        }
    }

if __name__ == "__main__":
    print("注意:请先设置环境变量 DASHSCOPE_API_KEY")
    print("若未设置,可在脚本中直接修改 API_KEY 变量")
    user_input = interactive_input()
    if user_input:
        print("\n正在调用 Agent 团队进行分析,请稍候...\n")
        result = app.invoke(user_input)
        print("\n" + "="*50)
        print(f"最终决策:{result['final_decision']}")
        print("="*50)
        # 可选:打印中间结果
        print("\n--- 详细过程 ---")
        print(f"基本面分析:{result['fundamental_report'][:200]}...")
        print(f"情绪分析:{result['sentiment_report']}")
        print(f"技术分析:{result['technical_report']}")
        print(f"辩论结论:{result['debate_result'][:200]}...")
        print(f"交易提案:{result['trader_proposal'][:200]}...")
        print(f"风控审核:{result['risk_assessment'][:200]}...")

五、运行与交互

  • 用户通过命令行交互输入股票代码、价格、PE、ROE、情绪得分、RSI。

  • 系统依次调用各个 Agent,最终输出最终决策和部分中间报告。

  • 当前为一次性推理,若要实现实时监控或回测,需要封装为类并集成数据源 API。

相关推荐
专利观察员1 小时前
用AI进行专利智能检索分析:拆解人形机器人半马跑赢的秘密/跑崩的解法(科技行业专利检索、专利分析实例)
人工智能·科技·机器人
俊基科技1 小时前
AR1105 声源定位模组 矿场智能安全监测与设备全生命周期运维技术方案
人工智能·声源定位·语音模组
刘~浪地球1 小时前
MongoDB安全与权限:企业级数据保护
数据库·安全·mongodb
阿正呀1 小时前
C#怎么清空Dictionary字典_C#如何管理内存集合【基础】
jvm·数据库·python
Zzj_tju1 小时前
视觉语言模型技术指南:LLaVA、Qwen-VL、MiniCPM-V 等主流方案差别在哪?
人工智能·语言模型·自然语言处理
咚咚王者1 小时前
人工智能之RAG工程 第五章 RAG 热门项目解析与实战
人工智能
贫民窟的勇敢爷们1 小时前
金融服务 AI 智能体:重塑金融工作流的技术与实践
人工智能·金融
yuanpan1 小时前
Python 与 Conda 编程实战指南:从环境配置到项目运行完整入门
开发语言·python·conda
Csvn1 小时前
日志系统
后端·python