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

129 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 止损立即平仓修复说明
## 🔍 问题描述
**时间范围**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