auto_trade_sys/STOP_LOSS_IMMEDIATE_CLOSE_FIX.md
薇薇安 1032295052 a
2026-01-25 09:16:16 +08:00

5.5 KiB
Raw Blame History

止损立即平仓修复说明

🔍 问题描述

时间范围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行

修复前

if current_price_val <= stop_loss_val:
    logger.error(f"{symbol} ⚠️ 当前价格(...)已触发止损价(...),无法挂止损单,应该立即平仓!")
    logger.error(f"  建议: 立即手动平仓或等待WebSocket监控触发平仓")
    sl_order = None  # ❌ 只设置None没有执行平仓

修复后

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行

新增逻辑:在挂止盈单前,也检查价格是否已经达到止盈价,如果达到则立即执行市价平仓。

# 在挂止盈单前,检查当前价格是否已经触发止盈
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 进程才能生效。

    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