From 16c4cfbdd8b2404bba705583581195348e44f309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=87=E8=96=87=E5=AE=89?= Date: Tue, 27 Jan 2026 11:11:03 +0800 Subject: [PATCH] a --- .../add_partial_profit_exit_reasons.sql | 42 +++ ...管ç†åˆ†æžä¸Žä¼˜åŒ–方案_2026-01-27.md | 252 ++++++++++++++++++ ...¶æ€ç»†åˆ†å®žæ–½å®Œæˆæ€»ç»“_2026-01-27.md | 160 +++++++++++ trading_system/position_manager.py | 38 ++- 4 files changed, 486 insertions(+), 6 deletions(-) create mode 100644 backend/database/add_partial_profit_exit_reasons.sql create mode 100644 docs/分步止盈状æ€ç®¡ç†åˆ†æžä¸Žä¼˜åŒ–方案_2026-01-27.md create mode 100644 docs/分步止盈状æ€ç»†åˆ†å®žæ–½å®Œæˆæ€»ç»“_2026-01-27.md diff --git a/backend/database/add_partial_profit_exit_reasons.sql b/backend/database/add_partial_profit_exit_reasons.sql new file mode 100644 index 0000000..00c7b5e --- /dev/null +++ b/backend/database/add_partial_profit_exit_reasons.sql @@ -0,0 +1,42 @@ +-- 分步止盈状æ€ç»†åˆ†ï¼šæ·»åŠ æ–°çš„exit_reasonå€¼æ”¯æŒ +-- 执行时间:2026-01-27 + +-- 1. æ›´æ–°exit_reason字段注释,说明新的状æ€å€¼ +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. 验è¯å­—段长度是å¦è¶³å¤Ÿï¼ˆVARCHAR(50)应该足够) +SELECT + COLUMN_NAME, + COLUMN_TYPE, + COLUMN_COMMENT +FROM + INFORMATION_SCHEMA.COLUMNS +WHERE + TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'trades' + AND COLUMN_NAME = 'exit_reason'; + +-- 3. 查看当å‰exit_reason的分布情况(用于验è¯ï¼‰ +SELECT + exit_reason, + COUNT(*) as count, + ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM trades WHERE status = 'closed'), 2) as percentage +FROM + trades +WHERE + status = 'closed' +GROUP BY + exit_reason +ORDER BY + count DESC; + +-- 说明: +-- 新的状æ€å€¼ï¼š +-- - take_profit_partial_then_take_profit: 第一目标止盈(50%仓ä½ï¼‰åŽï¼Œå‰©ä½™ä»“ä½ç¬¬äºŒç›®æ ‡æ­¢ç›ˆ +-- - take_profit_partial_then_stop: 第一目标止盈(50%仓ä½ï¼‰åŽï¼Œå‰©ä½™ä»“使­¢æŸï¼ˆä¿æœ¬ï¼‰ +-- - take_profit_partial_then_trailing_stop: 第一目标止盈(50%仓ä½ï¼‰åŽï¼Œå‰©ä½™ä»“ä½ç§»åŠ¨æ­¢æŸ +-- +-- 这些状æ€ç”¨äºŽæ›´å‡†ç¡®åœ°ç»Ÿè®¡èƒœçŽ‡å’Œç›ˆäºæ¯”: +-- - 第一目标止盈åŽå‰©ä½™ä»“使­¢æŸï¼Œåº”该算作"部分æˆåŠŸ"(第一目标已达æˆï¼‰ +-- - 第一目标止盈åŽå‰©ä½™ä»“ä½ç¬¬äºŒç›®æ ‡æ­¢ç›ˆï¼Œåº”该算作"完整æˆåŠŸ" diff --git a/docs/分步止盈状æ€ç®¡ç†åˆ†æžä¸Žä¼˜åŒ–方案_2026-01-27.md b/docs/分步止盈状æ€ç®¡ç†åˆ†æžä¸Žä¼˜åŒ–方案_2026-01-27.md new file mode 100644 index 0000000..3fdaac1 --- /dev/null +++ b/docs/分步止盈状æ€ç®¡ç†åˆ†æžä¸Žä¼˜åŒ–方案_2026-01-27.md @@ -0,0 +1,252 @@ +# 分步止盈状æ€ç®¡ç†åˆ†æžä¸Žä¼˜åŒ–方案(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_*`çŠ¶æ€ +- 更新日志文案,使用实际é…置值 +- 更新统计逻辑,将"第一目标止盈åŽå‰©ä½™ä»“使­¢æŸ"算作æˆåŠŸ + +**预期效果**: +- 更准确的状æ€ç®¡ç† +- 更准确的胜率ã€ç›ˆäºæ¯”统计 +- 更清晰的日志输出 diff --git a/docs/分步止盈状æ€ç»†åˆ†å®žæ–½å®Œæˆæ€»ç»“_2026-01-27.md b/docs/分步止盈状æ€ç»†åˆ†å®žæ–½å®Œæˆæ€»ç»“_2026-01-27.md new file mode 100644 index 0000000..53b990e --- /dev/null +++ b/docs/分步止盈状æ€ç»†åˆ†å®žæ–½å®Œæˆæ€»ç»“_2026-01-27.md @@ -0,0 +1,160 @@ +# 分步止盈状æ€ç»†åˆ†å®žæ–½å®Œæˆæ€»ç»“(2026-01-27) + +## ✅ 已完æˆçš„优化 + +### 1. 日志文案优化 + +**修改ä½ç½®**:`trading_system/position_manager.py:2858-2865` + +**优化内容**: +- 动æ€è¯»å–`TAKE_PROFIT_PERCENT`é…置值 +- 更新日志文案,使用实际é…置值(如10%ï¼‰è€Œä¸æ˜¯ç¡¬ç¼–ç çš„"30%" + +**效果**: +- æ—¥å¿—æ›´å‡†ç¡®ï¼Œåæ˜ å®žé™…é…ç½® +- é…ç½®å˜æ›´åŽï¼Œæ—¥å¿—自动更新 + +--- + +### 2. 订å•状æ€ç»†åˆ† + +**新增状æ€ç±»åž‹**: +- `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`: åŒæ­¥å¹³ä»“ + +--- + +### 3. 代ç ä¿®æ”¹ä½ç½® + +#### 修改1ï¼šç¬¬äºŒç›®æ ‡æ­¢ç›ˆçŠ¶æ€ +**ä½ç½®**:`trading_system/position_manager.py:2923` +- 从`take_profit`改为`take_profit_partial_then_take_profit` + +#### 修改2ï¼šå‰©ä½™ä»“ä½æ­¢æŸçжæ€ï¼ˆå®žæ—¶ç›‘控) +**ä½ç½®**:`trading_system/position_manager.py:2832-2835` +- 检查`partial_profit_taken`,如果为True,设置`take_profit_partial_then_stop` + +#### 修改3ï¼šå‰©ä½™ä»“ä½æ­¢æŸçжæ€ï¼ˆäº¤æ˜“æ‰€æ­¢ç›ˆå•æ£€æŸ¥ï¼‰ +**ä½ç½®**:`trading_system/position_manager.py:1553-1555` +- 检查`partial_profit_taken`,如果为Trueï¼Œæ ¹æ®æ˜¯å¦ç§»åŠ¨æ­¢æŸè®¾ç½®ç›¸åº”çŠ¶æ€ + +#### 修改4:剩余仓ä½ç§»åŠ¨æ­¢æŸçжæ€ï¼ˆå®žæ—¶ç›‘控) +**ä½ç½®**:`trading_system/position_manager.py:2798-2800` +- 检查`partial_profit_taken`,如果为Trueï¼Œæ ¹æ®æ˜¯å¦ç§»åŠ¨æ­¢æŸè®¾ç½®ç›¸åº”çŠ¶æ€ + +--- + +### 4. æ•°æ®åº“è¿ç§»è„šæœ¬ + +**文件**:`backend/database/add_partial_profit_exit_reasons.sql` + +**内容**: +- æ›´æ–°`exit_reason`字段注释,说明新的状æ€å€¼ +- 验è¯å­—段长度 +- 查看当å‰çжæ€åˆ†å¸ƒ + +--- + +## 📊 çŠ¶æ€æ˜ å°„表 + +| 场景 | åŽŸçŠ¶æ€ | æ–°çŠ¶æ€ | 说明 | +|------|--------|--------|------| +| 第一目标止盈(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` | ä¿æŒ | + +--- + +## 🎯 统计分类建议 + +### 胜率统计 + +**æˆåŠŸå•**: +- `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. **æ•°æ®åº“è¿ç§»**: + - 执行`backend/database/add_partial_profit_exit_reasons.sql` + - 更新字段注释,说明新的状æ€å€¼ + +2. **å‘åŽå…¼å®¹**: + - ä¿ç•™åŽŸæœ‰çŠ¶æ€å€¼ï¼Œä¸å½±å“çŽ°æœ‰æ•°æ® + - 新状æ€ä»…用于新交易 + +3. **统计逻辑更新**: + - å‰ç«¯ç»Ÿè®¡å±•ç¤ºéœ€è¦æ›´æ–°ï¼Œå°†`take_profit_partial_then_*`状æ€å½’类为"æˆåŠŸ"或"部分æˆåŠŸ" + +--- + +## 📠下一步 + +1. **执行数æ®åº“è¿ç§»**: + ```bash + mysql -u root -p auto_trade_sys < backend/database/add_partial_profit_exit_reasons.sql + ``` + +2. **æ›´æ–°å‰ç«¯ç»Ÿè®¡é€»è¾‘**: + - 修改统计展示,将`take_profit_partial_then_*`状æ€å½’类为"æˆåŠŸ" + - å¯ä»¥æ·»åŠ "部分æˆåŠŸ"åˆ†ç±»ï¼Œç”¨äºŽæ›´è¯¦ç»†çš„åˆ†æž + +3. **测试验è¯**: + - 测试分步止盈场景,验è¯çжæ€è®¾ç½®æ­£ç¡® + - 验è¯ç»Ÿè®¡ç»“果是å¦å‡†ç¡® + +--- + +## ✅ 总结 + +**问题**: +- 日志文案与实际é…ç½®ä¸ä¸€è‡´ +- 状æ€ç®¡ç†ä¸å®Œæ•´ï¼Œæ— æ³•区分"纯止æŸ"å’Œ"第一目标止盈åŽå‰©ä½™ä»“使­¢æŸ" +- 统计准确性å—å½±å“ + +**解决方案**: +- ✅ 更新日志文案,使用实际é…置值 +- ✅ 细分订å•状æ€ï¼Œæ–°å¢ž`take_profit_partial_then_*`çŠ¶æ€ +- ✅ 更新代ç é€»è¾‘,根æ®`partial_profit_taken`è®¾ç½®æ­£ç¡®çš„çŠ¶æ€ + +**预期效果**: +- ✅ 更准确的状æ€ç®¡ç† +- ✅ 更准确的胜率ã€ç›ˆäºæ¯”统计 +- ✅ 更清晰的日志输出 diff --git a/trading_system/position_manager.py b/trading_system/position_manager.py index 551f868..02318fb 100644 --- a/trading_system/position_manager.py +++ b/trading_system/position_manager.py @@ -678,7 +678,7 @@ class PositionManager: Args: symbol: 交易对 - reason: 平仓原因(manual, stop_loss, take_profit, trailing_stop, sync) + reason: 平仓原因(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) Returns: æ˜¯å¦æˆåŠŸ @@ -1552,7 +1552,15 @@ class PositionManager: # 直接比较当å‰ç›ˆäºç™¾åˆ†æ¯”与止æŸç›®æ ‡ï¼ˆåŸºäºŽä¿è¯é‡‘) if pnl_percent_margin <= -stop_loss_pct_margin: should_close_due_to_sl = True - exit_reason_sl = 'trailing_stop' if position_info.get('trailingStopActivated') else 'stop_loss' + # âš ï¸ 2026-01-27ä¼˜åŒ–ï¼šå¦‚æžœå·²éƒ¨åˆ†æ­¢ç›ˆï¼Œç»†åˆ†çŠ¶æ€ + partial_profit_taken = position_info.get('partialProfitTaken', False) + if partial_profit_taken: + if position_info.get('trailingStopActivated'): + exit_reason_sl = 'take_profit_partial_then_trailing_stop' + else: + exit_reason_sl = 'take_profit_partial_then_stop' + else: + exit_reason_sl = 'trailing_stop' if position_info.get('trailingStopActivated') else 'stop_loss' # 计算æŒä»“æ—¶é—´ entry_time = position_info.get('entryTime') @@ -2797,7 +2805,14 @@ class PositionManager: # 直接比较当å‰ç›ˆäºç™¾åˆ†æ¯”与止æŸç›®æ ‡ï¼ˆåŸºäºŽä¿è¯é‡‘) if pnl_percent_margin <= -stop_loss_pct_margin: should_close_due_to_sl = True - exit_reason_sl = 'trailing_stop' if position_info.get('trailingStopActivated') else 'stop_loss' + # âš ï¸ 2026-01-27ä¼˜åŒ–ï¼šå¦‚æžœå·²éƒ¨åˆ†æ­¢ç›ˆï¼Œç»†åˆ†çŠ¶æ€ + if partial_profit_taken: + if position_info.get('trailingStopActivated'): + exit_reason_sl = 'take_profit_partial_then_trailing_stop' + else: + exit_reason_sl = 'take_profit_partial_then_stop' + else: + exit_reason_sl = 'trailing_stop' if position_info.get('trailingStopActivated') else 'stop_loss' # 计算æŒä»“æ—¶é—´ entry_time = position_info.get('entryTime') @@ -2829,6 +2844,11 @@ class PositionManager: logger.warning(f" 移动止æŸ: 已激活(从åˆå§‹æ­¢æŸ {position_info.get('initialStopLoss', 'N/A')} 调整)") logger.warning("=" * 80) + # âš ï¸ 2026-01-27优化:如果已部分止盈,细分状æ€ä¸º"第一目标止盈åŽå‰©ä½™ä»“使­¢æŸ" + if partial_profit_taken: + exit_reason_sl = 'take_profit_partial_then_stop' + logger.info(f"{symbol} [实时监控] 第一目标止盈åŽï¼Œå‰©ä½™ä»“ä½è§¦å‘æ­¢æŸï¼ˆä¿æœ¬ï¼‰") + # âš ï¸ å…³é”®ä¿®å¤ï¼šæ­¢æŸå¿…é¡»ç«‹å³æ‰§è¡Œï¼Œä¸å—æ—¶é—´é”é™åˆ¶ if await self.close_position(symbol, reason=exit_reason_sl): logger.info(f"{symbol} [实时监控] æ­¢æŸå¹³ä»“æˆåŠŸï¼ˆä¸å—æ—¶é—´é”é™åˆ¶ï¼‰") @@ -2857,11 +2877,16 @@ class PositionManager: # 直接比较当å‰ç›ˆäºç™¾åˆ†æ¯”与第一目标(基于ä¿è¯é‡‘) if pnl_percent_margin >= take_profit_1_pct_margin: + # âš ï¸ 2026-01-27优化:动æ€è¯»å–é…置值,更新日志文案 + take_profit_pct_config = config.TRADING_CONFIG.get('TAKE_PROFIT_PERCENT', 0.10) + if take_profit_pct_config > 1: + take_profit_pct_config = take_profit_pct_config / 100.0 + take_profit_pct_display = take_profit_pct_config * 100 logger.info( - f"{symbol} [实时监控] 触å‘第一目标止盈(30%固定止盈,基于ä¿è¯é‡‘): " + f"{symbol} [实时监控] 触å‘第一目标止盈({take_profit_pct_display:.1f}%固定止盈,基于ä¿è¯é‡‘): " f"当å‰ç›ˆäº={pnl_percent_margin:.2f}% of margin >= 目标={take_profit_1_pct_margin:.2f}% of margin | " f"当å‰ä»·={current_price_float:.4f}, 目标价={take_profit_1:.4f} | " - f"将平掉50%仓ä½ï¼Œé”定30%盈利,剩余50%追求更高收益" + f"将平掉50%仓ä½ï¼Œé”定{take_profit_pct_display:.1f}%盈利,剩余50%追求更高收益" ) # 部分平仓50% partial_quantity = quantity * 0.5 @@ -2917,7 +2942,8 @@ class PositionManager: # 直接比较剩余仓ä½ç›ˆäºç™¾åˆ†æ¯”与第二目标(基于ä¿è¯é‡‘) if remaining_pnl_pct_margin >= take_profit_2_pct_margin: should_close = True - exit_reason = 'take_profit' + # âš ï¸ 2026-01-27优化:细分状æ€ï¼ŒåŒºåˆ†"第一目标止盈åŽç¬¬äºŒç›®æ ‡æ­¢ç›ˆ" + exit_reason = 'take_profit_partial_then_take_profit' logger.info( f"{symbol} [实时监控] 触å‘第二目标止盈(4.0:1,山寨å¸ç­–略): " f"剩余仓ä½ç›ˆäº={remaining_pnl_pct_margin:.2f}% of margin >= 目标={take_profit_2_pct_margin:.2f}% of margin | "