From 599a3498ba9e473c5d2bb5af2e2366c753c24655 Mon Sep 17 00:00:00 2001 From: aaron <> Date: Sun, 29 Mar 2026 10:35:22 +0800 Subject: [PATCH] update --- backend/app/crypto_agent/crypto_agent.py | 3 +- .../crypto_agent/executor/bitget_executor.py | 35 ++-- .../executor/hyperliquid_executor.py | 55 +++--- check_bitget_tp_sl.py | 163 ++++++++++++++++++ 4 files changed, 209 insertions(+), 47 deletions(-) create mode 100644 check_bitget_tp_sl.py diff --git a/backend/app/crypto_agent/crypto_agent.py b/backend/app/crypto_agent/crypto_agent.py index 2a735e3..c73ae3e 100644 --- a/backend/app/crypto_agent/crypto_agent.py +++ b/backend/app/crypto_agent/crypto_agent.py @@ -716,13 +716,14 @@ class CryptoAgent: 'symbol': symbol, 'action': signal_action, 'confidence': main_signal.get('confidence', 50), + 'grade': main_signal.get('grade', 'C'), # 添加信号等级 'entry_price': main_signal.get('entry_price', current_price), 'stop_loss': main_signal.get('stop_loss'), 'take_profit': main_signal.get('take_profit'), 'reasoning': main_signal.get('reasoning', ''), } - logger.info(f" 信号: {signal_action} {symbol} @ ${trading_signal['entry_price']:.2f} (置信度 {trading_signal['confidence']}%)") + logger.info(f" 信号: {signal_action} {symbol} @ ${trading_signal['entry_price']:.2f} (置信度 {trading_signal['confidence']}%, {trading_signal['grade']}级)") # 2.1 模拟盘处理 if self.settings.paper_trading_enabled: diff --git a/backend/app/crypto_agent/executor/bitget_executor.py b/backend/app/crypto_agent/executor/bitget_executor.py index e8b77e8..dcf5236 100644 --- a/backend/app/crypto_agent/executor/bitget_executor.py +++ b/backend/app/crypto_agent/executor/bitget_executor.py @@ -64,28 +64,21 @@ class BitgetExecutor(BaseExecutor): order_id = result.get('order_id') order_status = result.get('order_status', 'filled') - # 设置止盈止损(成交后) + # 设置止盈止损 + # 策略:总是记录到 pending,由定期检查机制处理 + # 原因:Bitget 的持仓确认可能有延迟,立即设置可能失败 if stop_loss or take_profit: - if order_status == 'filled': - # 已成交,立即设置 - tp_sl_result = self.bitget.set_tp_sl( - symbol=symbol, - is_long=is_buy, - size=contracts, - tp_price=take_profit, - sl_price=stop_loss - ) - if not tp_sl_result.get('success'): - logger.warning(f" ⚠️ 止盈止损设置失败: {tp_sl_result.get('error')}") - result['tp_sl_warning'] = tp_sl_result.get('error') - else: - # 挂单中,记录到待处理列表 - logger.info(f" 📌 挌单中,TP/SL 将在成交后设置") - # 由 crypto_agent 的循环检查机制处理 - result['pending_tp_sl'] = { - 'stop_loss': stop_loss, - 'take_profit': take_profit - } + # 返回给 crypto_agent 的 pending_tp_sl 格式 + # crypto_agent 会合并: {symbol, is_long, contracts, **pending_tp_sl} + result['pending_tp_sl'] = { + 'tp_price': take_profit, + 'sl_price': stop_loss + } + # 同时记录 contracts 到 result,供 crypto_agent 使用 + result['contracts'] = contracts + + logger.info(f" 📌 已记录 TP/SL 到待处理列表: TP=${take_profit}, SL=${stop_loss}") + logger.info(f" 📌 将由定期检查机制在持仓确认后自动设置") logger.info(f" ✅ 开仓成功: {symbol} {contracts}张 @ ${order_type}") diff --git a/backend/app/crypto_agent/executor/hyperliquid_executor.py b/backend/app/crypto_agent/executor/hyperliquid_executor.py index 1ae2eeb..cb92ae9 100644 --- a/backend/app/crypto_agent/executor/hyperliquid_executor.py +++ b/backend/app/crypto_agent/executor/hyperliquid_executor.py @@ -49,25 +49,26 @@ class HyperliquidExecutor(BaseExecutor): # 设置杠杆 self.hyperliquid.update_leverage(symbol, leverage) - # 下单(Hyperliquid 支持在下单时设置 TP/SL) + # 下单 is_buy = (action == 'buy') - order_params = { - 'symbol': symbol, - 'is_buy': is_buy, - 'size': position_size, - 'price': entry_price if order_type == 'limit' else None, - 'order_type': order_type, - } - - # 如果支持下单时设置 TP/SL,添加到参数中 - if stop_loss or take_profit: - if self.should_set_tp_sl_on_order(): - order_params['sl'] = stop_loss - order_params['tp'] = take_profit - logger.info(f" 下单时设置 TP/SL: SL=${stop_loss}, TP={take_profit}") - - result = self.hyperliquid.place_order(**order_params) + if order_type == 'market': + # 市价单 + result = self.hyperliquid.place_market_order( + symbol=symbol, + is_buy=is_buy, + size=position_size, + reduce_only=False + ) + else: + # 限价单 + result = self.hyperliquid.place_limit_order( + symbol=symbol, + is_buy=is_buy, + size=position_size, + price=entry_price, + reduce_only=False + ) if not result.get('success'): return result @@ -93,14 +94,18 @@ class HyperliquidExecutor(BaseExecutor): } ) - # 如果成交且未在下单时设置 TP/SL,单独设置 - if order_status == 'filled' and not self.should_set_tp_sl_on_order(): - if stop_loss or take_profit: - tp_sl_result = await self.set_stop_loss_take_profit( - symbol, order_id, stop_loss, take_profit, position_size - ) - if not tp_sl_result.get('success'): - result['tp_sl_warning'] = tp_sl_result.get('message') + # 成交后单独设置止盈止损(Hyperliquid 不支持下单时设置 TP/SL) + if order_status == 'filled' and (stop_loss or take_profit): + tp_sl_result = self.hyperliquid.set_tp_sl( + symbol=symbol, + is_long=is_buy, + size=position_size, + tp_price=take_profit, + sl_price=stop_loss + ) + if not tp_sl_result.get('success'): + logger.warning(f" ⚠️ 止盈止损设置失败: {tp_sl_result.get('message')}") + result['tp_sl_warning'] = tp_sl_result.get('message') return result diff --git a/check_bitget_tp_sl.py b/check_bitget_tp_sl.py new file mode 100644 index 0000000..1913f25 --- /dev/null +++ b/check_bitget_tp_sl.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +""" +Bitget 止盈止损诊断工具 +检查当前持仓、挂单、以及待设置的 TP/SL +""" +import sys +import os +import asyncio + +# 添加后端路径 +sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'backend')) + +from app.config import get_settings +from app.services.bitget_live_trading_service import get_bitget_live_service +from app.services.bitget_trading_api_sdk import get_bitget_trading_api + +def diagnose(): + """诊断 Bitget 止盈止损状态""" + settings = get_settings() + + print("=" * 80) + print("🔍 Bitget 止盈止损诊断工具") + print("=" * 80) + + # 1. 检查配置 + print("\n📋 1. 检查配置") + print(f" Bitget 交易已启用: {settings.bitget_trading_enabled}") + + if not settings.bitget_trading_enabled: + print(" ❌ Bitget 交易未启用") + return + + # 2. 获取服务实例 + print("\n🔧 2. 初始化服务") + bitget_service = get_bitget_live_service() + + if not bitget_service: + print(" ❌ Bitget 服务初始化失败") + return + + print(" ✅ Bitget 服务已初始化") + + # 3. 检查账户状态 + print("\n💰 3. 账户状态") + account_state = bitget_service.get_account_state() + + if account_state: + print(f" 账户价值: ${account_state.get('account_value', 0):,.2f}") + print(f" 已用保证金: ${account_state.get('total_margin_used', 0):,.2f}") + print(f" 可用余额: ${account_state.get('available_balance', 0):,.2f}") + else: + print(" ⚠️ 无法获取账户状态") + + # 4. 检查持仓 + print("\n📊 4. 当前持仓") + positions = bitget_service.get_open_positions() + + if not positions: + print(" 📭 无持仓") + else: + print(f" 发现 {len(positions)} 个持仓:") + for pos in positions: + symbol = pos.get('coin', pos.get('symbol', 'Unknown')) + size = pos.get('size', 0) + entry_price = pos.get('entry_price', 0) + unrealized_pnl = pos.get('unrealized_pnl', 0) + leverage = pos.get('leverage', 1) + + side = '做多' if size > 0 else '做空' + size_abs = abs(size) + + print(f"\n 🎯 {symbol} {side}") + print(f" 大小: {size_abs:.4f}") + print(f" 入场价: ${entry_price:,.2f}") + print(f" 杠杆: {leverage}x") + print(f" 未实现盈亏: ${unrealized_pnl:,.2f}") + + # 检查是否有 TP/SL + tp_sl = bitget_service.get_tp_sl_prices(symbol) + tp_price = tp_sl.get('take_profit') + sl_price = tp_sl.get('stop_loss') + + if tp_price or sl_price: + print(f" ✅ 止盈止损已设置:") + if tp_price: + print(f" 止盈: ${tp_price:,.2f}") + if sl_price: + print(f" 止损: ${sl_price:,.2f}") + else: + print(f" ❌ 止盈止损未设置!") + + # 5. 检查挂单 + print("\n📌 5. 当前挂单") + trading_api = get_bitget_trading_api() + + if not trading_api: + print(" ❌ Bitget Trading API 初始化失败") + return + + open_orders = trading_api.get_open_orders() + + if not open_orders: + print(" 📭 无挂单") + else: + print(f" 发现 {len(open_orders)} 个挂单:") + for order in open_orders: + symbol = order.get('symbol', 'Unknown') + order_id = order.get('id', 'Unknown') + side = order.get('side', 'Unknown') + amount = order.get('amount', 0) + price = order.get('price', 0) + order_type = order.get('type', 'Unknown') + reduce_only = order.get('reduceOnly', False) + + side_text = '买入' if side == 'buy' else '卖出' + order_type_text = '限价' if order_type == 'limit' else order_type + + print(f"\n 📝 订单 #{order_id}") + print(f" 交易对: {symbol}") + print(f" 类型: {order_type_text} {side_text}") + print(f" 数量: {amount}") + print(f" 价格: ${price:,.2f}") + print(f" 只平仓: {'是' if reduce_only else '否'}") + + # 6. 总结 + print("\n" + "=" * 80) + print("📝 诊断总结:") + print("=" * 80) + + if positions: + no_tp_sl_count = 0 + for pos in positions: + symbol = pos.get('coin', pos.get('symbol', 'Unknown')) + tp_sl = bitget_service.get_tp_sl_prices(symbol) + if not tp_sl.get('take_profit') and not tp_sl.get('stop_loss'): + no_tp_sl_count += 1 + + if no_tp_sl_count > 0: + print(f"\n⚠️ 警告: {no_tp_sl_count} 个持仓没有设置止盈止损!") + print("\n可能的原因:") + print(" 1. 挂单刚刚成交,定期检查还未运行(每5分钟检查一次)") + print(" 2. 止盈止损设置失败,查看日志确认") + print(" 3. 挂单还在等待成交") + print("\n建议:") + print(" • 等待下一个 5 分钟检查周期") + print(" • 或手动在 Bitget 网页/App 设置止盈止损") + print(" • 或重启后端服务,立即触发检查") + else: + print("\n✅ 所有持仓都已设置止盈止损") + else: + print("\n✅ 当前无持仓") + + print("\n" + "=" * 80) + +if __name__ == "__main__": + try: + diagnose() + except KeyboardInterrupt: + print("\n\n👋 诊断已取消") + except Exception as e: + print(f"\n❌ 诊断失败: {e}") + import traceback + traceback.print_exc()