update
This commit is contained in:
parent
7e41c0f587
commit
568faa1f8d
@ -115,40 +115,54 @@ class CryptoAgent:
|
|||||||
async def _notify_order_filled(self, result: Dict[str, Any]):
|
async def _notify_order_filled(self, result: Dict[str, Any]):
|
||||||
"""发送挂单成交通知"""
|
"""发送挂单成交通知"""
|
||||||
side_text = "做多" if result.get('side') == 'long' else "做空"
|
side_text = "做多" if result.get('side') == 'long' else "做空"
|
||||||
|
side_icon = "🟢" if result.get('side') == 'long' else "🔴"
|
||||||
grade = result.get('signal_grade', 'N/A')
|
grade = result.get('signal_grade', 'N/A')
|
||||||
|
|
||||||
message = f"""✅ 挂单成交
|
title = f"✅ 挂单成交 - {result.get('symbol')}"
|
||||||
|
|
||||||
交易对: {result.get('symbol')}
|
content_parts = [
|
||||||
方向: {side_text}
|
f"{side_icon} **方向**: {side_text}",
|
||||||
等级: {grade}
|
f"⭐ **信号等级**: {grade}",
|
||||||
挂单价: ${result.get('entry_price', 0):,.2f}
|
f"💰 **挂单价**: ${result.get('entry_price', 0):,.2f}",
|
||||||
成交价: ${result.get('filled_price', 0):,.2f}
|
f"🎯 **成交价**: ${result.get('filled_price', 0):,.2f}",
|
||||||
仓位: ${result.get('quantity', 0):,.0f}
|
f"💵 **仓位**: ${result.get('quantity', 0):,.0f}",
|
||||||
止损: ${result.get('stop_loss', 0):,.2f}
|
]
|
||||||
止盈: ${result.get('take_profit', 0):,.2f}"""
|
|
||||||
|
if result.get('stop_loss'):
|
||||||
|
content_parts.append(f"🛑 **止损**: ${result.get('stop_loss', 0):,.2f}")
|
||||||
|
if result.get('take_profit'):
|
||||||
|
content_parts.append(f"🎯 **止盈**: ${result.get('take_profit', 0):,.2f}")
|
||||||
|
|
||||||
|
content = "\n".join(content_parts)
|
||||||
|
|
||||||
if self.settings.feishu_enabled:
|
if self.settings.feishu_enabled:
|
||||||
await self.feishu.send_text(message)
|
await self.feishu.send_card(title, content, "green")
|
||||||
if self.settings.telegram_enabled:
|
if self.settings.telegram_enabled:
|
||||||
|
message = f"{title}\n\n{content}"
|
||||||
await self.telegram.send_message(message)
|
await self.telegram.send_message(message)
|
||||||
logger.info(f"已发送挂单成交通知: {result.get('order_id')}")
|
logger.info(f"已发送挂单成交通知: {result.get('order_id')}")
|
||||||
|
|
||||||
async def _notify_pending_cancelled(self, result: Dict[str, Any]):
|
async def _notify_pending_cancelled(self, result: Dict[str, Any]):
|
||||||
"""发送挂单撤销通知"""
|
"""发送挂单撤销通知"""
|
||||||
side_text = "做多" if result.get('side') == 'long' else "做空"
|
side_text = "做多" if result.get('side') == 'long' else "做空"
|
||||||
|
side_icon = "🟢" if result.get('side') == 'long' else "🔴"
|
||||||
new_side_text = "做多" if result.get('new_side') == 'long' else "做空"
|
new_side_text = "做多" if result.get('new_side') == 'long' else "做空"
|
||||||
|
|
||||||
message = f"""⚠️ 挂单撤销
|
title = f"⚠️ 挂单撤销 - {result.get('symbol')}"
|
||||||
|
|
||||||
交易对: {result.get('symbol')}
|
content_parts = [
|
||||||
原方向: {side_text}
|
f"{side_icon} **原方向**: {side_text}",
|
||||||
挂单价: ${result.get('entry_price', 0):,.2f}
|
f"💰 **挂单价**: ${result.get('entry_price', 0):,.2f}",
|
||||||
原因: 收到反向{new_side_text}信号,自动撤销"""
|
f"",
|
||||||
|
f"📝 **原因**: 收到反向{new_side_text}信号,自动撤销",
|
||||||
|
]
|
||||||
|
|
||||||
|
content = "\n".join(content_parts)
|
||||||
|
|
||||||
if self.settings.feishu_enabled:
|
if self.settings.feishu_enabled:
|
||||||
await self.feishu.send_text(message)
|
await self.feishu.send_card(title, content, "orange")
|
||||||
if self.settings.telegram_enabled:
|
if self.settings.telegram_enabled:
|
||||||
|
message = f"{title}\n\n{content}"
|
||||||
await self.telegram.send_message(message)
|
await self.telegram.send_message(message)
|
||||||
logger.info(f"已发送挂单撤销通知: {result.get('order_id')}")
|
logger.info(f"已发送挂单撤销通知: {result.get('order_id')}")
|
||||||
|
|
||||||
@ -187,31 +201,42 @@ class CryptoAgent:
|
|||||||
if status == 'closed_tp':
|
if status == 'closed_tp':
|
||||||
emoji = "🎯"
|
emoji = "🎯"
|
||||||
status_text = "止盈平仓"
|
status_text = "止盈平仓"
|
||||||
|
color = "green"
|
||||||
elif status == 'closed_sl':
|
elif status == 'closed_sl':
|
||||||
emoji = "🛑"
|
emoji = "🛑"
|
||||||
status_text = "止损平仓"
|
status_text = "止损平仓"
|
||||||
|
color = "red"
|
||||||
elif status == 'closed_be':
|
elif status == 'closed_be':
|
||||||
emoji = "📈"
|
emoji = "📈"
|
||||||
status_text = "移动止损"
|
status_text = "移动止损"
|
||||||
|
color = "orange"
|
||||||
else:
|
else:
|
||||||
emoji = "📤"
|
emoji = "📤"
|
||||||
status_text = "手动平仓"
|
status_text = "手动平仓"
|
||||||
|
color = "blue"
|
||||||
|
|
||||||
win_text = "盈利" if is_win else "亏损"
|
win_text = "盈利" if is_win else "亏损"
|
||||||
|
win_emoji = "✅" if is_win else "❌"
|
||||||
side_text = "做多" if result.get('side') == 'long' else "做空"
|
side_text = "做多" if result.get('side') == 'long' else "做空"
|
||||||
|
side_icon = "🟢" if result.get('side') == 'long' else "🔴"
|
||||||
|
|
||||||
message = f"""{emoji} 订单{status_text}
|
title = f"{emoji} 订单{status_text}"
|
||||||
|
|
||||||
交易对: {result.get('symbol')}
|
content_parts = [
|
||||||
方向: {side_text}
|
f"{side_icon} **方向**: {side_text}",
|
||||||
入场: ${result.get('entry_price', 0):,.2f}
|
f"💰 **交易对**: {result.get('symbol')}",
|
||||||
出场: ${result.get('exit_price', 0):,.2f}
|
f"📊 **入场**: ${result.get('entry_price', 0):,.2f}",
|
||||||
{win_text}: {result.get('pnl_percent', 0):+.2f}% (${result.get('pnl_amount', 0):+.2f})
|
f"🎯 **出场**: ${result.get('exit_price', 0):,.2f}",
|
||||||
持仓时间: {result.get('hold_duration', 'N/A')}"""
|
f"{win_emoji} **{win_text}**: {result.get('pnl_percent', 0):+.2f}% (${result.get('pnl_amount', 0):+.2f})",
|
||||||
|
f"⏱️ **持仓时间**: {result.get('hold_duration', 'N/A')}",
|
||||||
|
]
|
||||||
|
|
||||||
|
content = "\n".join(content_parts)
|
||||||
|
|
||||||
if self.settings.feishu_enabled:
|
if self.settings.feishu_enabled:
|
||||||
await self.feishu.send_text(message)
|
await self.feishu.send_card(title, content, color)
|
||||||
if self.settings.telegram_enabled:
|
if self.settings.telegram_enabled:
|
||||||
|
message = f"{title}\n\n{content}"
|
||||||
await self.telegram.send_message(message)
|
await self.telegram.send_message(message)
|
||||||
logger.info(f"已发送订单平仓通知: {result.get('order_id')}")
|
logger.info(f"已发送订单平仓通知: {result.get('order_id')}")
|
||||||
|
|
||||||
@ -1371,25 +1396,30 @@ class CryptoAgent:
|
|||||||
"""发送实盘订单创建通知"""
|
"""发送实盘订单创建通知"""
|
||||||
side = signal.get('action', 'buy')
|
side = signal.get('action', 'buy')
|
||||||
side_text = "做多" if side == 'buy' else "做空"
|
side_text = "做多" if side == 'buy' else "做空"
|
||||||
|
side_icon = "🟢" if side == 'buy' else "🔴"
|
||||||
grade = signal.get('grade', 'N/A')
|
grade = signal.get('grade', 'N/A')
|
||||||
position_size = result.get('position_size', 'light')
|
position_size = result.get('position_size', 'light')
|
||||||
quantity = result.get('quantity', 0) # 这是保证金金额
|
quantity = result.get('quantity', 0) # 这是保证金金额
|
||||||
position_value = quantity * 20 # 持仓价值 = 保证金 × 杠杆
|
position_value = quantity * 20 # 持仓价值 = 保证金 × 杠杆
|
||||||
|
|
||||||
message = f"""💰 实盘订单已创建
|
title = f"💰 实盘订单已创建 - {symbol}"
|
||||||
|
|
||||||
交易对: {symbol}
|
content_parts = [
|
||||||
方向: {side_text}
|
f"{side_icon} **方向**: {side_text}",
|
||||||
等级: {grade}
|
f"⭐ **信号等级**: {grade}",
|
||||||
仓位: {position_size}
|
f"📊 **仓位**: {position_size}",
|
||||||
持仓价值: ${position_value:,.2f}
|
f"💰 **持仓价值**: ${position_value:,.2f}",
|
||||||
订单 ID: {result.get('order_id', '')[:12]}...
|
f"🆔 **订单ID**: {result.get('order_id', '')[:12]}...",
|
||||||
|
f"",
|
||||||
|
f"⚠️ **真实资金交易中**",
|
||||||
|
]
|
||||||
|
|
||||||
⚠️ 真实资金交易中"""
|
content = "\n".join(content_parts)
|
||||||
|
|
||||||
if self.settings.feishu_enabled:
|
if self.settings.feishu_enabled:
|
||||||
await self.feishu.send_text(message)
|
await self.feishu.send_card(title, content, "red")
|
||||||
if self.settings.telegram_enabled:
|
if self.settings.telegram_enabled:
|
||||||
|
message = f"{title}\n\n{content}"
|
||||||
await self.telegram.send_message(message)
|
await self.telegram.send_message(message)
|
||||||
logger.info(f"已发送实盘订单创建通知: {result.get('order_id')}")
|
logger.info(f"已发送实盘订单创建通知: {result.get('order_id')}")
|
||||||
|
|
||||||
@ -1411,32 +1441,36 @@ class CryptoAgent:
|
|||||||
}
|
}
|
||||||
action_text = action_map.get(action, action)
|
action_text = action_map.get(action, action)
|
||||||
|
|
||||||
message = f"""{action_text}
|
title = f"{action_text} - {symbol}"
|
||||||
|
|
||||||
交易对: {symbol}
|
content_parts = [
|
||||||
订单: {order_id[:8]}
|
f"📊 **订单**: {order_id[:8]}",
|
||||||
原因: {reason}"""
|
f"📝 **原因**: {reason}",
|
||||||
|
]
|
||||||
|
|
||||||
if action == 'ADJUST_SL_TP':
|
if action == 'ADJUST_SL_TP':
|
||||||
changes = result.get('changes', [])
|
changes = result.get('changes', [])
|
||||||
message += f"\n调整内容: {', '.join(changes)}"
|
content_parts.append(f"🔄 **调整内容**: {', '.join(changes)}")
|
||||||
|
|
||||||
elif action in ['PARTIAL_CLOSE', 'FULL_CLOSE']:
|
elif action in ['PARTIAL_CLOSE', 'FULL_CLOSE']:
|
||||||
pnl_info = result.get('pnl', {})
|
pnl_info = result.get('pnl', {})
|
||||||
if pnl_info:
|
if pnl_info:
|
||||||
pnl = pnl_info.get('pnl', 0)
|
pnl = pnl_info.get('pnl', 0)
|
||||||
pnl_percent = pnl_info.get('pnl_percent', 0)
|
pnl_percent = pnl_info.get('pnl_percent', 0)
|
||||||
message += f"\n实现盈亏: ${pnl:+.2f} ({pnl_percent:+.1f}%)"
|
content_parts.append(f"💰 **实现盈亏**: ${pnl:+.2f} ({pnl_percent:+.1f}%)")
|
||||||
|
|
||||||
if action == 'PARTIAL_CLOSE':
|
if action == 'PARTIAL_CLOSE':
|
||||||
close_percent = decision.get('close_percent', 0)
|
close_percent = decision.get('close_percent', 0)
|
||||||
remaining = result.get('remaining_quantity', 0)
|
remaining = result.get('remaining_quantity', 0)
|
||||||
message += f"\n平仓比例: {close_percent:.0f}%"
|
content_parts.append(f"📊 **平仓比例**: {close_percent:.0f}%")
|
||||||
message += f"\n剩余仓位: ${remaining:,.0f}"
|
content_parts.append(f"💵 **剩余仓位**: ${remaining:,.0f}")
|
||||||
|
|
||||||
|
content = "\n".join(content_parts)
|
||||||
|
|
||||||
if self.settings.feishu_enabled:
|
if self.settings.feishu_enabled:
|
||||||
await self.feishu.send_text(message)
|
await self.feishu.send_card(title, content, "blue")
|
||||||
if self.settings.telegram_enabled:
|
if self.settings.telegram_enabled:
|
||||||
|
message = f"{title}\n\n{content}"
|
||||||
await self.telegram.send_message(message)
|
await self.telegram.send_message(message)
|
||||||
|
|
||||||
async def _notify_signal_not_executed(
|
async def _notify_signal_not_executed(
|
||||||
|
|||||||
@ -50,22 +50,27 @@ async def price_monitor_loop():
|
|||||||
# 处理挂单成交事件
|
# 处理挂单成交事件
|
||||||
if event_type == 'order_filled':
|
if event_type == 'order_filled':
|
||||||
side_text = "做多" if result.get('side') == 'long' else "做空"
|
side_text = "做多" if result.get('side') == 'long' else "做空"
|
||||||
|
side_icon = "🟢" if result.get('side') == 'long' else "🔴"
|
||||||
grade = result.get('signal_grade', 'N/A')
|
grade = result.get('signal_grade', 'N/A')
|
||||||
|
|
||||||
message = f"""✅ 挂单成交
|
title = f"✅ 挂单成交 - {result.get('symbol')}"
|
||||||
|
content_parts = [
|
||||||
|
f"{side_icon} **方向**: {side_text}",
|
||||||
|
f"⭐ **信号等级**: {grade}",
|
||||||
|
f"💰 **挂单价**: ${result.get('entry_price', 0):,.2f}",
|
||||||
|
f"🎯 **成交价**: ${result.get('filled_price', 0):,.2f}",
|
||||||
|
f"💵 **仓位**: ${result.get('quantity', 0):,.0f}",
|
||||||
|
]
|
||||||
|
if result.get('stop_loss'):
|
||||||
|
content_parts.append(f"🛑 **止损**: ${result.get('stop_loss', 0):,.2f}")
|
||||||
|
if result.get('take_profit'):
|
||||||
|
content_parts.append(f"🎯 **止盈**: ${result.get('take_profit', 0):,.2f}")
|
||||||
|
|
||||||
交易对: {result.get('symbol')}
|
content = "\n".join(content_parts)
|
||||||
方向: {side_text}
|
|
||||||
等级: {grade}
|
|
||||||
挂单价: ${result.get('entry_price', 0):,.2f}
|
|
||||||
成交价: ${result.get('filled_price', 0):,.2f}
|
|
||||||
仓位: ${result.get('quantity', 0):,.0f}
|
|
||||||
止损: ${result.get('stop_loss', 0):,.2f}
|
|
||||||
止盈: ${result.get('take_profit', 0):,.2f}"""
|
|
||||||
|
|
||||||
# 发送通知
|
# 发送通知
|
||||||
await feishu.send_text(message)
|
await feishu.send_card(title, content, "green")
|
||||||
await telegram.send_message(message)
|
await telegram.send_message(f"{title}\n\n{content}")
|
||||||
logger.info(f"后台监控触发挂单成交: {result.get('order_id')} | {symbol}")
|
logger.info(f"后台监控触发挂单成交: {result.get('order_id')} | {symbol}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -75,31 +80,38 @@ async def price_monitor_loop():
|
|||||||
if status == 'closed_tp':
|
if status == 'closed_tp':
|
||||||
emoji = "🎯"
|
emoji = "🎯"
|
||||||
status_text = "止盈平仓"
|
status_text = "止盈平仓"
|
||||||
|
color = "green"
|
||||||
elif status == 'closed_sl':
|
elif status == 'closed_sl':
|
||||||
emoji = "🛑"
|
emoji = "🛑"
|
||||||
status_text = "止损平仓"
|
status_text = "止损平仓"
|
||||||
|
color = "red"
|
||||||
elif status == 'closed_be':
|
elif status == 'closed_be':
|
||||||
emoji = "🔒"
|
emoji = "🔒"
|
||||||
status_text = "保本止损"
|
status_text = "保本止损"
|
||||||
|
color = "orange"
|
||||||
else:
|
else:
|
||||||
emoji = "📤"
|
emoji = "📤"
|
||||||
status_text = "平仓"
|
status_text = "平仓"
|
||||||
|
color = "blue"
|
||||||
|
|
||||||
win_text = "盈利" if is_win else "亏损"
|
win_text = "盈利" if is_win else "亏损"
|
||||||
|
win_emoji = "✅" if is_win else "❌"
|
||||||
side_text = "做多" if result.get('side') == 'long' else "做空"
|
side_text = "做多" if result.get('side') == 'long' else "做空"
|
||||||
|
side_icon = "🟢" if result.get('side') == 'long' else "🔴"
|
||||||
|
|
||||||
message = f"""{emoji} 订单{status_text}
|
title = f"{emoji} 订单{status_text} - {result.get('symbol')}"
|
||||||
|
content_parts = [
|
||||||
交易对: {result.get('symbol')}
|
f"{side_icon} **方向**: {side_text}",
|
||||||
方向: {side_text}
|
f"📊 **入场**: ${result.get('entry_price', 0):,.2f}",
|
||||||
入场: ${result.get('entry_price', 0):,.2f}
|
f"🎯 **出场**: ${result.get('exit_price', 0):,.2f}",
|
||||||
出场: ${result.get('exit_price', 0):,.2f}
|
f"{win_emoji} **{win_text}**: {result.get('pnl_percent', 0):+.2f}% (${result.get('pnl_amount', 0):+.2f})",
|
||||||
{win_text}: {result.get('pnl_percent', 0):+.2f}% (${result.get('pnl_amount', 0):+.2f})
|
f"⏱️ **持仓时间**: {result.get('hold_duration', 'N/A')}",
|
||||||
持仓时间: {result.get('hold_duration', 'N/A')}"""
|
]
|
||||||
|
content = "\n".join(content_parts)
|
||||||
|
|
||||||
# 发送通知
|
# 发送通知
|
||||||
await feishu.send_text(message)
|
await feishu.send_card(title, content, color)
|
||||||
await telegram.send_message(message)
|
await telegram.send_message(f"{title}\n\n{content}")
|
||||||
logger.info(f"后台监控触发平仓: {result.get('order_id')} | {symbol}")
|
logger.info(f"后台监控触发平仓: {result.get('order_id')} | {symbol}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -223,31 +235,38 @@ async def price_monitor_loop():
|
|||||||
if status == 'closed_tp':
|
if status == 'closed_tp':
|
||||||
emoji = "🎯"
|
emoji = "🎯"
|
||||||
status_text = "止盈平仓"
|
status_text = "止盈平仓"
|
||||||
|
color = "green"
|
||||||
elif status == 'closed_sl':
|
elif status == 'closed_sl':
|
||||||
emoji = "🛑"
|
emoji = "🛑"
|
||||||
status_text = "止损平仓"
|
status_text = "止损平仓"
|
||||||
|
color = "red"
|
||||||
elif status == 'closed_be':
|
elif status == 'closed_be':
|
||||||
emoji = "📈"
|
emoji = "📈"
|
||||||
status_text = "移动止损"
|
status_text = "移动止损"
|
||||||
|
color = "orange"
|
||||||
else:
|
else:
|
||||||
emoji = "📤"
|
emoji = "📤"
|
||||||
status_text = "平仓"
|
status_text = "平仓"
|
||||||
|
color = "blue"
|
||||||
|
|
||||||
win_text = "盈利" if is_win else "亏损"
|
win_text = "盈利" if is_win else "亏损"
|
||||||
|
win_emoji = "✅" if is_win else "❌"
|
||||||
side_text = "做多" if result.get('side') == 'long' else "做空"
|
side_text = "做多" if result.get('side') == 'long' else "做空"
|
||||||
|
side_icon = "🟢" if result.get('side') == 'long' else "🔴"
|
||||||
|
|
||||||
message = f"""{emoji} 订单{status_text}
|
title = f"{emoji} 订单{status_text} - {result.get('symbol')}"
|
||||||
|
content_parts = [
|
||||||
交易对: {result.get('symbol')}
|
f"{side_icon} **方向**: {side_text}",
|
||||||
方向: {side_text}
|
f"📊 **入场**: ${result.get('entry_price', 0):,.2f}",
|
||||||
入场: ${result.get('entry_price', 0):,.2f}
|
f"🎯 **出场**: ${result.get('exit_price', 0):,.2f}",
|
||||||
出场: ${result.get('exit_price', 0):,.2f}
|
f"{win_emoji} **{win_text}**: {result.get('pnl_percent', 0):+.2f}% (${result.get('pnl_amount', 0):+.2f})",
|
||||||
{win_text}: {result.get('pnl_percent', 0):+.2f}% (${result.get('pnl_amount', 0):+.2f})
|
f"⏱️ **持仓时间**: {result.get('hold_duration', 'N/A')}",
|
||||||
持仓时间: {result.get('hold_duration', 'N/A')}"""
|
]
|
||||||
|
content = "\n".join(content_parts)
|
||||||
|
|
||||||
# 发送通知
|
# 发送通知
|
||||||
await feishu.send_text(message)
|
await feishu.send_card(title, content, color)
|
||||||
await telegram.send_message(message)
|
await telegram.send_message(f"{title}\n\n{content}")
|
||||||
logger.info(f"后台监控触发平仓: {result.get('order_id')} | {symbol}")
|
logger.info(f"后台监控触发平仓: {result.get('order_id')} | {symbol}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@ -519,6 +519,8 @@ class StockAgent:
|
|||||||
logger.info(f"\n⏸️ 信号质量不高,不发送通知")
|
logger.info(f"\n⏸️ 信号质量不高,不发送通知")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
logger.info(f"\n📢 【最佳信号】{best_signal.get('action')} {best_signal.get('grade')}级 {best_signal.get('confidence')}%")
|
||||||
|
|
||||||
# 检查置信度阈值
|
# 检查置信度阈值
|
||||||
threshold = self.settings.stock_llm_threshold * 100
|
threshold = self.settings.stock_llm_threshold * 100
|
||||||
if best_signal.get('confidence', 0) < threshold:
|
if best_signal.get('confidence', 0) < threshold:
|
||||||
@ -530,7 +532,10 @@ class StockAgent:
|
|||||||
logger.info(f"\n⏸️ 信号冷却中,不发送通知")
|
logger.info(f"\n⏸️ 信号冷却中,不发送通知")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
logger.info(f"\n✅ 满足所有条件,准备发送通知...")
|
||||||
|
|
||||||
# 发送通知
|
# 发送通知
|
||||||
|
try:
|
||||||
await self._send_signal_notification(symbol, best_signal, current_price)
|
await self._send_signal_notification(symbol, best_signal, current_price)
|
||||||
result['notified'] = True
|
result['notified'] = True
|
||||||
result['best_signal'] = best_signal
|
result['best_signal'] = best_signal
|
||||||
@ -538,6 +543,12 @@ class StockAgent:
|
|||||||
# 更新状态
|
# 更新状态
|
||||||
self.last_signals[symbol] = best_signal
|
self.last_signals[symbol] = best_signal
|
||||||
self.signal_cooldown[symbol] = datetime.now()
|
self.signal_cooldown[symbol] = datetime.now()
|
||||||
|
except Exception as notify_error:
|
||||||
|
logger.error(f"❌ 发送 {symbol} 通知失败: {notify_error}")
|
||||||
|
import traceback
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
|
result['notified'] = False
|
||||||
|
result['notify_error'] = str(notify_error)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -589,6 +600,8 @@ class StockAgent:
|
|||||||
):
|
):
|
||||||
"""发送信号通知"""
|
"""发送信号通知"""
|
||||||
try:
|
try:
|
||||||
|
logger.info(f"📤 准备发送 {symbol} 信号通知...")
|
||||||
|
|
||||||
from app.utils.signal_formatter import get_signal_formatter
|
from app.utils.signal_formatter import get_signal_formatter
|
||||||
formatter = get_signal_formatter()
|
formatter = get_signal_formatter()
|
||||||
|
|
||||||
@ -597,11 +610,20 @@ class StockAgent:
|
|||||||
title = card['title']
|
title = card['title']
|
||||||
content = card['content']
|
content = card['content']
|
||||||
|
|
||||||
|
logger.info(f" 标题: {title}")
|
||||||
|
logger.info(f" 内容长度: {len(content)} 字符")
|
||||||
|
|
||||||
# 根据信号方向选择颜色
|
# 根据信号方向选择颜色
|
||||||
color = "green" if signal.get('action') == 'buy' else "red"
|
color = "green" if signal.get('action') == 'buy' else "red"
|
||||||
|
logger.info(f" 颜色: {color}")
|
||||||
|
|
||||||
|
# 检查飞书服务
|
||||||
|
logger.info(f" 飞书服务: {type(self.feishu).__name__}")
|
||||||
|
logger.info(f" Webhook URL: {self.feishu.webhook_url[:50]}...")
|
||||||
|
|
||||||
# 发送到飞书
|
# 发送到飞书
|
||||||
await self.feishu.send_card(title, content, color)
|
await self.feishu.send_card(title, content, color)
|
||||||
|
logger.info(f" ✅ 飞书通知发送成功")
|
||||||
|
|
||||||
# 发送到 Telegram
|
# 发送到 Telegram
|
||||||
await self.telegram.send_message(formatter.format_signal_message(signal, symbol, agent_type='stock'))
|
await self.telegram.send_message(formatter.format_signal_message(signal, symbol, agent_type='stock'))
|
||||||
@ -616,7 +638,11 @@ class StockAgent:
|
|||||||
self.signal_db.add_signal(signal_to_save)
|
self.signal_db.add_signal(signal_to_save)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"发送通知失败: {e}")
|
logger.error(f"❌ 发送通知失败: {e}")
|
||||||
|
import traceback
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
|
# 重新抛出异常,让上层能够捕获
|
||||||
|
raise
|
||||||
|
|
||||||
def _validate_data(self, data: Dict[str, pd.DataFrame]) -> bool:
|
def _validate_data(self, data: Dict[str, pd.DataFrame]) -> bool:
|
||||||
"""验证数据完整性"""
|
"""验证数据完整性"""
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user