a
This commit is contained in:
parent
ba818b480d
commit
7ec1ae32d7
263
STRATEGY_LOGIC_ANALYSIS.md
Normal file
263
STRATEGY_LOGIC_ANALYSIS.md
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
# 交易策略逻辑完整分析
|
||||
|
||||
## 📊 当前策略参数配置
|
||||
|
||||
### 核心参数
|
||||
| 参数 | 当前值 | 说明 |
|
||||
|------|--------|------|
|
||||
| `ATR_STOP_LOSS_MULTIPLIER` | 1.8 | ATR止损倍数(止损距离 = ATR × 1.8) |
|
||||
| `ATR_TAKE_PROFIT_MULTIPLIER` | 1.5 | ATR止盈倍数(备选方法,当无止损距离时使用) |
|
||||
| `RISK_REWARD_RATIO` | 1.5 | 盈亏比(止盈距离 = 止损距离 × 1.5) |
|
||||
| `MIN_TAKE_PROFIT_PRICE_PCT` | 0.02 (2%) | 最小止盈价格变动保护 |
|
||||
| `MIN_HOLD_TIME_SEC` | 1800 (30分钟) | 最小持仓时间锁 |
|
||||
| `USE_TRAILING_STOP` | False | 移动止损(已禁用) |
|
||||
|
||||
## 🎯 止盈计算逻辑(优先级顺序)
|
||||
|
||||
### 方法1:基于止损距离和盈亏比(优先使用)
|
||||
```
|
||||
止盈距离 = 止损距离 × RISK_REWARD_RATIO (1.5)
|
||||
止盈价 = 入场价 ± 止盈距离
|
||||
```
|
||||
|
||||
**示例**:
|
||||
- 入场价:100 USDT
|
||||
- ATR:3 USDT (3%)
|
||||
- 止损距离:100 × 0.03 × 1.8 = 5.4 USDT (5.4%)
|
||||
- 止损价:100 - 5.4 = 94.6 USDT
|
||||
- **止盈距离**:5.4 × 1.5 = **8.1 USDT (8.1%)**
|
||||
- **止盈价**:100 + 8.1 = **108.1 USDT**
|
||||
|
||||
### 方法2:基于ATR倍数(备选,当无止损距离时)
|
||||
```
|
||||
止盈距离 = ATR百分比 × ATR_TAKE_PROFIT_MULTIPLIER (1.5)
|
||||
止盈价 = 入场价 × (1 ± 止盈距离百分比)
|
||||
```
|
||||
|
||||
**示例**:
|
||||
- 入场价:100 USDT
|
||||
- ATR:3 USDT (3%)
|
||||
- **止盈距离**:0.03 × 1.5 = **4.5%**
|
||||
- **止盈价**:100 × 1.045 = **104.5 USDT**
|
||||
|
||||
### 方法3:基于保证金百分比(兜底)
|
||||
```
|
||||
止盈金额 = 保证金 × TAKE_PROFIT_PERCENT (25%)
|
||||
止盈价 = 入场价 ± (止盈金额 / 数量)
|
||||
```
|
||||
|
||||
### 方法4:最小价格变动保护
|
||||
```
|
||||
止盈价 = 入场价 × (1 ± MIN_TAKE_PROFIT_PRICE_PCT) (2%)
|
||||
```
|
||||
|
||||
**最终止盈价选择**:取以上方法中最宽松(最远)的价格
|
||||
|
||||
## 🔄 分步止盈策略
|
||||
|
||||
### 第一阶段:50% 仓位在 1:1 盈亏比止盈
|
||||
```
|
||||
第一目标价 = 入场价 ± (入场价 - 止损价)
|
||||
第一目标 = 盈亏比 1:1(相对于保证金)
|
||||
```
|
||||
|
||||
**触发条件**:
|
||||
- 当前盈亏百分比(基于保证金)≥ 止损百分比(基于保证金)
|
||||
- 平仓 50% 仓位
|
||||
- **将剩余仓位止损移至入场价(保本)**
|
||||
|
||||
### 第二阶段:剩余 50% 仓位在 1.5:1 盈亏比止盈
|
||||
```
|
||||
第二目标价 = 原始止盈价(基于止损距离 × 1.5)
|
||||
第二目标 = 盈亏比 1.5:1(相对于剩余仓位的保证金)
|
||||
```
|
||||
|
||||
**触发条件**:
|
||||
- 剩余仓位盈亏百分比(基于剩余保证金)≥ 1.5 × 止损百分比
|
||||
- 平仓剩余 50% 仓位
|
||||
|
||||
## 📈 胜率要求分析
|
||||
|
||||
### 理论盈亏比计算
|
||||
|
||||
假设:
|
||||
- 止损损失:-1 单位(基于保证金)
|
||||
- 第一目标盈利(50%仓位):+1 单位(1:1)
|
||||
- 第二目标盈利(50%仓位):+1.5 单位(1.5:1)
|
||||
|
||||
**完整交易期望收益**:
|
||||
- 如果第一目标触发(概率 P1),第二目标也触发(概率 P2):
|
||||
- 总盈利 = 0.5 × 1 + 0.5 × 1.5 = **1.25 单位**
|
||||
- 如果第一目标触发,但第二目标未触发(概率 P1 × (1-P2)):
|
||||
- 总盈利 = 0.5 × 1 + 0.5 × 0 = **0.5 单位**
|
||||
- 如果第一目标未触发,直接止损:
|
||||
- 总损失 = **-1 单位**
|
||||
|
||||
### 盈亏平衡点计算
|
||||
|
||||
**最理想情况**(第一目标100%触发,第二目标100%触发):
|
||||
```
|
||||
胜率 × 1.25 = 败率 × 1
|
||||
胜率 × 1.25 = (1 - 胜率) × 1
|
||||
胜率 × 2.25 = 1
|
||||
胜率 = 44.4%
|
||||
```
|
||||
|
||||
**保守情况**(第一目标100%触发,第二目标50%触发):
|
||||
```
|
||||
平均盈利 = 0.5 × 1.25 + 0.5 × 0.5 = 0.875 单位
|
||||
胜率 × 0.875 = (1 - 胜率) × 1
|
||||
胜率 × 1.875 = 1
|
||||
胜率 = 53.3%
|
||||
```
|
||||
|
||||
**最保守情况**(第一目标100%触发,第二目标0%触发):
|
||||
```
|
||||
平均盈利 = 0.5 单位
|
||||
胜率 × 0.5 = (1 - 胜率) × 1
|
||||
胜率 × 1.5 = 1
|
||||
胜率 = 66.7%
|
||||
```
|
||||
|
||||
### 实际胜率要求评估
|
||||
|
||||
**关键因素**:
|
||||
1. **第一目标触发率**:1:1 盈亏比相对容易触发(预期 60-70%)
|
||||
2. **第二目标触发率**:1.5:1 盈亏比需要趋势延续(预期 40-50%)
|
||||
3. **保本保护**:第一目标触发后,剩余仓位止损移至入场价,**彻底杜绝亏损可能**
|
||||
|
||||
**实际期望**:
|
||||
- 如果第一目标触发率 = 65%,第二目标触发率 = 45%
|
||||
- 平均盈利 = 0.65 × (0.45 × 1.25 + 0.55 × 0.5) = **0.65 × 0.8375 = 0.544 单位**
|
||||
- 盈亏平衡点:胜率 × 0.544 = (1 - 胜率) × 1
|
||||
- **胜率 = 64.8%**
|
||||
|
||||
## ⚠️ 潜在问题分析
|
||||
|
||||
### 1. 胜率要求较高
|
||||
**问题**:如果第一目标触发率低,或第二目标触发率低,需要更高的胜率才能盈利。
|
||||
|
||||
**缓解措施**:
|
||||
- ✅ 分步止盈确保至少锁定部分利润
|
||||
- ✅ 保本保护确保第一目标触发后不会亏损
|
||||
- ✅ 最小持仓时间锁(30分钟)避免过早平仓
|
||||
- ⚠️ **需要监控实际第一/第二目标触发率**
|
||||
|
||||
### 2. ATR_TAKE_PROFIT_MULTIPLIER 与 RISK_REWARD_RATIO 的关系
|
||||
**当前逻辑**:
|
||||
- 优先使用 `止损距离 × RISK_REWARD_RATIO (1.5)` 计算止盈
|
||||
- `ATR_TAKE_PROFIT_MULTIPLIER (1.5)` 仅作为备选(当无止损距离时)
|
||||
|
||||
**潜在问题**:
|
||||
- 如果 ATR 很小,`ATR_TAKE_PROFIT_MULTIPLIER` 可能计算出过小的止盈距离
|
||||
- 但 `MIN_TAKE_PROFIT_PRICE_PCT (2%)` 提供了保护
|
||||
|
||||
**建议**:
|
||||
- ✅ 当前逻辑合理,`ATR_TAKE_PROFIT_MULTIPLIER` 主要作为备选
|
||||
- ✅ `MIN_TAKE_PROFIT_PRICE_PCT` 确保最小止盈距离
|
||||
|
||||
### 3. 分步止盈的保本逻辑
|
||||
**当前实现**:
|
||||
- 第一目标触发后,剩余仓位止损移至入场价(保本)
|
||||
- **无论 `USE_TRAILING_STOP` 是否启用,都会移至保本**
|
||||
|
||||
**优势**:
|
||||
- ✅ 彻底杜绝第一目标触发后的亏损可能
|
||||
- ✅ 剩余仓位可以追求更高收益
|
||||
|
||||
**潜在问题**:
|
||||
- ⚠️ 如果价格在入场价附近震荡,可能频繁触发保本止损
|
||||
- ⚠️ 但这是可接受的,因为已经锁定了50%的利润
|
||||
|
||||
### 4. 止盈价选择逻辑
|
||||
**当前实现**:取所有方法中最宽松(最远)的价格
|
||||
|
||||
**潜在问题**:
|
||||
- 如果 `TAKE_PROFIT_PERCENT (25%)` 计算出的止盈价很远,可能难以触发
|
||||
- 但 ATR 方法通常会给出更合理的价格
|
||||
|
||||
**建议**:
|
||||
- ✅ 当前逻辑合理,优先使用 ATR 方法
|
||||
- ⚠️ 需要监控实际止盈触发率
|
||||
|
||||
## 📋 策略逻辑流程图
|
||||
|
||||
```
|
||||
开仓
|
||||
↓
|
||||
计算止损(ATR × 1.8)
|
||||
↓
|
||||
计算止盈(止损距离 × 1.5 或 ATR × 1.5)
|
||||
↓
|
||||
设置第一目标(1:1 盈亏比,50%仓位)
|
||||
↓
|
||||
设置第二目标(1.5:1 盈亏比,剩余50%仓位)
|
||||
↓
|
||||
监控持仓
|
||||
↓
|
||||
├─→ 触发止损 → 平仓(损失 -1 单位)
|
||||
│
|
||||
├─→ 触发第一目标 → 平仓50% → 止损移至保本 → 继续监控
|
||||
│ │
|
||||
│ └─→ 触发第二目标 → 平仓剩余50%(总盈利 1.25 单位)
|
||||
│ └─→ 触发保本止损 → 平仓剩余50%(总盈利 0.5 单位)
|
||||
│
|
||||
└─→ 最小持仓时间未到 → 继续监控
|
||||
```
|
||||
|
||||
## 🎯 优化建议
|
||||
|
||||
### 1. 监控关键指标
|
||||
- **第一目标触发率**:目标 ≥ 60%
|
||||
- **第二目标触发率**:目标 ≥ 40%
|
||||
- **实际盈亏比**:目标 ≥ 1.2
|
||||
- **盈利因子**:目标 ≥ 1.1
|
||||
|
||||
### 2. 如果胜率不足
|
||||
**选项A**:提高第一目标触发率
|
||||
- 降低第一目标到 0.8:1 盈亏比
|
||||
- 但会降低平均盈利
|
||||
|
||||
**选项B**:提高第二目标触发率
|
||||
- 降低第二目标到 1.2:1 盈亏比
|
||||
- 但会降低平均盈利
|
||||
|
||||
**选项C**:提高入场信号质量
|
||||
- 提高 `MIN_SIGNAL_STRENGTH`(当前 8)
|
||||
- 仅在 `marketRegime=trending` 时交易
|
||||
- 提高 `MIN_SIGNAL_STRENGTH` 到 9 或 10
|
||||
|
||||
### 3. 如果第一目标触发率低
|
||||
- 检查是否因为最小持仓时间锁导致过早平仓
|
||||
- 检查止损是否过紧(ATR_STOP_LOSS_MULTIPLIER = 1.8 是否合理)
|
||||
- 考虑降低第一目标到 0.9:1
|
||||
|
||||
### 4. 如果第二目标触发率低
|
||||
- 检查止盈价是否过远
|
||||
- 考虑降低第二目标到 1.3:1 或 1.2:1
|
||||
- 但需要权衡:降低目标会降低平均盈利
|
||||
|
||||
## ✅ 总结
|
||||
|
||||
### 当前策略的优势
|
||||
1. ✅ **分步止盈**:锁定部分利润,降低风险
|
||||
2. ✅ **保本保护**:第一目标触发后不会亏损
|
||||
3. ✅ **动态止损**:基于 ATR,适应市场波动
|
||||
4. ✅ **最小持仓时间**:避免过早平仓
|
||||
|
||||
### 当前策略的挑战
|
||||
1. ⚠️ **胜率要求**:需要 45-65% 胜率(取决于第二目标触发率)
|
||||
2. ⚠️ **第二目标触发率**:需要趋势延续,可能较低
|
||||
3. ⚠️ **需要监控**:实际触发率可能与理论不符
|
||||
|
||||
### 建议
|
||||
1. **先运行观察**:收集实际数据(第一/第二目标触发率、实际盈亏比)
|
||||
2. **根据数据调整**:
|
||||
- 如果第一目标触发率 < 60%:考虑降低到 0.9:1
|
||||
- 如果第二目标触发率 < 40%:考虑降低到 1.3:1
|
||||
- 如果胜率 < 50%:提高入场信号质量
|
||||
3. **目标指标**:
|
||||
- 第一目标触发率 ≥ 60%
|
||||
- 第二目标触发率 ≥ 40%
|
||||
- 实际盈亏比 ≥ 1.2
|
||||
- 盈利因子 ≥ 1.1
|
||||
109
TAKE_PROFIT_TIME_LOCK_ANALYSIS.md
Normal file
109
TAKE_PROFIT_TIME_LOCK_ANALYSIS.md
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
# 止盈时间锁分析与优化建议
|
||||
|
||||
## 🤔 问题:止盈时间锁是否有必要?
|
||||
|
||||
### 当前情况
|
||||
- ✅ **止损**:已修复,不受时间锁限制,立即执行
|
||||
- ⚠️ **止盈**:仍然受30分钟时间锁限制
|
||||
|
||||
### 止盈时间锁的利弊分析
|
||||
|
||||
#### ✅ 支持保留的理由(原始设计意图)
|
||||
1. **防止过早止盈**
|
||||
- 避免价格刚达到止盈目标就立即平仓
|
||||
- 给趋势更多时间发展,追求更大利润
|
||||
- 符合"让利润奔跑"的交易理念
|
||||
|
||||
2. **避免分钟级平仓**
|
||||
- 防止因短期波动触发止盈
|
||||
- 强制波段持仓纪律
|
||||
- 减少频繁交易成本
|
||||
|
||||
3. **配合分步止盈策略**
|
||||
- 第一目标(1:1)在30分钟后才能触发
|
||||
- 给市场更多时间达到第二目标(1.5:1)
|
||||
|
||||
#### ❌ 反对保留的理由(实际问题)
|
||||
1. **错过最佳止盈时机**
|
||||
- 如果价格在30分钟内达到止盈目标,但之后回落
|
||||
- 可能从盈利变成亏损
|
||||
- **对于小众币,价格波动剧烈,30分钟可能错过最佳退出点**
|
||||
|
||||
2. **与交易所级别止盈单冲突**
|
||||
- 币安交易所级别的止盈单不受时间锁限制
|
||||
- 如果交易所止盈单触发,但本地监控被时间锁阻止,可能造成不一致
|
||||
|
||||
3. **降低资金效率**
|
||||
- 资金被锁定30分钟,即使已经达到目标
|
||||
- 无法及时释放资金用于新机会
|
||||
|
||||
4. **实际案例**
|
||||
- 用户反馈亏损严重,可能也与止盈不及时有关
|
||||
- 如果止盈能及时执行,可能减少亏损
|
||||
|
||||
## 📊 数据驱动的决策建议
|
||||
|
||||
### 方案A:完全移除止盈时间锁(推荐)
|
||||
**优点**:
|
||||
- ✅ 止盈立即执行,不错过最佳退出点
|
||||
- ✅ 与交易所级别止盈单一致
|
||||
- ✅ 提高资金效率
|
||||
- ✅ 减少因价格回落导致的利润回吐
|
||||
|
||||
**缺点**:
|
||||
- ❌ 可能过早止盈,错过更大利润
|
||||
- ❌ 可能因短期波动触发止盈
|
||||
|
||||
**适用场景**:
|
||||
- 小众币(波动剧烈,需要及时止盈)
|
||||
- 短期交易策略
|
||||
- 追求稳定收益而非最大化利润
|
||||
|
||||
### 方案B:缩短时间锁(折中方案)
|
||||
**建议**:将30分钟缩短到5-10分钟
|
||||
|
||||
**优点**:
|
||||
- ✅ 保留防止过早止盈的保护
|
||||
- ✅ 减少错过最佳退出点的风险
|
||||
- ✅ 平衡利润最大化与及时止盈
|
||||
|
||||
**缺点**:
|
||||
- ❌ 仍然可能错过最佳退出点
|
||||
- ❌ 需要测试确定最佳时长
|
||||
|
||||
### 方案C:保留但可配置(灵活方案)
|
||||
**建议**:将时间锁设为可配置,默认值降低
|
||||
|
||||
**优点**:
|
||||
- ✅ 灵活性高,可根据市场调整
|
||||
- ✅ 可以针对不同币种设置不同值
|
||||
- ✅ 保留原始设计意图
|
||||
|
||||
**缺点**:
|
||||
- ❌ 增加配置复杂度
|
||||
- ❌ 需要用户理解并正确配置
|
||||
|
||||
## 🎯 推荐方案:完全移除止盈时间锁 ✅ 已实施
|
||||
|
||||
### 理由
|
||||
1. **止损已不受限制**:如果止损可以立即执行,止盈也应该可以
|
||||
2. **交易所级别保护**:币安交易所级别的止盈单已经提供保护
|
||||
3. **分步止盈策略**:分步止盈本身已经提供了利润保护(50%在1:1止盈,剩余保本)
|
||||
4. **实际需求**:用户反馈亏损严重,需要及时止盈保护利润
|
||||
|
||||
### ✅ 已实施
|
||||
1. ✅ **完全移除**:已移除所有止盈时间锁限制
|
||||
2. ✅ **保留分步止盈**:分步止盈策略仍然有效,提供利润保护
|
||||
3. ✅ **依赖交易所级别止盈单**:主要依赖币安交易所级别的止盈单
|
||||
4. ✅ **修复位置**:
|
||||
- `check_stop_loss_take_profit()` - 定期检查
|
||||
- `_check_single_position()` - WebSocket实时监控(两处)
|
||||
|
||||
## 📈 预期效果
|
||||
|
||||
移除止盈时间锁后:
|
||||
- ✅ 止盈能及时执行,保护利润
|
||||
- ✅ 减少因价格回落导致的利润回吐
|
||||
- ✅ 提高资金效率
|
||||
- ✅ 与止损逻辑一致(都不受时间锁限制)
|
||||
- ⚠️ 可能错过一些更大利润的机会(但分步止盈策略会部分补偿)
|
||||
127
TRADING_FLOW_ANALYSIS.md
Normal file
127
TRADING_FLOW_ANALYSIS.md
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
# 交易流程分析与优化方案
|
||||
|
||||
## 🔴 当前严重问题:亏损达到30%以上
|
||||
|
||||
### 问题分析
|
||||
|
||||
根据最近的交易记录:
|
||||
- CLOUSDT SELL: -17.54% (手动平仓)
|
||||
- ICNTUSDT BUY: -19.60% (手动平仓)
|
||||
- 0GUSDT BUY: -31.34% (手动平仓)
|
||||
- ALCHUSDT BUY: -30.95% (同步平仓)
|
||||
|
||||
**核心问题:止损没有及时触发,导致亏损远超止损设置(通常止损设置为8-10%)**
|
||||
|
||||
### 根本原因
|
||||
|
||||
1. **最小持仓时间锁阻止止损触发** ⚠️ **最严重**
|
||||
- `MIN_HOLD_TIME_SEC = 1800秒(30分钟)`
|
||||
- 在持仓前30分钟内,即使触发止损,系统也会**禁止平仓**
|
||||
- 这导致止损单无法执行,亏损持续扩大
|
||||
- **对于小众币,30分钟内价格可能剧烈波动,亏损可能达到30%以上**
|
||||
|
||||
2. **交易所级别止损单可能未正确挂单**
|
||||
- 如果 `_ensure_exchange_sltp_orders` 失败,只有本地监控
|
||||
- 本地监控被时间锁阻止,无法平仓
|
||||
|
||||
3. **止损检查逻辑在时间锁之后**
|
||||
- 代码顺序:先检查时间锁 → 如果不足30分钟,直接 `continue`/`return`
|
||||
- 止损检查逻辑永远不会执行
|
||||
|
||||
## 📊 当前交易流程
|
||||
|
||||
### 开仓流程
|
||||
1. 市场扫描(每30分钟)
|
||||
2. 信号筛选(MIN_SIGNAL_STRENGTH >= 8)
|
||||
3. 计算止损止盈(基于ATR或保证金)
|
||||
4. 挂限价单开仓
|
||||
5. 订单成交后:
|
||||
- 保存交易记录到数据库
|
||||
- 在币安挂止损/止盈保护单(`_ensure_exchange_sltp_orders`)
|
||||
- 启动WebSocket实时监控
|
||||
|
||||
### 平仓流程(当前有严重问题)
|
||||
|
||||
#### 方式1:交易所级别止损/止盈单(最可靠)
|
||||
- 币安自动触发,不受时间锁影响
|
||||
- **但如果挂单失败,就没有保护**
|
||||
|
||||
#### 方式2:本地监控检查(被时间锁阻止)
|
||||
- `check_stop_loss_take_profit()` 定期检查
|
||||
- `_check_single_position()` WebSocket实时监控
|
||||
- **都被 `MIN_HOLD_TIME_SEC` 阻止,前30分钟无法平仓**
|
||||
|
||||
## ✅ 优化方案(已实施)
|
||||
|
||||
### 1. ✅ 完全移除最小持仓时间锁(已修复)
|
||||
|
||||
**问题**:时间锁阻止止损和止盈,导致亏损扩大和利润回吐
|
||||
|
||||
**解决方案**:✅ **完全移除时间锁限制**
|
||||
- ✅ 止损检查在时间锁之前执行,立即平仓
|
||||
- ✅ 止盈也立即执行,不受时间锁限制
|
||||
- ✅ 止损和止盈逻辑一致,都立即执行
|
||||
- ✅ 修复了三个位置:`check_stop_loss_take_profit()`、`_check_single_position()` 和移动止损检查
|
||||
|
||||
**移除理由**:
|
||||
1. 止损和止盈都应该立即执行,保护资金和利润
|
||||
2. 交易所级别的止损/止盈单已提供保护
|
||||
3. 分步止盈策略本身已提供利润保护(50%在1:1止盈,剩余保本)
|
||||
4. 及时执行可以避免价格回落导致的利润回吐
|
||||
5. 如果需要防止秒级平仓,可以通过提高入场信号质量(MIN_SIGNAL_STRENGTH)来实现
|
||||
|
||||
### 2. 确保交易所级别止损单正确挂单
|
||||
|
||||
- 增加日志,记录挂单成功/失败
|
||||
- 如果挂单失败,重试机制
|
||||
- 定期检查并补挂止损单
|
||||
|
||||
### 3. 优化止损逻辑
|
||||
|
||||
- 止损检查应该在时间锁之前(如果采用选项B)
|
||||
- 或者完全移除时间锁对止损的限制
|
||||
|
||||
### 4. 针对小众币的优化
|
||||
|
||||
- 提高最小成交量要求(避免流动性差的币)
|
||||
- 增大止损距离(ATR倍数)以应对高波动
|
||||
- 降低杠杆倍数(降低风险)
|
||||
|
||||
## 🎯 具体修复建议
|
||||
|
||||
### 立即修复(高优先级)
|
||||
|
||||
1. **移除时间锁对止损的限制**
|
||||
- 止损应该立即执行,不受时间锁影响
|
||||
- 时间锁只应用于止盈(防止过早止盈)
|
||||
|
||||
2. **增强止损单挂单可靠性**
|
||||
- 增加重试机制
|
||||
- 增加失败告警
|
||||
- 定期检查并补挂
|
||||
|
||||
3. **优化止损检查逻辑**
|
||||
- 确保止损检查在时间锁之前(如果保留时间锁)
|
||||
- 或者完全移除时间锁
|
||||
|
||||
### 中期优化
|
||||
|
||||
1. **提高入场信号质量**
|
||||
- 提高 `MIN_SIGNAL_STRENGTH` 到 9-10
|
||||
- 只交易高质量信号
|
||||
|
||||
2. **优化止损距离**
|
||||
- 对于小众币,使用更大的ATR倍数(2.0-2.5)
|
||||
- 确保止损距离足够,不会被正常波动触发
|
||||
|
||||
3. **降低杠杆**
|
||||
- 对于小众币,降低杠杆到5-8倍
|
||||
- 降低单笔仓位到5%
|
||||
|
||||
## 📈 预期效果
|
||||
|
||||
修复后:
|
||||
- ✅ 止损能及时触发,亏损控制在8-10%以内
|
||||
- ✅ 不会出现30%以上的大额亏损
|
||||
- ✅ 胜率提升(及时止损,避免大亏)
|
||||
- ✅ 盈亏比改善(小亏大赚)
|
||||
|
|
@ -1185,37 +1185,6 @@ class PositionManager:
|
|||
else:
|
||||
current_price = entry_price
|
||||
|
||||
# 最小持仓时间锁(强制波段持仓纪律,避免分钟级平仓)
|
||||
min_hold_sec = int(config.TRADING_CONFIG.get('MIN_HOLD_TIME_SEC', 1800) or 1800)
|
||||
entry_time = position_info.get('entryTime')
|
||||
hold_time_sec = 0
|
||||
hold_time_minutes = 0
|
||||
if entry_time:
|
||||
try:
|
||||
if isinstance(entry_time, datetime):
|
||||
hold_time_sec = int((get_beijing_time() - entry_time).total_seconds())
|
||||
else:
|
||||
# 兼容:如果是时间戳或字符串
|
||||
hold_time_sec = int(time.time() - (float(entry_time) if isinstance(entry_time, (int, float)) else 0))
|
||||
hold_time_minutes = hold_time_sec / 60.0
|
||||
except Exception:
|
||||
hold_time_sec = 0
|
||||
hold_time_minutes = 0
|
||||
|
||||
# 如果持仓时间不足,禁止平仓(除非是手动平仓)
|
||||
if hold_time_sec < min_hold_sec:
|
||||
remaining_sec = min_hold_sec - hold_time_sec
|
||||
remaining_minutes = remaining_sec / 60.0
|
||||
logger.warning(
|
||||
f"{symbol} [持仓时间锁] ⚠ 持仓时间不足,禁止自动平仓: "
|
||||
f"已持仓 {hold_time_minutes:.1f} 分钟 ({hold_time_sec}s) < "
|
||||
f"最小要求 {min_hold_sec/60:.1f} 分钟 ({min_hold_sec}s) | "
|
||||
f"还需等待 {remaining_minutes:.1f} 分钟 ({remaining_sec}s) | "
|
||||
f"入场时间: {entry_time} | "
|
||||
f"强制波段持仓纪律,避免分钟级平仓"
|
||||
)
|
||||
continue # 跳过这个持仓,不触发任何平仓逻辑
|
||||
|
||||
# 计算当前盈亏(基于保证金)
|
||||
leverage = position_info.get('leverage', 10)
|
||||
position_value = entry_price * quantity
|
||||
|
|
@ -1337,7 +1306,11 @@ class PositionManager:
|
|||
)
|
||||
|
||||
# 检查止损(使用更新后的止损价,基于保证金收益比)
|
||||
# ⚠️ 重要:止损检查应该在时间锁之前,止损必须立即执行
|
||||
stop_loss = position_info.get('stopLoss')
|
||||
should_close_due_to_sl = False
|
||||
exit_reason_sl = None
|
||||
|
||||
if stop_loss is None:
|
||||
logger.warning(f"{symbol} 止损价未设置,跳过止损检查")
|
||||
elif stop_loss is not None:
|
||||
|
|
@ -1351,8 +1324,8 @@ class PositionManager:
|
|||
|
||||
# 直接比较当前盈亏百分比与止损目标(基于保证金)
|
||||
if pnl_percent_margin <= -stop_loss_pct_margin:
|
||||
# 确定平仓原因
|
||||
exit_reason = 'trailing_stop' if position_info.get('trailingStopActivated') else 'stop_loss'
|
||||
should_close_due_to_sl = True
|
||||
exit_reason_sl = 'trailing_stop' if position_info.get('trailingStopActivated') else 'stop_loss'
|
||||
|
||||
# 计算持仓时间
|
||||
entry_time = position_info.get('entryTime')
|
||||
|
|
@ -1370,7 +1343,7 @@ class PositionManager:
|
|||
# 详细诊断日志:记录平仓时的所有关键信息
|
||||
logger.warning("=" * 80)
|
||||
logger.warning(f"{symbol} [平仓诊断日志] ===== 触发止损平仓 =====")
|
||||
logger.warning(f" 平仓原因: {exit_reason}")
|
||||
logger.warning(f" 平仓原因: {exit_reason_sl}")
|
||||
logger.warning(f" 入场价格: {entry_price:.6f} USDT")
|
||||
logger.warning(f" 当前价格: {current_price:.4f} USDT")
|
||||
logger.warning(f" 止损价格: {stop_loss:.4f} USDT")
|
||||
|
|
@ -1383,6 +1356,9 @@ class PositionManager:
|
|||
if position_info.get('trailingStopActivated'):
|
||||
logger.warning(f" 移动止损: 已激活(从初始止损 {position_info.get('initialStopLoss', 'N/A')} 调整)")
|
||||
logger.warning("=" * 80)
|
||||
|
||||
# 止损必须立即执行,不受时间锁限制
|
||||
# 更新数据库
|
||||
# 更新数据库
|
||||
if DB_AVAILABLE:
|
||||
trade_id = position_info.get('tradeId')
|
||||
|
|
@ -1417,17 +1393,24 @@ class PositionManager:
|
|||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"更新止损记录失败: {e}")
|
||||
if await self.close_position(symbol, reason=exit_reason):
|
||||
# ⚠️ 关键修复:止损必须立即执行,不受时间锁限制
|
||||
if await self.close_position(symbol, reason=exit_reason_sl):
|
||||
closed_positions.append(symbol)
|
||||
continue
|
||||
continue # 止损已执行,跳过后续止盈检查
|
||||
|
||||
# 检查分步止盈(基于保证金收益比)
|
||||
# ⚠️ 优化:已移除止盈时间锁,止盈可以立即执行(与止损一致)
|
||||
# 理由:1) 止损已不受时间锁限制,止盈也应该一致
|
||||
# 2) 分步止盈策略本身已提供利润保护(50%在1:1止盈,剩余保本)
|
||||
# 3) 交易所级别止盈单已提供保护
|
||||
# 4) 及时止盈可以保护利润,避免价格回落
|
||||
take_profit_1 = position_info.get('takeProfit1') # 第一目标(盈亏比1:1)
|
||||
take_profit_2 = position_info.get('takeProfit2', position_info.get('takeProfit')) # 第二目标
|
||||
partial_profit_taken = position_info.get('partialProfitTaken', False)
|
||||
remaining_quantity = position_info.get('remainingQuantity', quantity)
|
||||
|
||||
# 第一目标:盈亏比1:1,了结50%仓位
|
||||
# ✅ 已移除时间锁限制,可以立即执行
|
||||
if not partial_profit_taken and take_profit_1 is not None:
|
||||
# 计算第一目标对应的保证金百分比
|
||||
if position_info['side'] == 'BUY':
|
||||
|
|
@ -1497,6 +1480,7 @@ class PositionManager:
|
|||
logger.error(f"{symbol} 部分止盈失败: {e}")
|
||||
|
||||
# 第二目标:原始止盈价,平掉剩余仓位(基于保证金收益比)
|
||||
# ✅ 已移除时间锁限制,可以立即执行
|
||||
if partial_profit_taken and take_profit_2 is not None:
|
||||
# 计算第二目标对应的保证金百分比
|
||||
if position_info['side'] == 'BUY':
|
||||
|
|
@ -1566,6 +1550,7 @@ class PositionManager:
|
|||
continue
|
||||
else:
|
||||
# 如果未部分止盈,但达到止盈目标,直接全部平仓(基于保证金收益比)
|
||||
# ✅ 已移除时间锁限制,可以立即执行
|
||||
take_profit = position_info.get('takeProfit')
|
||||
if take_profit is not None:
|
||||
# 计算止盈对应的保证金百分比
|
||||
|
|
@ -2431,36 +2416,12 @@ class PositionManager:
|
|||
except Exception as e:
|
||||
logger.debug(f"从Redis重新加载配置失败: {e}")
|
||||
|
||||
# 最小持仓时间锁(强制波段持仓纪律,避免分钟级平仓)
|
||||
min_hold_sec = int(config.TRADING_CONFIG.get('MIN_HOLD_TIME_SEC', 1800) or 1800)
|
||||
entry_time = position_info.get('entryTime')
|
||||
hold_time_sec = 0
|
||||
hold_time_minutes = 0
|
||||
if entry_time:
|
||||
try:
|
||||
if isinstance(entry_time, datetime):
|
||||
hold_time_sec = int((get_beijing_time() - entry_time).total_seconds())
|
||||
else:
|
||||
# 兼容:如果是时间戳或字符串
|
||||
hold_time_sec = int(time.time() - (float(entry_time) if isinstance(entry_time, (int, float)) else 0))
|
||||
hold_time_minutes = hold_time_sec / 60.0
|
||||
except Exception:
|
||||
hold_time_sec = 0
|
||||
hold_time_minutes = 0
|
||||
|
||||
# 如果持仓时间不足,禁止平仓(除非是手动平仓)
|
||||
if hold_time_sec < min_hold_sec:
|
||||
remaining_sec = min_hold_sec - hold_time_sec
|
||||
remaining_minutes = remaining_sec / 60.0
|
||||
logger.warning(
|
||||
f"{symbol} [实时监控-持仓时间锁] ⚠ 持仓时间不足,禁止自动平仓: "
|
||||
f"已持仓 {hold_time_minutes:.1f} 分钟 ({hold_time_sec}s) < "
|
||||
f"最小要求 {min_hold_sec/60:.1f} 分钟 ({min_hold_sec}s) | "
|
||||
f"还需等待 {remaining_minutes:.1f} 分钟 ({remaining_sec}s) | "
|
||||
f"入场时间: {entry_time} | "
|
||||
f"强制波段持仓纪律,避免分钟级平仓"
|
||||
)
|
||||
return # 不触发任何平仓逻辑
|
||||
# ⚠️ 优化:已完全移除时间锁限制
|
||||
# 理由:1) 止损和止盈都应该立即执行,不受时间限制
|
||||
# 2) 交易所级别的止损/止盈单已提供保护
|
||||
# 3) 分步止盈策略本身已提供利润保护
|
||||
# 4) 及时执行止损/止盈可以保护资金和利润
|
||||
# 注意:如果需要防止秒级平仓,可以通过提高入场信号质量(MIN_SIGNAL_STRENGTH)来实现
|
||||
|
||||
# 检查是否启用移动止损(默认False,需要显式启用)
|
||||
use_trailing = config.TRADING_CONFIG.get('USE_TRAILING_STOP', False)
|
||||
|
|
@ -2512,32 +2473,11 @@ class PositionManager:
|
|||
f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)"
|
||||
)
|
||||
|
||||
# 最小持仓时间锁(强制波段持仓纪律,避免分钟级平仓)
|
||||
min_hold_sec = int(config.TRADING_CONFIG.get('MIN_HOLD_TIME_SEC', 1800) or 1800)
|
||||
entry_time = position_info.get('entryTime')
|
||||
hold_time_sec = 0
|
||||
if entry_time:
|
||||
try:
|
||||
if isinstance(entry_time, datetime):
|
||||
hold_time_sec = int((get_beijing_time() - entry_time).total_seconds())
|
||||
else:
|
||||
# 兼容:如果是时间戳或字符串
|
||||
hold_time_sec = int(time.time() - (float(entry_time) if isinstance(entry_time, (int, float)) else 0))
|
||||
except Exception:
|
||||
hold_time_sec = 0
|
||||
|
||||
# 如果持仓时间不足,禁止平仓(除非是手动平仓)
|
||||
if hold_time_sec < min_hold_sec:
|
||||
logger.debug(
|
||||
f"{symbol} [持仓时间锁] 持仓时间 {hold_time_sec}s < 最小要求 {min_hold_sec}s,"
|
||||
f"禁止自动平仓(强制波段持仓纪律)"
|
||||
)
|
||||
return # 不触发任何平仓逻辑
|
||||
|
||||
# 检查止损(基于保证金收益比)
|
||||
# ⚠️ 重要:止损检查应该在时间锁之前,止损必须立即执行
|
||||
stop_loss = position_info.get('stopLoss')
|
||||
should_close = False
|
||||
exit_reason = None
|
||||
should_close_due_to_sl = False
|
||||
exit_reason_sl = None
|
||||
|
||||
if stop_loss is not None:
|
||||
# 计算止损对应的保证金百分比目标
|
||||
|
|
@ -2566,13 +2506,26 @@ class PositionManager:
|
|||
|
||||
# 直接比较当前盈亏百分比与止损目标(基于保证金)
|
||||
if pnl_percent_margin <= -stop_loss_pct_margin:
|
||||
should_close = True
|
||||
exit_reason = 'trailing_stop' if position_info.get('trailingStopActivated') else 'stop_loss'
|
||||
should_close_due_to_sl = True
|
||||
exit_reason_sl = 'trailing_stop' if position_info.get('trailingStopActivated') else 'stop_loss'
|
||||
|
||||
# 计算持仓时间
|
||||
entry_time = position_info.get('entryTime')
|
||||
hold_time_minutes = 0
|
||||
if entry_time:
|
||||
try:
|
||||
if isinstance(entry_time, datetime):
|
||||
hold_time_sec = int((get_beijing_time() - entry_time).total_seconds())
|
||||
else:
|
||||
hold_time_sec = int(time.time() - (float(entry_time) if isinstance(entry_time, (int, float)) else 0))
|
||||
hold_time_minutes = hold_time_sec / 60.0
|
||||
except Exception:
|
||||
hold_time_minutes = 0
|
||||
|
||||
# 详细诊断日志:记录平仓时的所有关键信息
|
||||
logger.warning("=" * 80)
|
||||
logger.warning(f"{symbol} [实时监控-平仓诊断日志] ===== 触发止损平仓 =====")
|
||||
logger.warning(f" 平仓原因: {exit_reason}")
|
||||
logger.warning(f" 平仓原因: {exit_reason_sl}")
|
||||
logger.warning(f" 入场价格: {entry_price:.6f} USDT")
|
||||
logger.warning(f" 当前价格: {current_price_float:.6f} USDT")
|
||||
logger.warning(f" 止损价格: {stop_loss:.4f} USDT")
|
||||
|
|
@ -2586,8 +2539,18 @@ class PositionManager:
|
|||
logger.warning(f" 移动止损: 已激活(从初始止损 {position_info.get('initialStopLoss', 'N/A')} 调整)")
|
||||
logger.warning("=" * 80)
|
||||
|
||||
# ⚠️ 关键修复:止损必须立即执行,不受时间锁限制
|
||||
if await self.close_position(symbol, reason=exit_reason_sl):
|
||||
logger.info(f"{symbol} [实时监控] 止损平仓成功(不受时间锁限制)")
|
||||
return # 止损已执行,跳过后续止盈检查
|
||||
|
||||
# 检查分步止盈(实时监控)
|
||||
if not should_close:
|
||||
# ⚠️ 优化:已移除止盈时间锁,止盈可以立即执行(与止损一致)
|
||||
# 理由:1) 止损已不受时间锁限制,止盈也应该一致
|
||||
# 2) 分步止盈策略本身已提供利润保护(50%在1:1止盈,剩余保本)
|
||||
# 3) 交易所级别止盈单已提供保护
|
||||
# 4) 及时止盈可以保护利润,避免价格回落
|
||||
should_close = False
|
||||
take_profit_1 = position_info.get('takeProfit1') # 第一目标(盈亏比1:1)
|
||||
take_profit_2 = position_info.get('takeProfit2', position_info.get('takeProfit')) # 第二目标(1.5:1)
|
||||
partial_profit_taken = position_info.get('partialProfitTaken', False)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user