# 止损立即平仓修复说明 ## 🔍 问题描述 **时间范围**:23点后到早上 **症状**:系统检测到价格已触发止损价,但只记录错误日志,**没有执行平仓操作**,导致亏损持续扩大。 ### 错误日志示例 ``` NOMUSDT ⚠️ 当前价格(0.00944000)已触发止损价(0.00977746),无法挂止损单,应该立即平仓! ZROUSDT ⚠️ 当前价格(2.02533560)已触发止损价(2.02531200),无法挂止损单,应该立即平仓! WCTUSDT ⚠️ 当前价格(0.08786000)已触发止损价(0.08963080),无法挂止损单,应该立即平仓! ``` ## 🎯 根本原因 在 `trading_system/position_manager.py` 的 `_ensure_exchange_sltp_orders()` 方法中: 1. **挂单逻辑死锁**:当 `current_price` 已经低于 `stop_loss_price`(做多时),币安 API 会拒绝 `STOP_MARKET` 订单,返回 `Order would immediately trigger`(错误代码 -2021)。 2. **只报警不执行**:代码检测到了这个情况并打印了警告日志,但**只设置了 `sl_order = None`,没有触发市价平仓**。 3. **依赖WebSocket延迟**:代码注释说"依赖WebSocket监控立即平仓",但WebSocket监控可能有延迟,在深夜价格剧烈波动时,无法及时止损。 ## ✅ 修复方案 ### 修复位置 `trading_system/position_manager.py` 的 `_ensure_exchange_sltp_orders()` 方法 ### 修复内容 #### 1. 止损价触发时立即平仓(第1199-1223行) **修复前**: ```python if current_price_val <= stop_loss_val: logger.error(f"{symbol} ⚠️ 当前价格(...)已触发止损价(...),无法挂止损单,应该立即平仓!") logger.error(f" 建议: 立即手动平仓或等待WebSocket监控触发平仓") sl_order = None # ❌ 只设置None,没有执行平仓 ``` **修复后**: ```python if current_price_val <= stop_loss_val: logger.error(f"{symbol} ⚠️ 当前价格({current_price_val:.8f})已触发止损价({stop_loss_val:.8f}),无法挂止损单,立即执行市价平仓保护!") logger.error(f" 入场价: {entry_price_val:.8f if entry_price_val else 'N/A'}") # ✅ 立即执行市价平仓 await self.close_position(symbol, reason='stop_loss') return # 直接返回,不再尝试挂单 ``` #### 2. 止盈价触发时立即平仓(第1272-1288行) **新增逻辑**:在挂止盈单前,也检查价格是否已经达到止盈价,如果达到则立即执行市价平仓。 ```python # 在挂止盈单前,检查当前价格是否已经触发止盈 if current_price and take_profit: try: current_price_val = float(current_price) take_profit_val = float(take_profit) # 检查是否已经触发止盈 triggered_tp = False if side == "BUY" and current_price_val >= take_profit_val: triggered_tp = True elif side == "SELL" and current_price_val <= take_profit_val: triggered_tp = True if triggered_tp: logger.info(f"{symbol} 🎯 当前价格({current_price_val:.8f})已达到止盈价({take_profit_val:.8f}),立即执行市价止盈!") await self.close_position(symbol, reason='take_profit') return except Exception as e: logger.debug(f"{symbol} 检查止盈触发条件时出错: {e}") ``` ## 📊 修复效果 ### 修复前 - ❌ 检测到止损触发 → 只记录错误日志 → 等待WebSocket监控 → **可能延迟或失败** - ❌ 价格继续下跌 → 亏损扩大 → 直到下次扫描才可能止损 ### 修复后 - ✅ 检测到止损触发 → **立即执行市价平仓** → 止损保护立即生效 - ✅ 价格继续下跌 → **已平仓,不再亏损** ## 🔄 触发场景 这个修复会在以下场景生效: 1. **开仓后立即检查**:在 `_ensure_exchange_sltp_orders()` 被调用时(开仓后立即执行) 2. **系统重启后同步**:如果系统重启,同步持仓时会调用 `_ensure_exchange_sltp_orders()` 补挂保护单 3. **定期检查**:`check_stop_loss_take_profit()` 方法会定期检查(通过扫描间隔) ## ⚠️ 注意事项 1. **市价平仓**:修复使用 `close_position()` 方法执行市价平仓,可能会有轻微滑点,但能确保及时止损。 2. **扫描间隔影响**:如果扫描间隔较长(如1小时),在间隔期间价格暴跌穿透止损线,等到下次扫描时,`_ensure_exchange_sltp_orders()` 会被调用(例如系统重启后),此时会立即平仓。 3. **WebSocket监控**:WebSocket监控仍然有效,作为第二层保护。但修复后,即使WebSocket延迟,也能通过价格检查立即平仓。 ## 🚀 部署建议 1. **重启交易进程**:修复后需要重启所有 `trading_system` 进程才能生效。 ```bash supervisorctl restart auto_sys_acc1 auto_sys_acc2 auto_sys_acc3 ... ``` 2. **验证修复**:查看日志,确认当价格触发止损时,会看到: ``` {symbol} ⚠️ 当前价格(...)已触发止损价(...),无法挂止损单,立即执行市价平仓保护! {symbol} [平仓] 开始平仓操作 (原因: stop_loss) {symbol} [平仓] ✓ 平仓订单已提交 ``` 3. **监控效果**:观察后续交易,确认深夜价格波动时能及时止损,不再出现"只报警不平仓"的情况。 ## 📝 相关文件 - `trading_system/position_manager.py`:主要修复文件 - `_ensure_exchange_sltp_orders()` 方法(第1101-1320行) - `close_position()` 方法(第669-769行) ## ✅ 修复完成时间 2026-01-25