update
This commit is contained in:
parent
284a3f463a
commit
b573ac1dfe
2
.gitignore
vendored
2
.gitignore
vendored
@ -20,6 +20,8 @@ wheels/
|
|||||||
.installed.cfg
|
.installed.cfg
|
||||||
*.egg
|
*.egg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 虚拟环境
|
# 虚拟环境
|
||||||
venv/
|
venv/
|
||||||
ENV/
|
ENV/
|
||||||
|
|||||||
41
README.md
41
README.md
@ -8,7 +8,7 @@
|
|||||||
- 利用DeepSeek大模型进行市场分析和预测
|
- 利用DeepSeek大模型进行市场分析和预测
|
||||||
- 提供市场趋势、价格预测和交易建议
|
- 提供市场趋势、价格预测和交易建议
|
||||||
- 支持多种加密货币分析
|
- 支持多种加密货币分析
|
||||||
- 通过钉钉机器人发送分析结果
|
- 通过钉钉机器人和Discord Webhook发送分析结果
|
||||||
|
|
||||||
## 项目结构
|
## 项目结构
|
||||||
|
|
||||||
@ -98,6 +98,10 @@ OKX_PASSPHRASE=OKX密码
|
|||||||
DINGTALK_ENABLED=true/false
|
DINGTALK_ENABLED=true/false
|
||||||
DINGTALK_WEBHOOK_URL=钉钉Webhook地址
|
DINGTALK_WEBHOOK_URL=钉钉Webhook地址
|
||||||
DINGTALK_SECRET=钉钉密钥
|
DINGTALK_SECRET=钉钉密钥
|
||||||
|
|
||||||
|
# Discord机器人
|
||||||
|
DISCORD_ENABLED=true/false
|
||||||
|
DISCORD_WEBHOOK_URL=Discord Webhook地址
|
||||||
```
|
```
|
||||||
|
|
||||||
在Docker中可以通过`-e`参数或`.env`文件传递环境变量。
|
在Docker中可以通过`-e`参数或`.env`文件传递环境变量。
|
||||||
@ -176,3 +180,38 @@ curl -X POST "http://localhost:8000/api/analyze" \
|
|||||||
"task_type": "市场分析"
|
"task_type": "市场分析"
|
||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 消息通知
|
||||||
|
|
||||||
|
项目支持多种消息通知方式,可以将分析结果发送到不同的平台。
|
||||||
|
|
||||||
|
### 钉钉机器人
|
||||||
|
|
||||||
|
在配置文件中设置钉钉机器人的Webhook URL和密钥,启用后会将分析结果发送到钉钉群聊。
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
dingtalk:
|
||||||
|
enabled: true
|
||||||
|
webhook_url: your_dingtalk_webhook_url
|
||||||
|
secret: your_dingtalk_secret
|
||||||
|
```
|
||||||
|
|
||||||
|
### Discord机器人
|
||||||
|
|
||||||
|
在配置文件中设置Discord Webhook URL,启用后会将分析结果以精美的嵌入式消息发送到Discord频道。
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
discord:
|
||||||
|
enabled: true
|
||||||
|
webhook_url: your_discord_webhook_url
|
||||||
|
username: CryptoAI分析机器人
|
||||||
|
avatar_url: https://cdn-icons-png.flaticon.com/512/2878/2878497.png
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 测试Discord机器人
|
||||||
|
|
||||||
|
可以使用以下命令测试Discord机器人的功能:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m cryptoai.tests.test_discord_bot --webhook your_webhook_url
|
||||||
|
```
|
||||||
Binary file not shown.
Binary file not shown.
@ -18,7 +18,7 @@ from models.data_processor import DataProcessor
|
|||||||
from utils.config_loader import ConfigLoader
|
from utils.config_loader import ConfigLoader
|
||||||
from utils.dingtalk_bot import DingTalkBot
|
from utils.dingtalk_bot import DingTalkBot
|
||||||
from utils.db_manager import get_db_manager
|
from utils.db_manager import get_db_manager
|
||||||
|
from utils.discord_bot import DiscordBot
|
||||||
|
|
||||||
class CryptoAgent:
|
class CryptoAgent:
|
||||||
"""加密货币智能体,用于分析市场数据并生成交易策略"""
|
"""加密货币智能体,用于分析市场数据并生成交易策略"""
|
||||||
@ -40,6 +40,7 @@ class CryptoAgent:
|
|||||||
self.crypto_config = self.config_loader.get_crypto_config()
|
self.crypto_config = self.config_loader.get_crypto_config()
|
||||||
self.data_config = self.config_loader.get_data_config()
|
self.data_config = self.config_loader.get_data_config()
|
||||||
self.dingtalk_config = self.config_loader.get_dingtalk_config()
|
self.dingtalk_config = self.config_loader.get_dingtalk_config()
|
||||||
|
self.discord_config = self.config_loader.get_discord_config()
|
||||||
|
|
||||||
# 初始化API客户端
|
# 初始化API客户端
|
||||||
self.binance_api = BinanceAPI(
|
self.binance_api = BinanceAPI(
|
||||||
@ -70,6 +71,14 @@ class CryptoAgent:
|
|||||||
)
|
)
|
||||||
print("钉钉机器人已启用")
|
print("钉钉机器人已启用")
|
||||||
|
|
||||||
|
# 初始化Discord机器人(如果启用)
|
||||||
|
self.discord_bot = None
|
||||||
|
if self.discord_config.get('enabled', False):
|
||||||
|
self.discord_bot = DiscordBot(
|
||||||
|
webhook_url=self.discord_config['crypto_webhook_url']
|
||||||
|
)
|
||||||
|
print("Discord机器人已启用")
|
||||||
|
|
||||||
# 初始化数据库管理器
|
# 初始化数据库管理器
|
||||||
self.db_manager = get_db_manager()
|
self.db_manager = get_db_manager()
|
||||||
|
|
||||||
@ -346,6 +355,9 @@ class CryptoAgent:
|
|||||||
if self.dingtalk_bot:
|
if self.dingtalk_bot:
|
||||||
self.dingtalk_bot.send_markdown(title="加密货币交易建议", text=message)
|
self.dingtalk_bot.send_markdown(title="加密货币交易建议", text=message)
|
||||||
|
|
||||||
|
if self.discord_bot:
|
||||||
|
self.discord_bot.send_message(content=message)
|
||||||
|
|
||||||
# 导出 DeepSeek API token 使用情况
|
# 导出 DeepSeek API token 使用情况
|
||||||
self._export_token_usage()
|
self._export_token_usage()
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ from api.deepseek_api import DeepSeekAPI
|
|||||||
from models.data_processor import DataProcessor
|
from models.data_processor import DataProcessor
|
||||||
from utils.config_loader import ConfigLoader
|
from utils.config_loader import ConfigLoader
|
||||||
from utils.dingtalk_bot import DingTalkBot
|
from utils.dingtalk_bot import DingTalkBot
|
||||||
|
from utils.discord_bot import DiscordBot
|
||||||
|
|
||||||
class GoldAgent:
|
class GoldAgent:
|
||||||
"""黄金分析智能体,用于分析黄金市场数据并生成交易策略"""
|
"""黄金分析智能体,用于分析黄金市场数据并生成交易策略"""
|
||||||
@ -39,6 +39,7 @@ class GoldAgent:
|
|||||||
self.gold_config = self.config_loader.get_gold_config() # 黄金特定配置
|
self.gold_config = self.config_loader.get_gold_config() # 黄金特定配置
|
||||||
self.data_config = self.config_loader.get_data_config()
|
self.data_config = self.config_loader.get_data_config()
|
||||||
self.dingtalk_config = self.config_loader.get_dingtalk_config()
|
self.dingtalk_config = self.config_loader.get_dingtalk_config()
|
||||||
|
self.discord_config = self.config_loader.get_discord_config()
|
||||||
|
|
||||||
# 初始化API客户端
|
# 初始化API客户端
|
||||||
self.binance_api = BinanceAPI(
|
self.binance_api = BinanceAPI(
|
||||||
@ -66,6 +67,14 @@ class GoldAgent:
|
|||||||
)
|
)
|
||||||
print("钉钉机器人已启用")
|
print("钉钉机器人已启用")
|
||||||
|
|
||||||
|
# 初始化Discord机器人(如果启用)
|
||||||
|
self.discord_bot = None
|
||||||
|
if self.discord_config.get('enabled', False):
|
||||||
|
self.discord_bot = DiscordBot(
|
||||||
|
webhook_url=self.discord_config['gold_webhook_url']
|
||||||
|
)
|
||||||
|
print("Discord机器人已启用")
|
||||||
|
|
||||||
# 设置黄金交易对
|
# 设置黄金交易对
|
||||||
self.gold_symbols = self.gold_config.get('symbols', ["XAUUSD"]) # 默认黄金/美元
|
self.gold_symbols = self.gold_config.get('symbols', ["XAUUSD"]) # 默认黄金/美元
|
||||||
|
|
||||||
@ -336,6 +345,9 @@ class GoldAgent:
|
|||||||
if self.dingtalk_bot:
|
if self.dingtalk_bot:
|
||||||
self.dingtalk_bot.send_markdown(title="黄金交易建议", text=trading_suggestions)
|
self.dingtalk_bot.send_markdown(title="黄金交易建议", text=trading_suggestions)
|
||||||
|
|
||||||
|
if self.discord_bot:
|
||||||
|
self.discord_bot.send_message(content=trading_suggestions)
|
||||||
|
|
||||||
return results, trading_suggestions
|
return results, trading_suggestions
|
||||||
|
|
||||||
def convert_analysis_to_trading_suggestions(self, results: Dict[str, Any]) -> str:
|
def convert_analysis_to_trading_suggestions(self, results: Dict[str, Any]) -> str:
|
||||||
|
|||||||
@ -27,8 +27,10 @@ crypto:
|
|||||||
base_currencies:
|
base_currencies:
|
||||||
- "BTC"
|
- "BTC"
|
||||||
- "ETH"
|
- "ETH"
|
||||||
# - "SOL"
|
- "SOL"
|
||||||
# - "SUI"
|
- "SUI"
|
||||||
|
- "XRP"
|
||||||
|
- “DOGE”
|
||||||
quote_currency: "USDT"
|
quote_currency: "USDT"
|
||||||
time_interval: "4h" # 可选: 1m, 5m, 15m, 30m, 1h, 4h, 1d
|
time_interval: "4h" # 可选: 1m, 5m, 15m, 30m, 1h, 4h, 1d
|
||||||
historical_days: 90
|
historical_days: 90
|
||||||
@ -38,7 +40,7 @@ gold:
|
|||||||
# 黄金交易对
|
# 黄金交易对
|
||||||
symbols: ["GOLD"]
|
symbols: ["GOLD"]
|
||||||
# 历史数据天数
|
# 历史数据天数
|
||||||
historical_days: 30
|
historical_days: 90
|
||||||
# 时间间隔
|
# 时间间隔
|
||||||
time_interval: "4h"
|
time_interval: "4h"
|
||||||
|
|
||||||
@ -60,6 +62,13 @@ dingtalk:
|
|||||||
at_mobiles: [] # 需要@的手机号列表
|
at_mobiles: [] # 需要@的手机号列表
|
||||||
at_all: false # 是否@所有人
|
at_all: false # 是否@所有人
|
||||||
|
|
||||||
|
# Discord机器人配置
|
||||||
|
discord:
|
||||||
|
enabled: true
|
||||||
|
crypto_webhook_url: "https://discord.com/api/webhooks/1286585288986198048/iQ-yr26ViW45GM48ql8rPu70Iumqcmn_XXAmxAcKGeiQBmTQoDPeq-TmlChvIHkw_HJ-"
|
||||||
|
gold_webhook_url: "https://discord.com/api/webhooks/1367341235987021914/XVcjs6ZAZad3ZezzuudyiK_KqNUowqz2o2NJPdvwWY_EvwZVJcnVHq5M0-RQhkKV-FEQ"
|
||||||
|
|
||||||
|
|
||||||
# 数据库配置
|
# 数据库配置
|
||||||
database:
|
database:
|
||||||
host: "gz-cynosdbmysql-grp-2j1cnopr.sql.tencentcdb.com"
|
host: "gz-cynosdbmysql-grp-2j1cnopr.sql.tencentcdb.com"
|
||||||
|
|||||||
@ -26,13 +26,18 @@ def main():
|
|||||||
print("定时程序启动")
|
print("定时程序启动")
|
||||||
CryptoAgent().start_agent()
|
CryptoAgent().start_agent()
|
||||||
# 设置 08:00, 20:00 运行一次
|
# 设置 08:00, 20:00 运行一次
|
||||||
|
schedule.every().day.at("00:00").do(CryptoAgent().start_agent)
|
||||||
schedule.every().day.at("08:00").do(CryptoAgent().start_agent)
|
schedule.every().day.at("08:00").do(CryptoAgent().start_agent)
|
||||||
|
schedule.every().day.at("12:00").do(CryptoAgent().start_agent)
|
||||||
|
schedule.every().day.at("16:00").do(CryptoAgent().start_agent)
|
||||||
schedule.every().day.at("20:00").do(CryptoAgent().start_agent)
|
schedule.every().day.at("20:00").do(CryptoAgent().start_agent)
|
||||||
|
|
||||||
|
schedule.every().day.at("00:00").do(GoldAgent().start_agent)
|
||||||
schedule.every().day.at("08:00").do(GoldAgent().start_agent)
|
schedule.every().day.at("08:00").do(GoldAgent().start_agent)
|
||||||
|
schedule.every().day.at("12:00").do(GoldAgent().start_agent)
|
||||||
|
schedule.every().day.at("16:00").do(GoldAgent().start_agent)
|
||||||
schedule.every().day.at("20:00").do(GoldAgent().start_agent)
|
schedule.every().day.at("20:00").do(GoldAgent().start_agent)
|
||||||
|
|
||||||
# 启动定时任务
|
|
||||||
while True:
|
while True:
|
||||||
schedule.run_pending()
|
schedule.run_pending()
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|||||||
@ -2,3 +2,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
"""工具模块,提供各种辅助功能。"""
|
"""工具模块,提供各种辅助功能。"""
|
||||||
|
|
||||||
|
from cryptoai.utils.dingtalk_bot import DingTalkBot
|
||||||
|
from cryptoai.utils.discord_bot import DiscordBot
|
||||||
|
from cryptoai.utils.config_loader import ConfigLoader
|
||||||
Binary file not shown.
Binary file not shown.
@ -96,35 +96,11 @@ class ConfigLoader:
|
|||||||
"""获取钉钉机器人配置"""
|
"""获取钉钉机器人配置"""
|
||||||
return self.get_config('dingtalk')
|
return self.get_config('dingtalk')
|
||||||
|
|
||||||
|
def get_discord_config(self) -> Dict[str, Any]:
|
||||||
|
"""获取Discord机器人配置"""
|
||||||
|
return self.get_config('discord')
|
||||||
|
|
||||||
def get_database_config(self) -> Dict[str, Any]:
|
def get_database_config(self) -> Dict[str, Any]:
|
||||||
"""获取数据库配置"""
|
"""获取数据库配置"""
|
||||||
# 首先从配置文件获取
|
|
||||||
db_config = self.get_config('database')
|
|
||||||
|
|
||||||
# 使用环境变量覆盖(如果存在)
|
return self.get_config('database')
|
||||||
if os.environ.get('DB_HOST'):
|
|
||||||
db_config['host'] = os.environ.get('DB_HOST')
|
|
||||||
if os.environ.get('DB_PORT'):
|
|
||||||
db_config['port'] = int(os.environ.get('DB_PORT'))
|
|
||||||
if os.environ.get('DB_USER'):
|
|
||||||
db_config['user'] = os.environ.get('DB_USER')
|
|
||||||
if os.environ.get('DB_PASSWORD'):
|
|
||||||
db_config['password'] = os.environ.get('DB_PASSWORD')
|
|
||||||
if os.environ.get('DB_NAME'):
|
|
||||||
db_config['db_name'] = os.environ.get('DB_NAME')
|
|
||||||
|
|
||||||
# 确保返回默认值(如果配置不存在)
|
|
||||||
default_config = {
|
|
||||||
'host': 'gz-cynosdbmysql-grp-2j1cnopr.sql.tencentcdb.com',
|
|
||||||
'port': 27469,
|
|
||||||
'user': 'root',
|
|
||||||
'password': 'Aa#223388',
|
|
||||||
'db_name': 'cryptoai'
|
|
||||||
}
|
|
||||||
|
|
||||||
# 合并默认配置和实际配置
|
|
||||||
for key, value in default_config.items():
|
|
||||||
if key not in db_config:
|
|
||||||
db_config[key] = value
|
|
||||||
|
|
||||||
return db_config
|
|
||||||
63
cryptoai/utils/discord_bot.py
Normal file
63
cryptoai/utils/discord_bot.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
|
import traceback
|
||||||
|
import datetime
|
||||||
|
from typing import Dict, Any, List, Optional, Union
|
||||||
|
|
||||||
|
class DiscordBot:
|
||||||
|
"""Discord Webhook机器人,用于发送分析结果到Discord频道"""
|
||||||
|
|
||||||
|
def __init__(self, webhook_url: str):
|
||||||
|
"""
|
||||||
|
初始化Discord Webhook机器人
|
||||||
|
|
||||||
|
Args:
|
||||||
|
webhook_url: Discord Webhook的URL
|
||||||
|
"""
|
||||||
|
self.webhook_url = webhook_url
|
||||||
|
|
||||||
|
def send_message(self, content: str, username: str = None, avatar_url: str = None) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
发送普通消息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
content: 消息内容
|
||||||
|
username: 自定义机器人名称
|
||||||
|
avatar_url: 自定义机器人头像URL
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
接口返回结果
|
||||||
|
"""
|
||||||
|
data = {"content": content}
|
||||||
|
|
||||||
|
if username:
|
||||||
|
data["username"] = username
|
||||||
|
|
||||||
|
if avatar_url:
|
||||||
|
data["avatar_url"] = avatar_url
|
||||||
|
|
||||||
|
return self._post(data)
|
||||||
|
|
||||||
|
def _post(self, data: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
发送数据到Discord Webhook
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data: 要发送的数据
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
接口返回结果
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
headers = {'Content-Type': 'application/json'}
|
||||||
|
response = requests.post(self.webhook_url, json=data, headers=headers)
|
||||||
|
if response.status_code == 204: # Discord返回成功时无内容
|
||||||
|
return {"success": True}
|
||||||
|
return response.json()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"发送Discord消息时出错: {e}")
|
||||||
|
traceback.print_exc()
|
||||||
|
return {"success": False, "error": str(e)}
|
||||||
@ -4,7 +4,7 @@ services:
|
|||||||
cryptoai:
|
cryptoai:
|
||||||
build: .
|
build: .
|
||||||
container_name: cryptoai-task
|
container_name: cryptoai-task
|
||||||
image: cryptoai:0.0.9
|
image: cryptoai:0.0.10
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- ./cryptoai/data:/app/cryptoai/data
|
- ./cryptoai/data:/app/cryptoai/data
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user