人工智能对冲基金
这是人工智能对冲基金的概念验证。该项目旨在探索如何利用人工智能进行交易决策。本项目仅供教育用途,不适用于实际交易或投资。
该系统采用多个代理协同工作:
本杰明·格雷厄姆经纪人——价值投资教父,只购买具有安全边际的隐藏宝石
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}
}
}
}