【保姆级教程】零基础搭建你的专属 AI 金融分析师 (TradingAgents-CN) - 第一篇:部署实战
进入你的 VPS 防火墙设置放行18000端口。访问地址为 http://111.222.333.444:18000,即可打开项目。
前言: 想要拥有一个像华尔街专业分析师一样的 AI 助手吗?它能帮你全天候盯盘、分析财报、评估风险,甚至直接给出操作建议。 哪怕你没有任何编程基础,跟着这篇教程走,30 分钟内你也能拥有一套完全属于自己的 AI 投研系统!
🚀 为什么选择 TradingAgents-CN?
市面上的 AI 很多,但能深度整合金融数据的很少。TradingAgents-CN 是专为中国市场优化的版本,不仅能接入 GPT-5.2、Claude Opus 4.5 等顶尖大脑,还能直接读取 A 股、美股的实时行情和财报数据进行分析。
最重要的是:数据掌握在自己手里,安全、私密、可定制。
🛠️ 第一阶段:准备工作
1. 准备一台服务器 (VPS)
对于新手,我们推荐使用 Linux 服务器。由于我们要使用 LLM Hub 解决网络问题,所以你从阿里云、腾讯云购买的国内服务器完全可以使用!
- 推荐配置:
- CPU: 2核 及以上
- 内存: 4GB 及以上 (推荐 8GB,运行更流畅)
- 系统: Ubuntu 22.04 LTS (最稳、坑最少)
- 带宽: 3M 及以上

2. 准备 AI“大脑”密钥 (LLM Hub)
想要使用 GPT-5.2、Claude Opus 4.5、Gemini 3 Pro 这些顶尖模型,通常需要去各模型官网分别注册账号,不仅繁琐,还面临网络访问和封号难题。
本教程使用 LLM Hub 聚合平台来解决这些问题。它最大的优势是:
- 一站式接入:一个账号就能同时使用 OpenAI、Claude、Gemini 以及国内 Qwen、DeepSeek 等主流大模型。
- 免去繁琐注册:不需要你去申请 OpenAI 账号或绑国外信用卡,直接使用 LLM Hub 提供的密钥即可。
- 稳定高速:专为国内开发者优化,无需魔法上网,支持支付宝支付。
- 访问 LLM Hub 官网 注册账号。
- 在后台创建令牌 (Token),复制
sk-开头的密钥。
3. 安装服务器管家 (1Panel)
登录服务器终端(SSH),执行以下命令安装 1Panel:
# 1. 更新系统软件包 sudo apt update && sudo apt upgrade -y # 2. 安装 1Panel 面板 bash -c "$(curl -sSL https://resource.fit2cloud.com/1panel/package/v2/quick_start.sh)"
安装完成后,登录 1Panel 面板,你就会拥有一个可视化的管理后台。
🏗️ 第二阶段:安装基础软件 (数据库)
为了让系统更稳定,我们通过 1Panel 的应用商店来独立部署数据库。
1. 安装 Redis
- 进入 1Panel 应用商店,搜索
Redis。 - 点击安装。
- 关键设置:
- 版本:选最新的 8.x。
- 容器名称:1panel-redis,稍后要用。
- 密码:1Panel 自动生成密码,务必记下来!

2. 安装 MongoDB
- 在 应用商店 搜索
MongoDB。 - 点击安装。
- 关键设置:
- 版本:选最新的 8.x。
- 容器名称:1panel-mongodb,稍后要用。
- Root 用户名与密码:1Panel 自动生成用户名和密码,务必记下来!

⚡️ 第三阶段:部署 TradingAgents-CN
1. 创建项目目录
在 1Panel 的【主机】->【文件】管理中,逐级进入目录:/opt/1panel/docker/compose。 【创建文件夹】,命名为 tradingagents-cn,并进入该目录。
2. 创建核心配置文件
在 tradingagents-cn 目录下,我们需要手动创建两个子文件夹和几个文件。
步骤 2.1:创建 Nginx 配置
- 新建文件夹:
nginx - 进入
nginx文件夹,新建文件:nginx.conf - 填入以下内容:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://frontend:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /api/ {
proxy_pass http://backend:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
步骤 2.2:创建初始化脚本
- 回到
tradingagents-cn根目录。 - 新建文件夹:
scripts - 进入
scripts文件夹,新建文件:import_config_and_create_user.py - 填入以下内容:
#!/usr/bin/env python3
"""
导入配置数据并创建默认用户
功能:
1. 从导出的 JSON 文件导入配置数据到 MongoDB
2. 创建默认管理员用户(admin/admin123)
3. 支持选择性导入集合
4. 支持覆盖或跳过已存在的数据
使用方法:
python scripts/import_config_and_create_user.py <export_file.json>
python scripts/import_config_and_create_user.py <export_file.json> --overwrite
python scripts/import_config_and_create_user.py <export_file.json> --collections system_configs users
"""
import json
import sys
import hashlib
from datetime import datetime
from pathlib import Path
from typing import List, Dict, Any, Optional
import argparse
import os
# 添加项目根目录到路径
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))
from pymongo import MongoClient
from bson import ObjectId
def load_env_config(script_dir: Path) -> dict:
"""从 .env 文件加载配置
Args:
script_dir: 脚本所在目录
Returns:
配置字典,包含 mongodb_port 等
"""
# 查找 .env 文件(在项目根目录)
env_file = script_dir.parent / '.env'
# 优先从系统环境变量获取(适配 Docker 环境)
config = {
'mongodb_port': int(os.environ.get('MONGODB_PORT', 27017)),
'mongodb_host': os.environ.get('MONGODB_HOST', 'localhost'),
'mongodb_username': os.environ.get('MONGODB_USERNAME', 'admin'),
'mongodb_password': os.environ.get('MONGODB_PASSWORD', 'tradingagents123'),
'mongodb_database': os.environ.get('MONGODB_DATABASE', 'tradingagents')
}
# 如果系统环境变量中没有设置(例如本地开发),则尝试读取 .env 文件覆盖
# 注意:这里逻辑改为“只有当环境变量未设置时才从文件读”或者“文件作为补充”
# 但为了简单且安全,我们保持“系统环境变量优先”。
# 如果脚本在容器外运行且没有设置环境变量,下面的 .env 读取逻辑会生效(覆盖默认值,但不覆盖已有的os.environ值)
if env_file.exists():
try:
file_config = {}
with open(env_file, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if not line or line.startswith('#'):
continue
if '=' in line:
key, value = line.split('=', 1)
key = key.strip()
value = value.strip()
file_config[key] = value
# 仅当 config 中的值为默认值(或空)时,才使用文件中的值
# 或者,更简单的逻辑:如果 os.environ 没取到(即使用了默认值),则尝试用文件值
# 但由于 os.environ.get 已经给了默认值,这里我们做个判断:
if 'MONGODB_PORT' not in os.environ and 'MONGODB_PORT' in file_config:
config['mongodb_port'] = int(file_config['MONGODB_PORT'])
# 对其他字段同理,只有环境变量未设置时才采纳文件配置
if 'MONGODB_HOST' not in os.environ and 'MONGODB_HOST' in file_config:
config['mongodb_host'] = file_config['MONGODB_HOST']
if 'MONGODB_USERNAME' not in os.environ and 'MONGODB_USERNAME' in file_config:
config['mongodb_username'] = file_config['MONGODB_USERNAME']
if 'MONGODB_PASSWORD' not in os.environ and 'MONGODB_PASSWORD' in file_config:
config['mongodb_password'] = file_config['MONGODB_PASSWORD']
except Exception as e:
print(f"⚠️ 警告: 读取 .env 文件失败: {e}")
else:
# 仅在非Docker环境且无env文件时提示警告
if not os.environ.get("DOCKER_CONTAINER"):
print(f"⚠️ 警告: .env 文件不存在: {env_file}")
return config
# MongoDB 连接配置
# Docker 内部运行时使用服务名 "mongodb"
# 宿主机运行时使用 "localhost"
DB_NAME = "tradingagents"
# 默认管理员用户
DEFAULT_ADMIN = {
"username": "admin",
"password": "admin123",
"email": "admin@tradingagents.cn"
}
# 配置集合列表
CONFIG_COLLECTIONS = [
"system_configs",
"users",
"llm_providers",
"market_categories",
"user_tags",
"datasource_groupings",
"platform_configs",
"user_configs",
"model_catalog"
]
def hash_password(password: str) -> str:
"""使用 SHA256 哈希密码(与系统一致)"""
return hashlib.sha256(password.encode()).hexdigest()
def convert_to_bson(data: Any) -> Any:
"""将 JSON 数据转换为 BSON 兼容格式"""
if isinstance(data, dict):
result = {}
for key, value in data.items():
# 处理 ObjectId
if key == "_id" or key.endswith("_id"):
if isinstance(value, str) and len(value) == 24:
try:
result[key] = ObjectId(value)
continue
except:
pass
# 处理日期时间
if key.endswith("_at") or key in ["created_at", "updated_at", "last_login", "added_at"]:
if isinstance(value, str):
try:
result[key] = datetime.fromisoformat(value.replace('Z', '+00:00'))
continue
except:
pass
result[key] = convert_to_bson(value)
return result
elif isinstance(data, list):
return [convert_to_bson(item) for item in data]
else:
return data
def load_export_file(file_path: str) -> Dict[str, Any]:
"""加载导出的 JSON 文件"""
print(f"\n📂 加载导出文件: {file_path}")
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
if "export_info" not in data or "data" not in data:
print("❌ 错误: 文件格式不正确,缺少 export_info 或 data 字段")
sys.exit(1)
export_info = data["export_info"]
print(f"✅ 文件加载成功")
print(f" 导出时间: {export_info.get('created_at', 'Unknown')}")
print(f" 导出格式: {export_info.get('format', 'Unknown')}")
print(f" 集合数量: {len(export_info.get('collections', []))}")
return data
except FileNotFoundError:
print(f"❌ 错误: 文件不存在: {file_path}")
sys.exit(1)
except json.JSONDecodeError as e:
print(f"❌ 错误: JSON 解析失败: {e}")
sys.exit(1)
except Exception as e:
print(f"❌ 错误: 加载文件失败: {e}")
sys.exit(1)
def connect_mongodb(use_docker: bool = True, config: dict = None) -> MongoClient:
"""连接到 MongoDB
Args:
use_docker: True=在 Docker 容器内运行(使用 mongodb 服务名)
False=在宿主机运行(使用 localhost)
config: 配置字典,包含端口等信息
"""
if config is None:
config = {
'mongodb_port': 27017,
'mongodb_host': 'localhost',
'mongodb_username': 'admin',
'mongodb_password': 'tradingagents123',
'mongodb_database': 'tradingagents'
}
# 构建 MongoDB URI
host = 'mongodb' if use_docker else config['mongodb_host']
port = config['mongodb_port']
username = config['mongodb_username']
password = config['mongodb_password']
database = config['mongodb_database']
mongo_uri = f"mongodb://{username}:{password}@{host}:{port}/{database}?authSource=admin"
env_name = "Docker 容器内" if use_docker else "宿主机"
print(f"\n🔌 连接到 MongoDB ({env_name})...")
print(f" URI: mongodb://{username}:***@{host}:{port}/{database}?authSource=admin")
try:
client = MongoClient(mongo_uri, serverSelectionTimeoutMS=5000)
# 测试连接
client.admin.command('ping')
print(f"✅ MongoDB 连接成功")
return client
except Exception as e:
print(f"❌ 错误: MongoDB 连接失败: {e}")
if use_docker:
print(f" 请确保在 Docker 容器内运行,或使用 --host 参数在宿主机运行")
print(f" 检查容器: docker ps | grep mongodb")
else:
print(f" 请确保 MongoDB 正在运行并监听端口 {port}")
print(f" 检查端口: netstat -an | findstr {port}")
sys.exit(1)
def import_collection(
db: Any,
collection_name: str,
documents: List[Dict[str, Any]],
overwrite: bool = False
) -> Dict[str, int]:
"""导入单个集合"""
collection = db[collection_name]
# 转换文档格式
converted_docs = [convert_to_bson(doc) for doc in documents]
if overwrite:
# 覆盖模式:删除现有数据
result = collection.delete_many({})
deleted_count = result.deleted_count
if converted_docs:
result = collection.insert_many(converted_docs)
inserted_count = len(result.inserted_ids)
else:
inserted_count = 0
return {
"deleted": deleted_count,
"inserted": inserted_count,
"skipped": 0
}
else:
# 增量模式:跳过已存在的文档
inserted_count = 0
skipped_count = 0
for doc in converted_docs:
# 检查是否已存在(根据 _id 或 username)
query = {}
if "_id" in doc:
query["_id"] = doc["_id"]
elif "username" in doc:
query["username"] = doc["username"]
elif "name" in doc:
query["name"] = doc["name"]
else:
# 没有唯一标识,直接插入
collection.insert_one(doc)
inserted_count += 1
continue
existing = collection.find_one(query)
if existing:
skipped_count += 1
else:
collection.insert_one(doc)
inserted_count += 1
return {
"deleted": 0,
"inserted": inserted_count,
"skipped": skipped_count
}
def create_default_admin(db: Any, overwrite: bool = False) -> bool:
"""创建默认管理员用户"""
print(f"\n👤 创建默认管理员用户...")
users_collection = db.users
# 检查用户是否已存在
existing_user = users_collection.find_one({"username": DEFAULT_ADMIN["username"]})
if existing_user:
if not overwrite:
print(f"⚠️ 用户 '{DEFAULT_ADMIN['username']}' 已存在,跳过创建")
return False
else:
print(f"⚠️ 用户 '{DEFAULT_ADMIN['username']}' 已存在,将覆盖")
users_collection.delete_one({"username": DEFAULT_ADMIN["username"]})
# 创建用户文档
user_doc = {
"username": DEFAULT_ADMIN["username"],
"email": DEFAULT_ADMIN["email"],
"hashed_password": hash_password(DEFAULT_ADMIN["password"]),
"is_active": True,
"is_verified": True,
"is_admin": True,
"created_at": datetime.utcnow(),
"updated_at": datetime.utcnow(),
"last_login": None,
"preferences": {
"default_market": "A股",
"default_depth": "深度",
"ui_theme": "light",
"language": "zh-CN",
"notifications_enabled": True,
"email_notifications": False
},
"daily_quota": 10000,
"concurrent_limit": 10,
"total_analyses": 0,
"successful_analyses": 0,
"failed_analyses": 0,
"favorite_stocks": []
}
users_collection.insert_one(user_doc)
print(f"✅ 默认管理员用户创建成功")
print(f" 用户名: {DEFAULT_ADMIN['username']}")
print(f" 密码: {DEFAULT_ADMIN['password']}")
print(f" 邮箱: {DEFAULT_ADMIN['email']}")
print(f" 角色: 管理员")
return True
def ensure_new_providers(db: Any):
"""确保新加入的 Provider 存在于数据库中(兼容旧导出文件)"""
print(f"\n✨ 检查并补充缺失的新 Provider...")
providers_collection = db.llm_providers
now = datetime.utcnow()
# 新 Provider 定义列表
new_providers = [
{
"name": "oneapi",
"display_name": "LLM Hub",
"description": "LLM Hub 一站式人工智能集成平台",
"website": "https://www.llmhub.com.cn",
"api_doc_url": "https://docs.llmhub.com.cn/",
"default_base_url": "https://api.llmhub.com.cn/v1",
"is_active": True,
"supported_features": ["chat", "completion", "embedding", "image", "vision", "function_calling", "streaming"],
"is_aggregator": True,
"aggregator_type": "openai_compatible",
"logo_url": "/assets/logos/oneapi.png"
}
]
added_count = 0
for provider in new_providers:
# 检查是否存在
existing = providers_collection.find_one({"name": provider["name"]})
if not existing:
# 补全时间字段
provider["created_at"] = now
provider["updated_at"] = now
provider["extra_config"] = {}
# 插入
providers_collection.insert_one(provider)
print(f" ➕ 已自动补全: {provider['display_name']} ({provider['name']})")
added_count += 1
else:
# 可选:如果存在但不是聚合类型,更新它
if not existing.get("is_aggregator"):
providers_collection.update_one(
{"_id": existing["_id"]},
{"$set": {"is_aggregator": True, "aggregator_type": "openai_compatible"}}
)
print(f" 🔄 已更新以支持聚合模式: {provider['display_name']}")
if added_count == 0:
print(" ✅ 所有新 Provider 已存在,无需补充")
else:
print(f" 🎉 成功补全 {added_count} 个 Provider")
def main():
"""主函数"""
parser = argparse.ArgumentParser(
description="导入配置数据并创建默认用户",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
示例:
# 在 Docker 容器内运行(默认)
python scripts/import_config_and_create_user.py
# 在宿主机运行(连接到 localhost:27017)
python scripts/import_config_and_create_user.py --host
# 从指定文件导入(默认覆盖模式)
python scripts/import_config_and_create_user.py export.json
# 增量模式:跳过已存在的数据
python scripts/import_config_and_create_user.py --incremental
# 只导入指定的集合
python scripts/import_config_and_create_user.py --collections system_configs users
# 只创建默认用户,不导入数据
python scripts/import_config_and_create_user.py --create-user-only
"""
)
parser.add_argument(
"export_file",
nargs="?",
help="导出的 JSON 文件路径(默认:install/database_export_config_*.json)"
)
parser.add_argument(
"--host",
action="store_true",
help="在宿主机运行(连接 localhost:27017),默认在 Docker 容器内运行(连接 mongodb:27017)"
)
parser.add_argument(
"--overwrite",
action="store_true",
default=True,
help="覆盖已存在的数据(默认:覆盖)"
)
parser.add_argument(
"--incremental",
action="store_true",
help="增量模式:跳过已存在的数据"
)
parser.add_argument(
"--collections",
nargs="+",
help="指定要导入的集合(默认:所有配置集合)"
)
parser.add_argument(
"--create-user-only",
action="store_true",
help="只创建默认用户,不导入数据"
)
parser.add_argument(
"--skip-user",
action="store_true",
help="跳过创建默认用户"
)
parser.add_argument(
"--mongodb-port",
type=int,
help="MongoDB 端口(覆盖 .env 配置)"
)
parser.add_argument(
"--mongodb-host",
type=str,
help="MongoDB 主机(覆盖 .env 配置)"
)
args = parser.parse_args()
# 处理 incremental 参数(如果指定了 --incremental,则 overwrite 为 False)
if args.incremental:
args.overwrite = False
# 如果没有指定文件,尝试从 install 目录查找
if not args.create_user_only and not args.export_file:
install_dir = project_root / "install"
if install_dir.exists():
# 查找 database_export_config_*.json 文件
config_files = list(install_dir.glob("database_export_config_*.json"))
if config_files:
# 使用最新的文件
args.export_file = str(sorted(config_files)[-1])
print(f"💡 未指定文件,使用默认配置: {args.export_file}")
else:
parser.error("install 目录中未找到配置文件 (database_export_config_*.json)")
else:
parser.error("必须提供导出文件路径,或使用 --create-user-only")
print("=" * 80)
print("📦 导入配置数据并创建默认用户")
print("=" * 80)
# 加载 .env 配置
script_dir = Path(__file__).parent
env_config = load_env_config(script_dir)
# 命令行参数覆盖 .env 配置
if args.mongodb_port:
env_config['mongodb_port'] = args.mongodb_port
print(f"💡 使用命令行指定的 MongoDB 端口: {args.mongodb_port}")
if args.mongodb_host:
env_config['mongodb_host'] = args.mongodb_host
print(f"💡 使用命令行指定的 MongoDB 主机: {args.mongodb_host}")
# 连接数据库
use_docker = not args.host # 默认在 Docker 内运行,除非指定 --host
client = connect_mongodb(use_docker=use_docker, config=env_config)
db = client[DB_NAME]
# 导入数据
if not args.create_user_only:
# 加载导出文件
export_data = load_export_file(args.export_file)
data = export_data["data"]
# 确定要导入的集合
if args.collections:
collections_to_import = args.collections
else:
collections_to_import = [c for c in CONFIG_COLLECTIONS if c in data]
print(f"\n📋 准备导入 {len(collections_to_import)} 个集合:")
for col in collections_to_import:
doc_count = len(data.get(col, []))
print(f" - {col}: {doc_count} 个文档")
# 导入集合
print(f"\n🚀 开始导入...")
print(f" 模式: {'覆盖' if args.overwrite else '增量'}")
total_stats = {
"deleted": 0,
"inserted": 0,
"skipped": 0
}
for collection_name in collections_to_import:
if collection_name not in data:
print(f"⚠️ 跳过 {collection_name}: 导出文件中不存在")
continue
documents = data[collection_name]
print(f"\n 导入 {collection_name}...")
try:
stats = import_collection(db, collection_name, documents, args.overwrite)
total_stats["deleted"] += stats["deleted"]
total_stats["inserted"] += stats["inserted"]
total_stats["skipped"] += stats["skipped"]
if args.overwrite:
print(f" ✅ 删除 {stats['deleted']} 个,插入 {stats['inserted']} 个")
else:
print(f" ✅ 插入 {stats['inserted']} 个,跳过 {stats['skipped']} 个")
except Exception as e:
print(f" ❌ 失败: {e}")
print(f"\n📊 导入统计:")
if args.overwrite:
print(f" 删除: {total_stats['deleted']} 个文档")
print(f" 插入: {total_stats['inserted']} 个文档")
if not args.overwrite:
print(f" 跳过: {total_stats['skipped']} 个文档")
# 创建默认用户
if not args.skip_user:
create_default_admin(db, args.overwrite)
# 🟢 确保新加入的 Provider (OneAPI, NewAPI, 302.AI) 存在
# 这是为了兼容旧的导出文件,防止新功能缺失
ensure_new_providers(db)
# 关闭连接
client.close()
print("\n" + "=" * 80)
print("✅ 操作完成!")
print("=" * 80)
if not args.skip_user:
print(f"\n🔐 登录信息:")
print(f" 用户名: {DEFAULT_ADMIN['username']}")
print(f" 密码: {DEFAULT_ADMIN['password']}")
print(f"\n📝 后续步骤:")
print(f" 1. 重启后端服务: docker restart tradingagents-backend")
print(f" 2. 访问前端并使用默认账号登录")
print(f" 3. 检查系统配置是否正确加载")
if __name__ == "__main__":
main()
3. 配置连接 (最关键的一步!)
回到 tradingagents-cn 目录(即 /opt/1panel/docker/compose/tradingagents-cn),我们需要创建环境变量文件。
步骤 3.1:创建 .env 文件: 新建文件 .env,填入以下配置(请自行替换数据库信息):
# TradingAgents-CN 生产环境配置 (.env)
# 专为 1Panel 集成设计
# ==================== 1. 核心连接配置 ====================
# ⚠️ 注意:必须填写正确的容器名称 (1Panel 创建的容器通常有随机后缀)
# 请在 1Panel 容器列表或终端使用 `docker ps` 查看准确名称并填入下方
# MongoDB 配置 (外部)
MONGODB_ENABLED=true
# 填入 MongoDB 容器名称 (例如: 1panel-mongodb)
MONGODB_HOST=1Panel-mongodb
MONGODB_PORT=27017
MONGODB_USERNAME=mongo_zetJdx
MONGODB_PASSWORD=mongo_WHdXh8
MONGODB_DATABASE=tradingagents
MONGODB_AUTH_SOURCE=admin
# 连接字符串 (格式: mongodb://用户:密码@容器名:端口/数据库?authSource=admin)
# 请同步修改下方的容器名
MONGODB_CONNECTION_STRING=mongodb://mongo_zetJdx:mongo_WHdXh8@1Panel-mongodb:27017/tradingagents?authSource=admin
# Redis 配置 (外部)
REDIS_ENABLED=true
# 填入 Redis 容器名称 (例如: 1panel-redis)
REDIS_HOST=1Panel-redis
REDIS_PORT=6379
REDIS_PASSWORD=redis_3wPzP3
# 连接字符串 (格式: redis://:密码@容器名:6379/0)
REDIS_URL=redis://:redis_3wPzP3@1Panel-redis:6379/0
# ==================== 2. 应用端口 ====================
# 暴露给宿主机的端口,1Panel OpenResty 将反代此端口
APP_PORT=18000
# ==================== 3. 安全配置 (必须修改) ====================
# 生成新密钥: openssl rand -hex 32
JWT_SECRET=334a40eb30d222bee16de8ac34b6ad9af9f25cc3c7e1ed2df536401ea9f88446
CSRF_SECRET=a97e64c9678b6c3948dc0d18072753df55303592ca6aa65c6337dcc4d90638b1
ACCESS_TOKEN_EXPIRE_MINUTES=480
# ==================== 4. API 密钥 (按需填写) ====================
# DeepSeek (推荐)
DEEPSEEK_API_KEY=
DEEPSEEK_ENABLED=false
# DashScope (阿里百炼)
DASHSCOPE_API_KEY=
DASHSCOPE_ENABLED=false
# OpenAI
OPENAI_API_KEY=
OPENAI_ENABLED=false
# ==================== 5. 聚合渠道配置 (LLM Hub) ====================
ONEAPI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ONEAPI_BASE_URL=https://api.llmhub.com.cn/v1
# ==================== 6. 数据源配置 ====================
TUSHARE_TOKEN=
TUSHARE_ENABLED=false
# ==================== 6. 系统参数 ====================
TZ=Asia/Shanghai
TRADINGAGENTS_LOG_LEVEL=INFO
# 生产环境通常不需要这些
DEBUG=false
PYTHONDONTWRITEBYTECODE=1
步骤 3.2:创建.docker-compose.yml文件: 新建文件.docker-compose.yml,填入以下配置
services:
# 后端服务
backend:
image: hsliup/tradingagents-backend:v1.0.0-preview
container_name: tradingagents-backend
restart: always
expose:
- "8000"
volumes:
- ./logs:/app/logs
- ./data:/app/data
# 挂载修改后的初始化脚本覆盖镜像内的版本
- ./scripts/import_config_and_create_user.py:/app/scripts/import_config_and_create_user.py
env_file:
- .env
networks:
- 1panel-network
deploy:
resources:
limits:
memory: 2G
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/api/health"]
interval: 30s
timeout: 10s
retries: 3
# 前端服务
frontend:
image: hsliup/tradingagents-frontend:v1.0.0-preview
container_name: tradingagents-frontend
restart: always
expose:
- "80"
environment:
# 前端只需知道它被代理在 /api 下访问后端,通常不需要改
VITE_API_BASE_URL: "/api"
networks:
- 1panel-network
healthcheck:
test:
[
"CMD",
"wget",
"--quiet",
"--tries=1",
"--spider",
"http://localhost:80",
]
interval: 30s
timeout: 10s
retries: 3
# 应用网关 (Nginx)
nginx:
image: nginx:alpine
container_name: tradingagents-nginx
restart: always
ports:
# 映射到宿主机端口,供 1Panel OpenResty 反代
- "${APP_PORT:-18000}:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./logs/nginx:/var/log/nginx
networks:
- 1panel-network
depends_on:
- backend
- frontend
networks:
# 引用外部 1Panel 网络
1panel-network:
external: true
4. 启动应用
在终端执行:
# 进入 /opt/1panel/docker/compose/tradingagents-cn
cd /opt/1panel/docker/compose/tradingagents-cn
# 指定生产环境文件启动
docker compose --env-file .env up -d
(注意:容器会自动加入 1Panel 的内部网络,从而能连上刚才安装的 Redis 和 MongoDB)
等待日志显示 Done。
5. 初始化数据


看到 ✅ 操作完成 即大功告成!
最后一步:防火墙放行端口

进入你的 VPS 防火墙设置放行 18000 端口。
访问地址为 http://111.222.333.444:18000,即可打开项目。
更多推荐



所有评论(0)