update
This commit is contained in:
parent
284a3f463a
commit
b573ac1dfe
2
.gitignore
vendored
2
.gitignore
vendored
@ -20,6 +20,8 @@ wheels/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
|
||||
|
||||
# 虚拟环境
|
||||
venv/
|
||||
ENV/
|
||||
|
||||
41
README.md
41
README.md
@ -8,7 +8,7 @@
|
||||
- 利用DeepSeek大模型进行市场分析和预测
|
||||
- 提供市场趋势、价格预测和交易建议
|
||||
- 支持多种加密货币分析
|
||||
- 通过钉钉机器人发送分析结果
|
||||
- 通过钉钉机器人和Discord Webhook发送分析结果
|
||||
|
||||
## 项目结构
|
||||
|
||||
@ -98,6 +98,10 @@ OKX_PASSPHRASE=OKX密码
|
||||
DINGTALK_ENABLED=true/false
|
||||
DINGTALK_WEBHOOK_URL=钉钉Webhook地址
|
||||
DINGTALK_SECRET=钉钉密钥
|
||||
|
||||
# Discord机器人
|
||||
DISCORD_ENABLED=true/false
|
||||
DISCORD_WEBHOOK_URL=Discord Webhook地址
|
||||
```
|
||||
|
||||
在Docker中可以通过`-e`参数或`.env`文件传递环境变量。
|
||||
@ -176,3 +180,38 @@ curl -X POST "http://localhost:8000/api/analyze" \
|
||||
"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.dingtalk_bot import DingTalkBot
|
||||
from utils.db_manager import get_db_manager
|
||||
|
||||
from utils.discord_bot import DiscordBot
|
||||
|
||||
class CryptoAgent:
|
||||
"""加密货币智能体,用于分析市场数据并生成交易策略"""
|
||||
@ -40,6 +40,7 @@ class CryptoAgent:
|
||||
self.crypto_config = self.config_loader.get_crypto_config()
|
||||
self.data_config = self.config_loader.get_data_config()
|
||||
self.dingtalk_config = self.config_loader.get_dingtalk_config()
|
||||
self.discord_config = self.config_loader.get_discord_config()
|
||||
|
||||
# 初始化API客户端
|
||||
self.binance_api = BinanceAPI(
|
||||
@ -70,6 +71,14 @@ class CryptoAgent:
|
||||
)
|
||||
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()
|
||||
|
||||
@ -346,6 +355,9 @@ class CryptoAgent:
|
||||
if self.dingtalk_bot:
|
||||
self.dingtalk_bot.send_markdown(title="加密货币交易建议", text=message)
|
||||
|
||||
if self.discord_bot:
|
||||
self.discord_bot.send_message(content=message)
|
||||
|
||||
# 导出 DeepSeek API token 使用情况
|
||||
self._export_token_usage()
|
||||
|
||||
|
||||
@ -17,7 +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.discord_bot import DiscordBot
|
||||
|
||||
class GoldAgent:
|
||||
"""黄金分析智能体,用于分析黄金市场数据并生成交易策略"""
|
||||
@ -39,6 +39,7 @@ class GoldAgent:
|
||||
self.gold_config = self.config_loader.get_gold_config() # 黄金特定配置
|
||||
self.data_config = self.config_loader.get_data_config()
|
||||
self.dingtalk_config = self.config_loader.get_dingtalk_config()
|
||||
self.discord_config = self.config_loader.get_discord_config()
|
||||
|
||||
# 初始化API客户端
|
||||
self.binance_api = BinanceAPI(
|
||||
@ -66,6 +67,14 @@ class GoldAgent:
|
||||
)
|
||||
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"]) # 默认黄金/美元
|
||||
|
||||
@ -336,6 +345,9 @@ class GoldAgent:
|
||||
if self.dingtalk_bot:
|
||||
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
|
||||
|
||||
def convert_analysis_to_trading_suggestions(self, results: Dict[str, Any]) -> str:
|
||||
|
||||
@ -27,8 +27,10 @@ crypto:
|
||||
base_currencies:
|
||||
- "BTC"
|
||||
- "ETH"
|
||||
# - "SOL"
|
||||
# - "SUI"
|
||||
- "SOL"
|
||||
- "SUI"
|
||||
- "XRP"
|
||||
- “DOGE”
|
||||
quote_currency: "USDT"
|
||||
time_interval: "4h" # 可选: 1m, 5m, 15m, 30m, 1h, 4h, 1d
|
||||
historical_days: 90
|
||||
@ -38,7 +40,7 @@ gold:
|
||||
# 黄金交易对
|
||||
symbols: ["GOLD"]
|
||||
# 历史数据天数
|
||||
historical_days: 30
|
||||
historical_days: 90
|
||||
# 时间间隔
|
||||
time_interval: "4h"
|
||||
|
||||
@ -60,6 +62,13 @@ dingtalk:
|
||||
at_mobiles: [] # 需要@的手机号列表
|
||||
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:
|
||||
host: "gz-cynosdbmysql-grp-2j1cnopr.sql.tencentcdb.com"
|
||||
|
||||
@ -26,13 +26,18 @@ def main():
|
||||
print("定时程序启动")
|
||||
CryptoAgent().start_agent()
|
||||
# 设置 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("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("00: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)
|
||||
|
||||
# 启动定时任务
|
||||
while True:
|
||||
schedule.run_pending()
|
||||
time.sleep(1)
|
||||
|
||||
@ -2,3 +2,7 @@
|
||||
# -*- 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')
|
||||
|
||||
def get_discord_config(self) -> Dict[str, Any]:
|
||||
"""获取Discord机器人配置"""
|
||||
return self.get_config('discord')
|
||||
|
||||
def get_database_config(self) -> Dict[str, Any]:
|
||||
"""获取数据库配置"""
|
||||
# 首先从配置文件获取
|
||||
db_config = 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
|
||||
return self.get_config('database')
|
||||
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:
|
||||
build: .
|
||||
container_name: cryptoai-task
|
||||
image: cryptoai:0.0.9
|
||||
image: cryptoai:0.0.10
|
||||
restart: always
|
||||
volumes:
|
||||
- ./cryptoai/data:/app/cryptoai/data
|
||||
|
||||
Loading…
Reference in New Issue
Block a user