update
This commit is contained in:
parent
0a637053fc
commit
1a9bf9f74b
@ -97,6 +97,7 @@ class Settings(BaseSettings):
|
||||
feishu_crypto_webhook_url: str = "https://open.feishu.cn/open-apis/bot/v2/hook/8a1dcf69-6753-41e2-a393-edc4f7822db0" # 加密货币通知
|
||||
feishu_stock_webhook_url: str = "https://open.feishu.cn/open-apis/bot/v2/hook/408ab727-0dcd-4c7a-bde7-4aad38cbf807" # 股票通知
|
||||
feishu_news_webhook_url: str = "https://open.feishu.cn/open-apis/bot/v2/hook/c7fd0db7-d295-451c-b943-130278a6cd9d" # 新闻智能体通知
|
||||
feishu_paper_trading_webhook_url: str = "https://open.feishu.cn/open-apis/bot/v2/hook/3f5642e7-420b-45f7-8f88-fff92bb98c69" # 模拟交易通知(交易信号+决策+执行)
|
||||
feishu_error_webhook_url: str = "https://open.feishu.cn/open-apis/bot/v2/hook/ba6952c9-3b0c-4bc1-8a43-ceaacb27b043" # 系统异常通知
|
||||
feishu_enabled: bool = True # 是否启用飞书通知
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ import pandas as pd
|
||||
from app.utils.logger import logger
|
||||
from app.config import get_settings
|
||||
from app.services.bitget_service import bitget_service
|
||||
from app.services.feishu_service import get_feishu_service
|
||||
from app.services.feishu_service import get_feishu_service, get_feishu_paper_trading_service
|
||||
from app.services.telegram_service import get_telegram_service
|
||||
from app.services.dingtalk_service import get_dingtalk_service
|
||||
from app.services.paper_trading_service import get_paper_trading_service
|
||||
@ -40,7 +40,8 @@ class CryptoAgent:
|
||||
CryptoAgent._initialized = True
|
||||
self.settings = get_settings()
|
||||
self.exchange = bitget_service # 交易所服务
|
||||
self.feishu = get_feishu_service()
|
||||
self.feishu = get_feishu_service() # 通用飞书服务(crypto等)
|
||||
self.feishu_paper = get_feishu_paper_trading_service() # 模拟交易专用飞书服务
|
||||
self.telegram = get_telegram_service()
|
||||
self.dingtalk = get_dingtalk_service() # 添加钉钉服务
|
||||
|
||||
@ -138,7 +139,7 @@ class CryptoAgent:
|
||||
content = "\n".join(content_parts)
|
||||
|
||||
if self.settings.feishu_enabled:
|
||||
await self.feishu.send_card(title, content, "green")
|
||||
await self.feishu_paper.send_card(title, content, "green")
|
||||
if self.settings.telegram_enabled:
|
||||
message = f"{title}\n\n{content}"
|
||||
await self.telegram.send_message(message)
|
||||
@ -164,7 +165,7 @@ class CryptoAgent:
|
||||
content = "\n".join(content_parts)
|
||||
|
||||
if self.settings.feishu_enabled:
|
||||
await self.feishu.send_card(title, content, "orange")
|
||||
await self.feishu_paper.send_card(title, content, "orange")
|
||||
if self.settings.telegram_enabled:
|
||||
message = f"{title}\n\n{content}"
|
||||
await self.telegram.send_message(message)
|
||||
@ -193,7 +194,7 @@ class CryptoAgent:
|
||||
content = "\n".join(content_parts)
|
||||
|
||||
if self.settings.feishu_enabled:
|
||||
await self.feishu.send_card(title, content, "green")
|
||||
await self.feishu_paper.send_card(title, content, "green")
|
||||
if self.settings.telegram_enabled:
|
||||
message = f"{title}\n\n{content}"
|
||||
await self.telegram.send_message(message)
|
||||
@ -246,7 +247,7 @@ class CryptoAgent:
|
||||
content = "\n".join(content_parts)
|
||||
|
||||
if self.settings.feishu_enabled:
|
||||
await self.feishu.send_card(title, content, color)
|
||||
await self.feishu_paper.send_card(title, content, color)
|
||||
if self.settings.telegram_enabled:
|
||||
message = f"{title}\n\n{content}"
|
||||
await self.telegram.send_message(message)
|
||||
@ -787,8 +788,7 @@ class CryptoAgent:
|
||||
if decision_type == 'HOLD':
|
||||
reasoning = paper_decision.get('reasoning', '观望')
|
||||
logger.info(f"\n📊 交易决策: {reasoning}")
|
||||
# 有信号但决策为 HOLD,发送未执行通知
|
||||
await self._notify_signal_not_executed(market_signal, paper_decision, current_price, is_paper=True)
|
||||
# HOLD决策的理由已在交易决策通知中说明,无需单独通知
|
||||
else:
|
||||
logger.info(f"\n📊 【执行交易】")
|
||||
|
||||
@ -810,14 +810,11 @@ class CryptoAgent:
|
||||
paper_executed = True
|
||||
else:
|
||||
logger.error(f" ❌ 订单对象无效: 缺少order_id属性")
|
||||
reason = "订单对象无效: 缺少order_id"
|
||||
await self._notify_signal_not_executed(market_signal, paper_decision, current_price, is_paper=True, reason=reason)
|
||||
# 订单创建失败,理由已在日志中记录,无需单独通知
|
||||
else:
|
||||
# 有信号但订单创建失败,发送未执行通知
|
||||
# 订单创建失败,理由已在日志中记录,无需单独通知
|
||||
reason = result.get('message', '订单创建失败') if result else '订单创建失败'
|
||||
logger.warning(f" ⚠️ 交易未执行: {reason}")
|
||||
await self._notify_signal_not_executed(market_signal, paper_decision, current_price, is_paper=True, reason=reason)
|
||||
logger.warning(f" ⚠️ 交易未执行: {reason}")
|
||||
elif decision_type == 'CLOSE':
|
||||
await self._execute_close(paper_decision, paper_trading=True)
|
||||
# CLOSE 操作也发送执行通知
|
||||
@ -845,8 +842,7 @@ class CryptoAgent:
|
||||
if decision_type == 'HOLD':
|
||||
reasoning = real_decision.get('reasoning', '观望')
|
||||
logger.info(f"\n💰 实盘交易: {reasoning}")
|
||||
# 有信号但决策为 HOLD,发送未执行通知
|
||||
await self._notify_signal_not_executed(market_signal, real_decision, current_price, is_paper=False)
|
||||
# HOLD决策的理由已在交易决策通知中说明,无需单独通知
|
||||
else:
|
||||
logger.info(f"\n💰 【执行实盘交易】")
|
||||
|
||||
@ -859,10 +855,9 @@ class CryptoAgent:
|
||||
await self._send_signal_notification(market_signal, real_decision, current_price, is_paper=False)
|
||||
real_executed = True
|
||||
else:
|
||||
# 有信号但订单创建失败,发送未执行通知
|
||||
# 订单创建失败,理由已在日志中记录,无需单独通知
|
||||
reason = result.get('message', '订单创建失败') if result else '订单创建失败'
|
||||
await self._notify_signal_not_executed(market_signal, real_decision, current_price, is_paper=False, reason=reason)
|
||||
logger.warning(f" ⚠️ 实盘交易未执行,已发送通知")
|
||||
logger.warning(f" ⚠️ 实盘交易未执行: {reason}")
|
||||
elif decision_type == 'CLOSE':
|
||||
await self._execute_close(real_decision, paper_trading=False)
|
||||
# CLOSE 操作也发送执行通知
|
||||
@ -1008,12 +1003,12 @@ class CryptoAgent:
|
||||
sl_display = "N/A"
|
||||
tp_display = "N/A"
|
||||
|
||||
# 构建卡片标题和颜色
|
||||
# 构建卡片标题和颜色 - 添加 [信号] 前缀区分
|
||||
if sig_action == 'buy':
|
||||
title = f"🟢 {symbol} {timeframe_text}做多信号"
|
||||
title = f"[信号] 🟢 {symbol} {timeframe_text}做多信号"
|
||||
color = "green"
|
||||
else:
|
||||
title = f"🔴 {symbol} {timeframe_text}做空信号"
|
||||
title = f"[信号] 🔴 {symbol} {timeframe_text}做空信号"
|
||||
color = "red"
|
||||
|
||||
# 构建卡片内容
|
||||
@ -1046,7 +1041,7 @@ class CryptoAgent:
|
||||
|
||||
content = "\n".join(content_parts)
|
||||
|
||||
# 根据配置发送通知
|
||||
# 根据配置发送通知 - [信号] 发送到 crypto webhook
|
||||
if self.settings.feishu_enabled:
|
||||
await self.feishu.send_card(title, content, color)
|
||||
if self.settings.telegram_enabled:
|
||||
@ -1098,8 +1093,8 @@ class CryptoAgent:
|
||||
}
|
||||
color = color_map.get(decision_type, 'blue')
|
||||
|
||||
# 构建标题
|
||||
title = f"{account_type} {symbol} 交易决策: {decision_text}"
|
||||
# 构建标题 - 添加 [决策] 前缀区分
|
||||
title = f"[决策] {account_type} {symbol} 交易决策: {decision_text}"
|
||||
|
||||
# 获取最佳信号用于显示
|
||||
best_signal = self._get_best_signal_from_market(market_signal)
|
||||
@ -1181,7 +1176,7 @@ class CryptoAgent:
|
||||
|
||||
content = "\n".join(content_parts)
|
||||
|
||||
# 发送通知
|
||||
# 发送通知 - [决策] 发送到 crypto webhook
|
||||
if self.settings.feishu_enabled:
|
||||
await self.feishu.send_card(title, content, color)
|
||||
if self.settings.telegram_enabled:
|
||||
@ -1253,26 +1248,26 @@ class CryptoAgent:
|
||||
position_map = {'heavy': '🔥 重仓', 'medium': '📊 中仓', 'light': '🌱 轻仓'}
|
||||
position_display = position_map.get(position_size, '🌱 轻仓')
|
||||
|
||||
# 构建卡片标题和颜色 - 考虑入场方式
|
||||
# 构建卡片标题和颜色 - 考虑入场方式,添加 [执行] 前缀区分
|
||||
# 挂单时标题显示"挂单",现价单时显示"开仓"/"平仓"等
|
||||
if decision_type == 'OPEN':
|
||||
decision_title = '挂单' if entry_type == 'limit' else '开仓'
|
||||
title = f"{account_type} {symbol} {decision_title}"
|
||||
title = f"[执行] {account_type} {symbol} {decision_title}"
|
||||
color = "green"
|
||||
elif decision_type == 'CLOSE':
|
||||
decision_title = '挂单' if entry_type == 'limit' else '平仓'
|
||||
title = f"{account_type} {symbol} {decision_title}"
|
||||
title = f"[执行] {account_type} {symbol} {decision_title}"
|
||||
color = "orange"
|
||||
elif decision_type == 'ADD':
|
||||
decision_title = '挂单' if entry_type == 'limit' else '加仓'
|
||||
title = f"{account_type} {symbol} {decision_title}"
|
||||
title = f"[执行] {account_type} {symbol} {decision_title}"
|
||||
color = "green"
|
||||
elif decision_type == 'REDUCE':
|
||||
decision_title = '挂单' if entry_type == 'limit' else '减仓'
|
||||
title = f"{account_type} {symbol} {decision_title}"
|
||||
title = f"[执行] {account_type} {symbol} {decision_title}"
|
||||
color = "orange"
|
||||
else:
|
||||
title = f"{account_type} {symbol} 交易执行"
|
||||
title = f"[执行] {account_type} {symbol} 交易执行"
|
||||
color = "blue"
|
||||
|
||||
# 构建卡片内容
|
||||
@ -1315,9 +1310,9 @@ class CryptoAgent:
|
||||
|
||||
content = "\n".join(content_parts)
|
||||
|
||||
# 根据配置发送通知
|
||||
# 根据配置发送通知 - 所有订单执行都发送到 paper trading webhook
|
||||
if self.settings.feishu_enabled:
|
||||
await self.feishu.send_card(title, content, color)
|
||||
await self.feishu_paper.send_card(title, content, color)
|
||||
if self.settings.telegram_enabled:
|
||||
# Telegram 使用文本格式
|
||||
message = f"{title}\n\n{content}"
|
||||
@ -1806,7 +1801,7 @@ class CryptoAgent:
|
||||
content = "\n".join(content_parts)
|
||||
|
||||
if self.settings.feishu_enabled:
|
||||
await self.feishu.send_card(title, content, "red")
|
||||
await self.feishu_paper.send_card(title, content, "red")
|
||||
if self.settings.telegram_enabled:
|
||||
message = f"{title}\n\n{content}"
|
||||
await self.telegram.send_message(message)
|
||||
@ -1859,7 +1854,7 @@ class CryptoAgent:
|
||||
content = "\n".join(content_parts)
|
||||
|
||||
if self.settings.feishu_enabled:
|
||||
await self.feishu.send_card(title, content, "blue")
|
||||
await self.feishu_paper.send_card(title, content, "blue")
|
||||
if self.settings.telegram_enabled:
|
||||
message = f"{title}\n\n{content}"
|
||||
await self.telegram.send_message(message)
|
||||
|
||||
@ -18,7 +18,7 @@ class FeishuService:
|
||||
|
||||
Args:
|
||||
webhook_url: 飞书机器人 Webhook URL(如果为空,则根据 service_type 从配置读取)
|
||||
service_type: 服务类型 ("crypto" 或 "stock")
|
||||
service_type: 服务类型 ("crypto", "stock", "news", "paper_trading", "error")
|
||||
"""
|
||||
settings = get_settings()
|
||||
|
||||
@ -33,6 +33,10 @@ class FeishuService:
|
||||
self.webhook_url = getattr(settings, 'feishu_stock_webhook_url', '')
|
||||
elif service_type == "news":
|
||||
self.webhook_url = getattr(settings, 'feishu_news_webhook_url', '')
|
||||
elif service_type == "paper_trading":
|
||||
self.webhook_url = getattr(settings, 'feishu_paper_trading_webhook_url', '')
|
||||
elif service_type == "error":
|
||||
self.webhook_url = getattr(settings, 'feishu_error_webhook_url', '')
|
||||
else:
|
||||
# 兼容旧配置
|
||||
self.webhook_url = getattr(settings, 'feishu_webhook_url', '')
|
||||
@ -285,10 +289,11 @@ class FeishuService:
|
||||
|
||||
|
||||
|
||||
# 全局实例(延迟初始化)- 分别用于加密货币、股票和新闻
|
||||
# 全局实例(延迟初始化)- 分别用于加密货币、股票、新闻和模拟交易
|
||||
_feishu_crypto_service: Optional[FeishuService] = None
|
||||
_feishu_stock_service: Optional[FeishuService] = None
|
||||
_feishu_news_service: Optional[FeishuService] = None
|
||||
_feishu_paper_trading_service: Optional[FeishuService] = None
|
||||
|
||||
|
||||
def get_feishu_service() -> FeishuService:
|
||||
@ -318,3 +323,11 @@ def get_feishu_news_service() -> FeishuService:
|
||||
if _feishu_news_service is None:
|
||||
_feishu_news_service = FeishuService(service_type="news")
|
||||
return _feishu_news_service
|
||||
|
||||
|
||||
def get_feishu_paper_trading_service() -> FeishuService:
|
||||
"""获取模拟交易飞书服务实例"""
|
||||
global _feishu_paper_trading_service
|
||||
if _feishu_paper_trading_service is None:
|
||||
_feishu_paper_trading_service = FeishuService(service_type="paper_trading")
|
||||
return _feishu_paper_trading_service
|
||||
|
||||
Loading…
Reference in New Issue
Block a user