This commit is contained in:
aaron 2025-04-28 14:53:05 +08:00
parent bc7b095f40
commit 9f989ce9bb
11 changed files with 636 additions and 22 deletions

24
crontab_setup.txt Normal file
View File

@ -0,0 +1,24 @@
# 加密货币智能体 crontab 配置示例
# 将以下内容添加到crontab中: crontab -e
# 设置环境变量
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
PYTHONPATH=/path/to/your/cryptoai
# 日志文件
LOGFILE=/path/to/your/cryptoai/logs/cron.log
# 每天早上8:30运行加密货币智能体
30 8 * * * cd /path/to/your/cryptoai && python run.py --agent crypto --run-once >> $LOGFILE 2>&1
# 每天晚上20:30运行黄金智能体
30 20 * * * cd /path/to/your/cryptoai && python run.py --agent gold --run-once >> $LOGFILE 2>&1
# 每6小时运行一次加密货币智能体
0 */6 * * * cd /path/to/your/cryptoai && python run.py --agent crypto --run-once >> $LOGFILE 2>&1
# 每周一早上9点运行完整分析
0 9 * * 1 cd /path/to/your/cryptoai && python run.py --agent crypto --symbol BTCUSDT --days 90 >> $LOGFILE 2>&1
# 注意:使用前请将路径替换为您实际的项目路径

View File

@ -17,6 +17,7 @@ from api.deepseek_api import DeepSeekAPI
from models.data_processor import DataProcessor
from utils.config_loader import ConfigLoader
from utils.dingtalk_bot import DingTalkBot
from utils.db_manager import get_db_manager
class CryptoAgent:
@ -73,6 +74,9 @@ class CryptoAgent:
)
print("钉钉机器人已启用")
# 初始化数据库管理器
self.db_manager = get_db_manager()
# 设置支持的加密货币
self.base_currencies = self.crypto_config['base_currencies']
self.quote_currency = self.crypto_config['quote_currency']
@ -283,6 +287,22 @@ class CryptoAgent:
"timestamp": datetime.now().isoformat()
}
# 保存分析结果到数据库
try:
# 保存到数据库
saved = self.db_manager.save_analysis_result(
agent='crypto',
symbol=symbol,
time_interval=self.time_interval,
analysis_result=analysis_result
)
if saved:
print(f"{symbol}分析结果已保存到数据库")
else:
print(f"{symbol}分析结果保存到数据库失败")
except Exception as e:
print(f"保存{symbol}分析结果到数据库时出错: {e}")
# 如果钉钉机器人已启用,发送分析报告
if self.dingtalk_bot:
try:

View File

@ -4,14 +4,21 @@ binance:
api_secret: "your_binance_api_secret_here"
test_mode: true # 设置为false将使用实盘交易
# OKX API设置
okx:
api_key: "your_okx_api_key"
api_secret: "your_okx_api_secret"
passphrase: "your_okx_passphrase"
test_mode: false # 设置为true使用测试网络
# DeepSeek AI设置
deepseek:
api_key: "your_deepseek_api_key_here"
api_key: "your_deepseek_api_key"
model: "deepseek-chat" # 使用的模型
# AllTick API设置用于获取黄金数据
alltick:
api_key: "6c7ba077eee07f6f270e219d4848700e-c-app"
api_key: "your_alltick_api_key"
symbols:
- "XAUUSD" # 黄金/美元
# - "XAGUSD" # 白银/美元
@ -19,18 +26,21 @@ alltick:
# 加密货币设置
crypto:
base_currencies:
# - "BTC"
- "BTC"
- "ETH"
# - "BNB"
- "BNB"
- "SOL"
# - "ADA"
- "ARB"
quote_currency: "USDT"
time_interval: "4h" # 可选: 1m, 5m, 15m, 30m, 1h, 4h, 1d
time_interval: "1d" # 支持: 1m, 5m, 15m, 30m, 1h, 2h, 4h, 1d, 1w, 1M
min_data_points: 100 # 最小数据点数量不应小于30
# 黄金市场分析配置
gold:
# 黄金交易对
symbols: ["XAUUSD"]
symbols:
- "GOLD"
- "SILVER"
# 历史数据天数
historical_days: 180
# 时间间隔
@ -45,7 +55,7 @@ gold:
# 数据设置
data:
storage_path: "./cryptoai/data"
historical_days: 30
historical_days: 60 # 历史数据获取天数
update_interval: 60 # 数据更新间隔(分钟)
# Agent设置
@ -53,9 +63,10 @@ agent:
analysis_interval: 120 # 分析间隔(分钟)
strategies:
- "trend_following"
- "momentum"
- "sentiment"
risk_level: "medium" # 可选: low, medium, high
- "mean_reversion"
- "breakout"
- "rsi_strategy"
risk_level: "medium" # 风险等级: low, medium, high
# 日志设置
logging:
@ -64,8 +75,16 @@ logging:
# 钉钉机器人设置
dingtalk:
enabled: true # 是否启用钉钉机器人
webhook_url: "https://oapi.dingtalk.com/robot/send?access_token=your_dingtalk_token_here"
secret: "your_dingtalk_secret_here" # 如果没有设置安全设置,可以为空
enabled: false # 是否启用钉钉通知
webhook_url: "https://oapi.dingtalk.com/robot/send?access_token=your_access_token"
secret: "your_secret" # 如果使用了加签安全设置,请填写此项
at_mobiles: [] # 需要@的手机号列表
at_all: false # 是否@所有人
at_all: false # 是否@所有人
# 数据库配置
database:
host: "gz-cynosdbmysql-grp-2j1cnopr.sql.tencentcdb.com"
port: 27469
user: "root"
password: "Aa#223388"
db_name: "cryptoai"

View File

@ -6,9 +6,9 @@ binance:
# OKX API设置
okx:
api_key: "your_okx_api_key_here"
api_secret: "your_okx_api_secret_here"
passphrase: "your_okx_passphrase_here"
api_key: "7abe4037-3d93-40d4-a77b-c77f4a1e9490"
api_secret: "654946A2045F44CC2853D47F96C62F4E"
passphrase: "Aa@123456"
test_mode: true # 设置为false将使用实盘交易
# DeepSeek AI设置
@ -26,11 +26,12 @@ alltick:
# 加密货币设置
crypto:
base_currencies:
# - "ONDO"
- "BTC"
# - "ETH"
# - "BNB"
# - "SOL"
- "SUI"
# - "SUI"
# - "WLD"
quote_currency: "USDT"
time_interval: "4h" # 可选: 1m, 5m, 15m, 30m, 1h, 4h, 1d
@ -75,4 +76,12 @@ dingtalk:
webhook_url: "https://oapi.dingtalk.com/robot/send?access_token=2278b723cd363bb6f85592c743b59b166e70b9e02a275bb5cedbc33b53a5cbdc"
secret: "your_secret" # 如果没有设置安全设置,可以为空
at_mobiles: [] # 需要@的手机号列表
at_all: false # 是否@所有人
at_all: false # 是否@所有人
# 数据库配置
database:
host: "gz-cynosdbmysql-grp-2j1cnopr.sql.tencentcdb.com"
port: 27469
user: "root"
password: "Aa#223388"
db_name: "cryptoai"

View File

@ -0,0 +1,263 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import json
import logging
from typing import Dict, Any, List, Optional, Union
from datetime import datetime
from sqlalchemy import create_engine, Column, Integer, String, Text, DateTime, Index, text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy.dialects.mysql import JSON
from sqlalchemy.pool import QueuePool
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger('db_manager')
# 创建模型基类
Base = declarative_base()
# 定义分析结果模型
class AnalysisResult(Base):
"""分析结果表模型"""
__tablename__ = 'analysis_results'
id = Column(Integer, primary_key=True, autoincrement=True)
agent = Column(String(50), nullable=False, comment='智能体类型(crypto, gold)')
symbol = Column(String(50), nullable=False, comment='交易对符号')
time_interval = Column(String(20), nullable=False, comment='时间间隔')
completion_result = Column(JSON, nullable=False, comment='分析结果JSON')
created_at = Column(DateTime, nullable=False, default=datetime.now, comment='创建时间')
updated_at = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment='更新时间')
# 索引
__table_args__ = (
Index('idx_agent', 'agent'),
Index('idx_symbol', 'symbol'),
Index('idx_time_interval', 'time_interval'),
Index('idx_created_at', 'created_at'),
)
class DBManager:
"""数据库管理工具用于连接MySQL数据库并保存智能体分析结果"""
def __init__(self, host: str, port: int, user: str, password: str, db_name: str):
"""
初始化数据库管理器
Args:
host: 数据库主机地址
port: 数据库端口
user: 用户名
password: 密码
db_name: 数据库名
"""
self.host = host
self.port = port
self.user = user
self.password = password
self.db_name = db_name
self.engine = None
self.Session = None
# 初始化数据库连接
self._init_db()
def _init_db(self) -> None:
"""初始化数据库连接和表"""
try:
# 创建数据库连接
connection_string = f"mysql+pymysql://{self.user}:{self.password}@{self.host}:{self.port}/{self.db_name}?charset=utf8mb4"
# 创建引擎,设置连接池
self.engine = create_engine(
connection_string,
echo=False, # 设置为True可以输出SQL语句调试用
pool_size=5, # 连接池大小
max_overflow=10, # 最大溢出连接数
pool_timeout=30, # 连接超时时间
pool_recycle=1800, # 连接回收时间(秒)
pool_pre_ping=True # 在使用连接前先ping一下确保连接有效
)
# 创建会话工厂
self.Session = sessionmaker(bind=self.engine)
# 创建表(如果不存在)
Base.metadata.create_all(self.engine)
logger.info(f"成功连接到数据库 {self.db_name}")
except Exception as e:
logger.error(f"数据库初始化失败: {e}")
self.engine = None
def save_analysis_result(self, agent: str, symbol: str, time_interval: str,
analysis_result: Dict[str, Any]) -> bool:
"""
保存分析结果到数据库
Args:
agent: 智能体类型例如 'crypto' 'gold'
symbol: 交易对符号例如 'BTCUSDT'
time_interval: 时间间隔例如 '1h', '4h', '1d'
analysis_result: 分析结果数据
Returns:
保存是否成功
"""
if not self.engine:
try:
self._init_db()
except Exception as e:
logger.error(f"重新连接数据库失败: {e}")
return False
try:
# 创建会话
session = self.Session()
try:
# 创建新记录
new_result = AnalysisResult(
agent=agent,
symbol=symbol,
time_interval=time_interval,
completion_result=analysis_result,
created_at=datetime.now(),
updated_at=datetime.now()
)
# 添加并提交
session.add(new_result)
session.commit()
logger.info(f"成功保存 {agent} 分析结果,交易对: {symbol}, 时间间隔: {time_interval}")
return True
except Exception as e:
session.rollback()
logger.error(f"保存分析结果失败: {e}")
return False
finally:
session.close()
except Exception as e:
logger.error(f"创建数据库会话失败: {e}")
# 如果是连接错误,尝试重新初始化
try:
self._init_db()
except:
pass
return False
def get_latest_result(self, agent: str, symbol: str, time_interval: str) -> Optional[Dict[str, Any]]:
"""
获取最新的分析结果
Args:
agent: 智能体类型例如 'crypto' 'gold'
symbol: 交易对符号例如 'BTCUSDT'
time_interval: 时间间隔例如 '1h', '4h', '1d'
Returns:
最新分析结果如果查询失败则返回None
"""
if not self.engine:
try:
self._init_db()
except Exception as e:
logger.error(f"重新连接数据库失败: {e}")
return None
try:
# 创建会话
session = self.Session()
try:
# 查询最新的结果
result = session.query(AnalysisResult).filter(
AnalysisResult.agent == agent,
AnalysisResult.symbol == symbol,
AnalysisResult.time_interval == time_interval
).order_by(AnalysisResult.created_at.desc()).first()
if result:
# 转换为字典
return {
'id': result.id,
'agent': result.agent,
'symbol': result.symbol,
'time_interval': result.time_interval,
'completion_result': result.completion_result,
'created_at': result.created_at
}
else:
return None
finally:
session.close()
except Exception as e:
logger.error(f"获取最新分析结果失败: {e}")
return None
def close(self) -> None:
"""关闭数据库连接"""
if self.engine:
self.engine.dispose()
self.engine = None
logger.info("数据库连接已关闭")
# 单例模式
_db_instance = None
def get_db_manager(host: Optional[str] = None,
port: Optional[int] = None,
user: Optional[str] = None,
password: Optional[str] = None,
db_name: Optional[str] = None) -> DBManager:
"""
获取数据库管理器实例单例模式
Args:
host: 数据库主机地址
port: 数据库端口
user: 用户名
password: 密码
db_name: 数据库名
Returns:
数据库管理器实例
"""
global _db_instance
# 如果已经初始化过,直接返回
if _db_instance is not None:
return _db_instance
# 从环境变量获取配置
db_host = host or os.environ.get('DB_HOST', 'gz-cynosdbmysql-grp-2j1cnopr.sql.tencentcdb.com')
db_port = port or int(os.environ.get('DB_PORT', '27469'))
db_user = user or os.environ.get('DB_USER', 'root')
db_password = password or os.environ.get('DB_PASSWORD', 'Aa#223388')
db_name = db_name or os.environ.get('DB_NAME', 'cryptoai')
# 创建实例
_db_instance = DBManager(
host=db_host,
port=db_port,
user=db_user,
password=db_password,
db_name=db_name
)
return _db_instance

View File

@ -12,4 +12,6 @@ aiohttp>=3.8.5
langchain>=0.0.267
pydantic>=2.3.0
fastapi>=0.103.1
uvicorn>=0.23.2
uvicorn>=0.23.2
alltick-api==0.0.1
okx-api==0.0.1

140
schedule_task.py Normal file
View File

@ -0,0 +1,140 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
加密货币分析智能体定时任务
支持以下配置
- 定时执行设置每天指定时间执行分析任务
- 周期执行设置每隔一定时间执行一次分析任务
- 同时支持多个智能体crypto和gold
使用方法
python schedule_task.py # 使用默认配置执行
python schedule_task.py --agent crypto # 指定执行加密货币智能体
python schedule_task.py --agent gold # 指定执行黄金智能体
python schedule_task.py --both # 同时执行两种智能体
python schedule_task.py --time "12:00" # 设置每天执行的时间
python schedule_task.py --interval 240 # 设置执行间隔(分钟)
"""
import os
import sys
import time
import argparse
import schedule
import subprocess
from datetime import datetime
def parse_arguments():
"""解析命令行参数"""
parser = argparse.ArgumentParser(description='加密货币分析智能体定时任务')
parser.add_argument('--agent', type=str, default='crypto',
choices=['crypto', 'gold'],
help='要执行的智能体类型,默认为加密货币智能体')
parser.add_argument('--both', action='store_true',
help='同时执行两种智能体')
parser.add_argument('--time', type=str, default=None,
help='每天执行任务的时间格式为HH:MM例如 "08:30"')
parser.add_argument('--interval', type=int, default=360,
help='自动执行间隔分钟默认为360分钟6小时')
return parser.parse_args()
def run_agent(agent_type='crypto'):
"""
执行智能体
Args:
agent_type: 智能体类型可选 'crypto' 'gold'
"""
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"[{current_time}] 执行{agent_type}智能体...")
try:
# 构建命令
cmd = ["python", "run.py", f"--agent={agent_type}", "--run-once"]
# 执行命令
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True
)
# 实时输出日志
while True:
output = process.stdout.readline()
if output == '' and process.poll() is not None:
break
if output:
print(output.strip())
# 获取执行结果
_, stderr = process.communicate()
# 检查是否有错误
if process.returncode != 0:
print(f"执行{agent_type}智能体时出错: {stderr}")
else:
print(f"[{current_time}] {agent_type}智能体执行完成")
except Exception as e:
print(f"执行{agent_type}智能体时出错: {e}")
def run_both_agents():
"""执行两种智能体"""
run_agent('crypto')
run_agent('gold')
def main():
"""主函数"""
args = parse_arguments()
# 定义任务函数
if args.both:
job_func = run_both_agents
agent_desc = "加密货币和黄金"
else:
job_func = lambda: run_agent(args.agent)
agent_desc = f"{args.agent}分析"
# 根据参数设置定时任务
if args.time:
# 设置每天固定时间执行
schedule.every().day.at(args.time).do(job_func)
print(f"已设置每天 {args.time} 执行{agent_desc}智能体")
else:
# 设置定时间隔执行
schedule.every(args.interval).minutes.do(job_func)
print(f"已设置每 {args.interval} 分钟执行一次{agent_desc}智能体")
# 立即执行一次
print("立即执行一次任务...")
job_func()
# 循环等待下次执行
while True:
# 检查是否有定时任务需要执行
schedule.run_pending()
# 打印下次执行时间
next_run = schedule.next_run().strftime("%Y-%m-%d %H:%M:%S")
print(f"下次执行时间: {next_run}")
# 等待一段时间再检查
time.sleep(60)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n定时任务已停止")
except Exception as e:
print(f"定时任务出错: {e}")
import traceback
traceback.print_exc()

137
schedule_task.sh Executable file
View File

@ -0,0 +1,137 @@
#!/bin/bash
# 加密货币分析智能体定时任务启动脚本
# 该脚本用于在后台启动智能体定时任务
# 使用说明:
# ./schedule_task.sh start crypto 360 # 以360分钟为间隔启动加密货币智能体
# ./schedule_task.sh start gold "08:30" # 每天08:30运行黄金智能体
# ./schedule_task.sh start both 240 # 以240分钟为间隔同时启动两种智能体
# ./schedule_task.sh stop # 停止所有运行中的定时任务
# ./schedule_task.sh status # 查看运行状态
# 获取当前脚本所在目录
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
LOG_DIR="${SCRIPT_DIR}/logs"
SCHEDULE_LOG="${LOG_DIR}/schedule_task.log"
# 确保日志目录存在
mkdir -p "${LOG_DIR}"
# 激活虚拟环境(如果使用了虚拟环境)
VENV_PATH="${SCRIPT_DIR}/venv"
if [ -d "${VENV_PATH}" ]; then
source "${VENV_PATH}/bin/activate"
echo "已激活虚拟环境: ${VENV_PATH}"
fi
# 定义启动定时任务的函数
start_schedule_task() {
local agent_type=$1
local time_or_interval=$2
local cmd="python ${SCRIPT_DIR}/schedule_task.py"
# 如果同时执行两种智能体
if [ "${agent_type}" == "both" ]; then
cmd="${cmd} --both"
else
cmd="${cmd} --agent ${agent_type}"
fi
# 判断第二个参数是时间点还是间隔
if [[ "${time_or_interval}" =~ ^[0-9]+$ ]]; then
# 如果是纯数字,则认为是间隔
cmd="${cmd} --interval ${time_or_interval}"
else
# 否则认为是时间点
cmd="${cmd} --time \"${time_or_interval}\""
fi
# 使用nohup在后台运行
echo "启动定时任务: ${cmd}"
nohup ${cmd} > "${SCHEDULE_LOG}" 2>&1 &
# 保存PID
echo $! > "${SCRIPT_DIR}/.schedule_task.pid"
echo "定时任务已在后台启动PID: $!"
echo "日志文件: ${SCHEDULE_LOG}"
}
# 定义停止定时任务的函数
stop_schedule_task() {
if [ -f "${SCRIPT_DIR}/.schedule_task.pid" ]; then
local pid=$(cat "${SCRIPT_DIR}/.schedule_task.pid")
echo "正在停止定时任务 (PID: ${pid})..."
kill -15 ${pid} 2>/dev/null || echo "进程 ${pid} 不存在"
rm -f "${SCRIPT_DIR}/.schedule_task.pid"
else
echo "没有找到运行中的定时任务"
fi
}
# 定义查看状态的函数
check_status() {
if [ -f "${SCRIPT_DIR}/.schedule_task.pid" ]; then
local pid=$(cat "${SCRIPT_DIR}/.schedule_task.pid")
if ps -p ${pid} > /dev/null; then
echo "定时任务正在运行 (PID: ${pid})"
echo "最近的日志:"
tail -n 20 "${SCHEDULE_LOG}"
else
echo "定时任务已停止 (上次PID: ${pid})"
rm -f "${SCRIPT_DIR}/.schedule_task.pid"
fi
else
echo "没有找到运行中的定时任务"
fi
}
# 主逻辑
case "$1" in
start)
if [ -f "${SCRIPT_DIR}/.schedule_task.pid" ]; then
pid=$(cat "${SCRIPT_DIR}/.schedule_task.pid")
if ps -p ${pid} > /dev/null; then
echo "定时任务已在运行中 (PID: ${pid})"
echo "如需重启,请先执行: $0 stop"
exit 1
else
rm -f "${SCRIPT_DIR}/.schedule_task.pid"
fi
fi
# 检查必要的参数
if [ -z "$2" ]; then
echo "缺少参数: agent_type (crypto, gold 或 both)"
echo "用法: $0 start [agent_type] [time_or_interval]"
exit 1
fi
if [ -z "$3" ]; then
# 使用默认间隔
start_schedule_task "$2" "360"
else
start_schedule_task "$2" "$3"
fi
;;
stop)
stop_schedule_task
;;
status)
check_status
;;
*)
echo "用法: $0 {start|stop|status}"
echo " start [agent_type] [time_or_interval] - 启动定时任务"
echo " agent_type: crypto, gold 或 both"
echo " time_or_interval: 时间点(HH:MM)或间隔(分钟)"
echo " stop - 停止定时任务"
echo " status - 查看运行状态"
exit 1
;;
esac
exit 0