ai-hedge-fund 采用LangGraph构建工作流,通过多个专业AI代理协同工作实现自动化交易决策,逐行解释和拆解

人工智能对冲基金

这是人工智能对冲基金的概念验证。该项目旨在探索如何利用人工智能进行交易决策。本项目仅供教育用途,不适用于实际交易或投资。

该系统采用多个代理协同工作:

本杰明·格雷厄姆经纪人——价值投资教父,只购买具有安全边际的隐藏宝石

Bill Ackman 经纪人 - 激进投资者,采取大胆立场并推动变革

Cathie Wood 经纪人 - 成长型投资女王,相信创新和颠覆的力量

查理芒格经纪人——沃伦巴菲特的合伙人,只以公平的价格购买优秀的企业

Michael Burry 经纪人 - 追寻深度价值的“大空头”反向投资者

彼得·林奇经纪人——务实的投资者,在日常业务中寻求“十倍股”

Phil Fisher 经纪人——细致的成长型投资者,使用深入的“谣言”研究

斯坦利·德鲁肯米勒经纪人——宏观传奇人物,寻找具有增长潜力的不对称机会

沃伦·巴菲特经纪人——奥马哈先知,以合理的价格寻找优秀的公司

估值代理——计算股票的内在价值并生成交易信号

情绪代理——分析市场情绪并生成交易信号

基本面代理 - 分析基本面数据并生成交易信号
技术代理 - 分析技术指标并生成交易信号
风险管理器——计算风险指标并设置持仓限额
投资组合经理——做出最终交易决策并生成订单
在这里插入图片描述

对冲基金交易系统原理图

系统架构图

用户输入
初始化
分析员集群
技术分析代理
基本面分析代理
情绪分析代理
风险管理系统
组合管理系统
交易决策输出

使用场景

该项目适用于以下场景:

  • 金融教育与研究:帮助学习者了解AI在金融领域的应用。

  • 策略开发与测试:模拟不同投资策略的性能,优化投资组合。

  • 市场分析:通过智能代理分析市场情绪、基本面和技术指标。

项目使用
环境搭建
克隆项目仓库:

git clone https://github.com/virattt/ai-hedge-fund.git   cd ai-hedge-fund   

安装 Poetry(如果尚未安装):

curl -sSL https://install.python-poetry.org | python3 -   

安装项目依赖:

poetry install   

设置环境变量:

.env.example 文件为 .env:
cp .env.example .env   

在 .env 文件中设置以下 API 密钥(至少设置一个):

OPENAI_API_KEY:用于运行 OpenAI 提供的语言模型。

GROQ_API_KEY:用于运行 Groq 提供的语言模型。

FINANCIAL_DATASETS_API_KEY:用于获取金融数据。

注意:苹果(AAPL)、谷歌(GOOGL)、微软(MSFT)、英伟达(NVDA)和特斯拉(TSLA)的数据无需 API 密钥即可免费使用。

运行项目
运行以下命令启动项目:

poetry run python src/main.py --ticker AAPL,MSFT,NVDA   

可选参数:

–show-reasoning:打印每个智能代理的决策逻辑。

–start-date 和 --end-date:指定决策的时间范围,格式为 YYYY-MM-DD。

运行回测工具
运行以下命令启动回测工具:

poetry run python src/backtester.py --ticker AAPL,MSFT,NVDA   

可选参数:

–start-date 和 --end-date:指定回测的时间范围。

项目结构
在这里插入图片描述

基于多智能体协作的对冲基金交易系统

本系统采用LangGraph构建工作流,通过多个专业AI代理协同工作实现自动化交易决策。系统包含技术分析、基本面分析、市场情绪分析等模块,最终由风险管理和组合管理代理生成交易指令。
"""
import sys
from dotenv import load_dotenv  # 加载环境变量
from langchain_core.messages import HumanMessage  # 人机交互消息格式
from langgraph.graph import END, StateGraph  # 工作流状态管理
from colorama import Fore, Style, init  # 终端彩色输出
import questionary  # 交互式命令行问卷
from agents.portfolio_manager import portfolio_management_agent  # 组合管理代理
from agents.risk_manager import risk_management_agent  # 风险管理代理
from graph.state import AgentState  # 共享状态对象
from utils.display import print_trading_output  # 结果格式化输出
from utils.analysts import ANALYST_ORDER, get_analyst_nodes  # 分析员配置
from utils.progress import progress  # 进度条显示
from llm.models import LLM_ORDER, OLLAMA_LLM_ORDER, get_model_info, ModelProvider  # 大模型管理
from utils.ollama import ensure_ollama_and_model  # 本地Ollama验证
import argparse  # 命令行参数解析
from datetime import datetime  # 日期处理
from dateutil.relativedelta import relativedelta  # 日期计算
from utils.visualize import save_graph_as_png  # 工作流可视化
import json  # JSON解析

# 环境初始化
load_dotenv()  # 加载.env文件
init(autoreset=True)  # 初始化Colorama

def parse_hedge_fund_response(response):
    """
    解析对冲基金决策的JSON响应
    
    参数:
        response: LLM的原始响应字符串
        
    返回:
        dict: 解析后的字典,解析失败返回None
        
    异常处理:
        - JSON解码错误
        - 类型错误
        - 意外错误
    """
    try:
        return json.loads(response)
    except json.JSONDecodeError as e:
        print(f"JSON解析错误: {e}\n响应内容: {repr(response)}")
        return None
    except TypeError as e:
        print(f"类型错误(应为字符串,实际收到{type(response).__name__}): {e}")
        return None
    except Exception as e:
        print(f"意外错误: {e}\n响应内容: {repr(response)}")
        return None

def run_hedge_fund(
    tickers: list[str],
    start_date: str,
    end_date: str,
    portfolio: dict,
    show_reasoning: bool = False,
    selected_analysts: list[str] = [],
    model_name: str = "gpt-4o",
    model_provider: str = "OpenAI",
):
    """
    交易系统核心执行流程
    
    参数:
        tickers: 待分析股票代码列表
        start_date: 分析开始日期(YYYY-MM-DD)
        end_date: 分析结束日期(YYYY-MM-DD)
        portfolio: 初始投资组合状态
        show_reasoning: 是否显示决策过程
        selected_analysts: 选择的分析员列表
        model_name: 使用的大模型名称
        model_provider: 模型提供商
        
    返回:
        dict: {
            "decisions": 最终交易决策,
            "analyst_signals": 各分析员信号
        }
        
    流程:
        1. 启动进度条
        2. 动态创建工作流
        3. 执行分析流程
        4. 解析返回结果
    """
    progress.start()  # 启动进度条动画

    try:
        # 动态创建工作流
        workflow = create_workflow(selected_analysts) if selected_analysts else app
        agent = workflow.compile()

        # 执行完整流程
        final_state = agent.invoke({
            "messages": [HumanMessage(content="基于提供数据做出交易决策")],
            "data": {
                "tickers": tickers,
                "portfolio": portfolio,
                "start_date": start_date,
                "end_date": end_date,
                "analyst_signals": {},  # 收集各分析员输出
            },
            "metadata": {  # 控制参数
                "show_reasoning": show_reasoning,
                "model_name": model_name,
                "model_provider": model_provider,
            },
        })

        return {
            "decisions": parse_hedge_fund_response(final_state["messages"][-1].content),
            "analyst_signals": final_state["data"]["analyst_signals"],
        }
    finally:
        progress.stop()  # 确保进度条清理

def create_workflow(selected_analysts=None):
    """
    创建代理工作流图
    
    参数:
        selected_analysts: 选择的分析员列表
        
    返回:
        StateGraph: 配置好的工作流
        
    图结构:
        开始节点 -> 分析员们 -> 风险管理 -> 组合管理 -> 结束
    """
    workflow = StateGraph(AgentState)
    workflow.add_node("start_node", start)  # 初始节点

    analyst_nodes = get_analyst_nodes()  # 获取预定义分析员配置
    
    # 默认使用所有分析员
    selected_analysts = selected_analysts or list(analyst_nodes.keys())
    
    # 添加选定分析员节点
    for analyst_key in selected_analysts:
        node_name, node_func = analyst_nodes[analyst_key]
        workflow.add_node(node_name, node_func)
        workflow.add_edge("start_node", node_name)  # 连接到开始节点

    # 添加必需的风险和组合节点
    workflow.add_node("risk_management_agent", risk_management_agent)
    workflow.add_node("portfolio_management_agent", portfolio_management_agent)

    # 连接分析员到风险管理
    for analyst_key in selected_analysts:
        workflow.add_edge(analyst_nodes[analyst_key][0], "risk_management_agent")

    # 最终工作流连接
    workflow.add_edge("risk_management_agent", "portfolio_management_agent")
    workflow.add_edge("portfolio_management_agent", END)

    workflow.set_entry_point("start_node")
    return workflow

if __name__ == "__main__":
    # 命令行接口配置
    parser = argparse.ArgumentParser(description="AI驱动的对冲基金交易系统")
    parser.add_argument("--initial-cash", type=float, default=100000.0, 
                       help="初始资金(默认: 10万美元)")
    parser.add_argument("--margin-requirement", type=float, default=0.0,
                       help="初始保证金要求(默认: 0)")
    parser.add_argument("--tickers", type=str, required=True,
                       help="逗号分隔的股票代码(例如 AAPL,TSLA)")
    parser.add_argument("--start-date", type=str, 
                       help"开始日期(YYYY-MM-DD)(默认: 3个月前)")
    parser.add_argument("--end-date", type=str, 
                       help="结束日期(YYYY-MM-DD)(默认: 今日)")
    parser.add_argument("--show-reasoning", action="store_true",
                       help="显示代理决策过程")
    parser.add_argument("--show-agent-graph", action="store_true",
                       help="生成工作流可视化PNG")
    parser.add_argument("--ollama", action="store_true",
                       help="使用本地Ollama模型代替云端LLM")

    args = parser.parse_args()

    # 交互式分析员选择
    selected_analysts = questionary.checkbox(
        "选择分析团队",
        choices=[questionary.Choice(显示名, 值) for 显示名, 值 in ANALYST_ORDER],
        instruction=(
            "空格: 选择  |  A: 全选/取消  |  Enter: 确认\n"
            "推荐组合: 技术面 + 基本面 + 市场情绪"
        ),
        style=questionary.Style(  # 自定义样式
            [
                ("checkbox-selected", "fg:green"),
                ("selected", "fg:green noinherit"),
                ("highlighted", "noinherit"),
                ("pointer", "noinherit"),
            ]
        ),
    ).ask()

    if not selected_analysts:  # 处理中途退出
        print("\n操作已取消")
        sys.exit(0)

    # 模型选择逻辑
    if args.ollama:  # 本地模型路径
        model_choice = questionary.select(
            "Ollama模型",
            choices=[questionary.Choice(显示名, 值) for 显示名, 值, _ in OLLAMA_LLM_ORDER]
        ).ask()
        
        if not ensure_ollama_and_model(model_choice):
            print(f"{Fore.RED}需要先配置Ollama环境{Style.RESET_ALL}")
            sys.exit(1)
            
        model_provider = ModelProvider.OLLAMA.value
    else:  # 云端模型路径
        model_choice = questionary.select(
            "云端模型",
            choices=[questionary.Choice(显示名, 值) for 显示名, 值, _ in LLM_ORDER]
        ).ask()
        model_provider = get_model_info(model_choice).provider.value

    # 工作流初始化
    workflow = create_workflow(selected_analysts)
    app = workflow.compile()
    
    # 可视化生成
    if args.show_agent_graph:
        filename = "_".join(selected_analysts) + "_工作流.png"
        save_graph_as_png(app, filename)
        print(f"工作流已保存为 {filename}")

    # 日期处理
    end_date = args.end_date or datetime.now().strftime("%Y-%m-%d")
    start_date = args.start_date or (
        datetime.strptime(end_date, "%Y-%m-%d") - relativedelta(months=3)
    ).strftime("%Y-%m-%d")

    # 投资组合初始化
    portfolio = {
        "cash": args.initial_cash,  # 初始现金
        "margin_requirement": args.margin_requirement,  # 保证金要求
        "margin_used": 0.0,  # 已用保证金总额
        "positions": {  # 持仓明细
            ticker: {
                "long": 0,   # 多头数量
                "short": 0,  # 空头数量
                "long_cost_basis": 0.0,  # 多头平均成本
                "short_cost_basis": 0.0,  # 空头平均成本
                "short_margin_used": 0.0,  # 该标的空头保证金
            } for ticker in args.tickers.split(",")
        },
        "realized_gains": {  # 已实现盈亏
            ticker: {
                "long": 0.0,  # 多头平仓盈亏
                "short": 0.0,  # 空头平仓盈亏
            } for ticker in args.tickers.split(",")
        }
    }

    # 执行交易流程
    result = run_hedge_fund(
        tickers=args.tickers.split(","),
        start_date=start_date,
        end_date=end_date,
        portfolio=portfolio,
        show_reasoning=args.show_reasoning,
        selected_analysts=selected_analysts,
        model_name=model_choice,
        model_provider=model_provider,
    )

    # 显示格式化结果
    print_trading_output(result)

"""
示例输出结构:
{
  "decisions": {
    "AAPL": {
      "action": "买入",
      "quantity": 100,
      "reason": "积极的技术指标和强劲的基本面"
    },
    "TSLA": {
      "action": "卖空",
      "quantity": 50,
      "reason": "超买信号和负面市场情绪"
    }
  },
  "analyst_signals": {
    "technical_analyst": {
      "AAPL": {"score": 0.85, "trend": "看涨"},
      "TSLA": {"score": 0.35, "trend": "看跌"}
    },
    "fundamental_analyst": {
      "AAPL": {"pe_ratio": 25.3, "growth_rate": 0.15},
      "TSLA": {"pe_ratio": 65.2, "growth_rate": 0.08}
    }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

monday_CN

72小时打磨,值得1元认可

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值