253 lines
7.5 KiB
Markdown
253 lines
7.5 KiB
Markdown
# 分步止盈状态管理分析与优化方案(2026-01-27)
|
||
|
||
## 📊 日志分析
|
||
|
||
### 日志内容
|
||
|
||
```
|
||
2026-01-27 10:51:07 - AXLUSDT [实时监控] 触发第一目标止盈(30%固定止盈,基于保证金):
|
||
当前盈亏=14.65% of margin >= 目标=12.00% of margin |
|
||
当前价=0.0890, 目标价=0.0887 |
|
||
将平掉50%仓位,锁定30%盈利,剩余50%追求更高收益
|
||
|
||
2026-01-27 10:51:07 - AXLUSDT [实时监控] 部分止盈成功: 平仓110.5000,剩余110.7000
|
||
|
||
2026-01-27 10:51:07 - AXLUSDT [实时监控] 部分止盈后:剩余仓位止损移至成本价 0.0874(保本),
|
||
剩余50%仓位追求更高收益(第二目标:4.0:1盈亏比或更高)
|
||
```
|
||
|
||
---
|
||
|
||
## 🔍 问题分析
|
||
|
||
### 问题1:日志文案与实际配置不一致
|
||
|
||
**问题**:
|
||
- 日志显示:"30%固定止盈"
|
||
- 实际目标:12.00%(说明配置已改为10%,但日志文案未更新)
|
||
|
||
**影响**:
|
||
- 日志误导,不利于排查问题
|
||
|
||
**解决方案**:
|
||
- 更新日志文案,使用实际配置值(动态读取`TAKE_PROFIT_PERCENT`)
|
||
|
||
---
|
||
|
||
### 问题2:状态管理不完整
|
||
|
||
**当前实现**:
|
||
- 部分止盈后,设置`partialProfitTaken = True`
|
||
- 剩余仓位止损移至成本价(保本)
|
||
- 但最终平仓时,如果剩余仓位止损,会被标记为`stop_loss`
|
||
|
||
**问题**:
|
||
- 无法区分"纯止损"和"第一目标止盈后剩余仓位止损"
|
||
- 影响胜率、盈亏比统计的准确性
|
||
|
||
**示例场景**:
|
||
1. **场景A**:第一目标止盈(50%仓位)→ 剩余仓位第二目标止盈
|
||
- 当前标记:`take_profit`
|
||
- ✅ 合理
|
||
|
||
2. **场景B**:第一目标止盈(50%仓位)→ 剩余仓位止损(保本)
|
||
- 当前标记:`stop_loss`
|
||
- ❌ 不合理:实际上已经实现了第一目标止盈,应该算作"部分成功"
|
||
|
||
3. **场景C**:第一目标止盈(50%仓位)→ 剩余仓位移动止损
|
||
- 当前标记:`trailing_stop`
|
||
- ⚠️ 不完整:无法区分是"第一目标止盈后移动止损"还是"直接移动止损"
|
||
|
||
---
|
||
|
||
### 问题3:统计准确性受影响
|
||
|
||
**当前统计**:
|
||
- 胜率 = 盈利单数 / 总单数
|
||
- 盈亏比 = 平均盈利 / 平均亏损
|
||
|
||
**问题**:
|
||
- 场景B(第一目标止盈后剩余仓位止损)被算作"亏损单"
|
||
- 但实际上已经实现了第一目标止盈(50%仓位盈利),应该算作"部分成功"
|
||
|
||
**影响**:
|
||
- 胜率被低估
|
||
- 盈亏比被低估
|
||
- 无法准确评估分步止盈策略的效果
|
||
|
||
---
|
||
|
||
## ✅ 优化方案
|
||
|
||
### 方案1:细分订单状态(推荐)
|
||
|
||
**新增状态类型**:
|
||
- `take_profit_partial`: 第一目标止盈(部分平仓50%)
|
||
- `take_profit_partial_then_take_profit`: 第一目标止盈后,剩余仓位第二目标止盈
|
||
- `take_profit_partial_then_stop`: 第一目标止盈后,剩余仓位止损(保本)
|
||
- `take_profit_partial_then_trailing_stop`: 第一目标止盈后,剩余仓位移动止损
|
||
|
||
**保留原有状态**:
|
||
- `take_profit`: 单次止盈(未启用分步止盈)
|
||
- `stop_loss`: 止损
|
||
- `trailing_stop`: 移动止损
|
||
- `manual`: 手动平仓
|
||
- `sync`: 同步平仓
|
||
|
||
---
|
||
|
||
### 方案2:添加阶段标记字段
|
||
|
||
**新增字段**:
|
||
- `partial_profit_stage`: 分步止盈阶段
|
||
- `none`: 未启用分步止盈
|
||
- `partial_taken`: 第一目标已达成(50%仓位已平)
|
||
- `full_taken`: 第二目标已达成(全部仓位已平)
|
||
|
||
**保留`exit_reason`字段**:
|
||
- 用于标记最终平仓原因
|
||
|
||
**组合使用**:
|
||
- `partial_profit_stage = 'partial_taken'` + `exit_reason = 'stop_loss'` → 第一目标止盈后剩余仓位止损
|
||
- `partial_profit_stage = 'partial_taken'` + `exit_reason = 'take_profit'` → 第一目标止盈后剩余仓位第二目标止盈
|
||
|
||
---
|
||
|
||
## 🎯 推荐方案:方案1(细分状态)
|
||
|
||
### 理由
|
||
|
||
1. **更直观**:状态名称直接反映交易过程
|
||
2. **统计方便**:可以直接按状态统计,无需组合字段
|
||
3. **向后兼容**:保留原有状态,不影响现有统计
|
||
|
||
---
|
||
|
||
## 📊 状态映射表
|
||
|
||
| 场景 | 当前状态 | 优化后状态 | 说明 |
|
||
|------|----------|------------|------|
|
||
| 第一目标止盈(50%)→ 第二目标止盈(剩余50%) | `take_profit` | `take_profit_partial_then_take_profit` | 完整成功 |
|
||
| 第一目标止盈(50%)→ 剩余仓位止损(保本) | `stop_loss` | `take_profit_partial_then_stop` | 部分成功 |
|
||
| 第一目标止盈(50%)→ 剩余仓位移动止损 | `trailing_stop` | `take_profit_partial_then_trailing_stop` | 部分成功 |
|
||
| 单次止盈(未启用分步止盈) | `take_profit` | `take_profit` | 保持 |
|
||
| 止损 | `stop_loss` | `stop_loss` | 保持 |
|
||
| 移动止损 | `trailing_stop` | `trailing_stop` | 保持 |
|
||
| 手动平仓 | `manual` | `manual` | 保持 |
|
||
| 同步平仓 | `sync` | `sync` | 保持 |
|
||
|
||
---
|
||
|
||
## 🔧 实施步骤
|
||
|
||
### 步骤1:更新数据库结构
|
||
|
||
**SQL迁移脚本**:
|
||
```sql
|
||
-- 更新exit_reason字段,支持新的状态值
|
||
ALTER TABLE trades MODIFY COLUMN exit_reason VARCHAR(50);
|
||
|
||
-- 添加注释说明新状态
|
||
ALTER TABLE trades MODIFY COLUMN exit_reason VARCHAR(50)
|
||
COMMENT '平仓原因: manual, stop_loss, take_profit, trailing_stop, sync, take_profit_partial_then_take_profit, take_profit_partial_then_stop, take_profit_partial_then_trailing_stop';
|
||
```
|
||
|
||
---
|
||
|
||
### 步骤2:更新代码逻辑
|
||
|
||
**修改位置**:
|
||
- `trading_system/position_manager.py` → `_check_single_position`方法
|
||
- `trading_system/position_manager.py` → `close_position`方法
|
||
|
||
**修改内容**:
|
||
1. 第一目标止盈时,记录`partial_profit_taken = True`
|
||
2. 剩余仓位平仓时,根据`partial_profit_taken`和实际平仓原因,设置正确的`exit_reason`
|
||
|
||
---
|
||
|
||
### 步骤3:更新日志文案
|
||
|
||
**修改位置**:
|
||
- `trading_system/position_manager.py` → `_check_single_position`方法
|
||
|
||
**修改内容**:
|
||
- 动态读取`TAKE_PROFIT_PERCENT`配置,更新日志文案
|
||
|
||
---
|
||
|
||
### 步骤4:更新统计逻辑
|
||
|
||
**修改位置**:
|
||
- `backend/api/routes/stats.py`(如果存在)
|
||
- 前端统计展示逻辑
|
||
|
||
**修改内容**:
|
||
- 统计时,将`take_profit_partial_then_*`状态归类为"部分成功"或"成功"
|
||
|
||
---
|
||
|
||
## 📊 统计分类建议
|
||
|
||
### 胜率统计
|
||
|
||
**成功单**:
|
||
- `take_profit`
|
||
- `take_profit_partial_then_take_profit`
|
||
- `take_profit_partial_then_stop`(第一目标已达成,算作成功)
|
||
- `take_profit_partial_then_trailing_stop`(第一目标已达成,算作成功)
|
||
|
||
**失败单**:
|
||
- `stop_loss`
|
||
- `trailing_stop`(如果未启用分步止盈)
|
||
|
||
**中性单**:
|
||
- `manual`
|
||
- `sync`
|
||
|
||
---
|
||
|
||
### 盈亏比统计
|
||
|
||
**盈利单**:
|
||
- 所有`take_profit*`状态
|
||
- 计算时,`take_profit_partial_then_stop`应该算作盈利(第一目标已达成)
|
||
|
||
**亏损单**:
|
||
- `stop_loss`(纯止损)
|
||
- `trailing_stop`(如果未启用分步止盈)
|
||
|
||
---
|
||
|
||
## ⚠️ 注意事项
|
||
|
||
1. **向后兼容**:
|
||
- 保留原有状态值,不影响现有数据
|
||
- 新状态仅用于新交易
|
||
|
||
2. **数据迁移**:
|
||
- 如果需要,可以编写脚本将历史数据中的`take_profit`状态,根据是否有`partial_profit_taken`标记,转换为新状态
|
||
|
||
3. **日志优化**:
|
||
- 更新日志文案,使用实际配置值
|
||
- 添加更详细的状态转换日志
|
||
|
||
---
|
||
|
||
## ✅ 总结
|
||
|
||
**问题**:
|
||
- 日志文案与实际配置不一致
|
||
- 状态管理不完整,无法区分"纯止损"和"第一目标止盈后剩余仓位止损"
|
||
- 统计准确性受影响
|
||
|
||
**解决方案**:
|
||
- 细分订单状态,新增`take_profit_partial_then_*`状态
|
||
- 更新日志文案,使用实际配置值
|
||
- 更新统计逻辑,将"第一目标止盈后剩余仓位止损"算作成功
|
||
|
||
**预期效果**:
|
||
- 更准确的状态管理
|
||
- 更准确的胜率、盈亏比统计
|
||
- 更清晰的日志输出
|