5.5 KiB
止损立即平仓修复说明
🔍 问题描述
时间范围: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() 方法中:
-
挂单逻辑死锁:当
current_price已经低于stop_loss_price(做多时),币安 API 会拒绝STOP_MARKET订单,返回Order would immediately trigger(错误代码 -2021)。 -
只报警不执行:代码检测到了这个情况并打印了警告日志,但只设置了
sl_order = None,没有触发市价平仓。 -
依赖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监控 → 可能延迟或失败
- ❌ 价格继续下跌 → 亏损扩大 → 直到下次扫描才可能止损
修复后
- ✅ 检测到止损触发 → 立即执行市价平仓 → 止损保护立即生效
- ✅ 价格继续下跌 → 已平仓,不再亏损
🔄 触发场景
这个修复会在以下场景生效:
- 开仓后立即检查:在
_ensure_exchange_sltp_orders()被调用时(开仓后立即执行) - 系统重启后同步:如果系统重启,同步持仓时会调用
_ensure_exchange_sltp_orders()补挂保护单 - 定期检查:
check_stop_loss_take_profit()方法会定期检查(通过扫描间隔)
⚠️ 注意事项
-
市价平仓:修复使用
close_position()方法执行市价平仓,可能会有轻微滑点,但能确保及时止损。 -
扫描间隔影响:如果扫描间隔较长(如1小时),在间隔期间价格暴跌穿透止损线,等到下次扫描时,
_ensure_exchange_sltp_orders()会被调用(例如系统重启后),此时会立即平仓。 -
WebSocket监控:WebSocket监控仍然有效,作为第二层保护。但修复后,即使WebSocket延迟,也能通过价格检查立即平仓。
🚀 部署建议
-
重启交易进程:修复后需要重启所有
trading_system进程才能生效。supervisorctl restart auto_sys_acc1 auto_sys_acc2 auto_sys_acc3 ... -
验证修复:查看日志,确认当价格触发止损时,会看到:
{symbol} ⚠️ 当前价格(...)已触发止损价(...),无法挂止损单,立即执行市价平仓保护! {symbol} [平仓] 开始平仓操作 (原因: stop_loss) {symbol} [平仓] ✓ 平仓订单已提交 -
监控效果:观察后续交易,确认深夜价格波动时能及时止损,不再出现"只报警不平仓"的情况。
📝 相关文件
trading_system/position_manager.py:主要修复文件_ensure_exchange_sltp_orders()方法(第1101-1320行)close_position()方法(第669-769行)
✅ 修复完成时间
2026-01-25