feat(position_manager): Enhance stop-loss logic for short positions and implement automatic SL/TP order synchronization
Updated the stop-loss calculation for short positions to ensure it locks in profits effectively. Added logic to automatically synchronize stop-loss and take-profit orders for positions without existing SL/TP on the exchange. This improves risk management and ensures positions are adequately protected. Enhanced logging for better tracking of stop-loss updates and synchronization events.
This commit is contained in:
parent
5d5ead36ac
commit
4a5406c7e8
99
docs/position_analysis_2026-02-28.md
Normal file
99
docs/position_analysis_2026-02-28.md
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# 持仓分析:持仓记录_2026-02-28T10-43-05.json
|
||||
|
||||
## 一、20% 以上盈利的持仓(共 3 个)
|
||||
|
||||
| 交易对 | 方向 | 盈亏% | 入场价 | 标记价 | 止损 | 止盈 | 交易所 SL/TP |
|
||||
|--------|------|-------|--------|--------|------|------|--------------|
|
||||
| **WIFUSDT** | SELL | **40.3%** | 0.2051 | 0.1863 | **无** | **无** | **无** |
|
||||
| **ZECUSDT** | SELL | **26.3%** | 221.44 | 207.78 | **无** | **无** | **无** |
|
||||
| **BCHUSDT** | SELL | **23.7%** | 470.74 | 444.40 | 479.05 | 436.04 | 有 |
|
||||
|
||||
### 止损问题诊断
|
||||
|
||||
1. **WIF、ZEC:完全没有止损/止盈**
|
||||
- 两笔已浮盈 40%、26%,但交易所无任何 SL/TP 挂单,一旦反转会全部回吐甚至变亏。
|
||||
- 可能原因:非本系统开仓(手动/别处)、或开仓时未成功挂出 SL/TP、或同步/补建时未补挂。
|
||||
- **建议**:尽快在交易所或通过系统对这两笔**至少挂上保本/锁利止损**(例如锁住一半利润或 5%~10% 利润)。
|
||||
|
||||
2. **BCH:有 SL/TP,但止损未上移锁利**
|
||||
- 空头:入场 470.74,当前 444.40,止损仍在 **479.05**(开仓时的初始止损,高于入场价)。
|
||||
- 正确做法:盈利 23.7% 后,**做空的移动止损应下移**(例如从 479 移到 455~460 一带),锁住部分利润;否则价格反弹到 479 才触发,会几乎回吐全部盈利。
|
||||
- 可能原因:
|
||||
- 该持仓不在本系统 `active_positions` 内(例如由同步/补建得到),未参与定时检查的移动止损逻辑;
|
||||
- 或做空方向的移动止损更新条件/方向在代码中有误(见下文「策略执行」)。
|
||||
|
||||
---
|
||||
|
||||
## 二、全部 13 笔持仓汇总
|
||||
|
||||
| 交易对 | 方向 | 盈亏% | 止损 | 止盈 | 交易所有 SL/TP |
|
||||
|--------|------|-------|------|------|----------------|
|
||||
| WIFUSDT | SELL | 40.3 | 无 | 无 | 无 |
|
||||
| ZECUSDT | SELL | 26.3 | 无 | 无 | 无 |
|
||||
| BCHUSDT | SELL | 23.7 | 479.05 | 436.04 | 有 |
|
||||
| VVVUSDT | BUY | 15.1 | 无 | 无 | 无 |
|
||||
| PUMPUSDT | SELL | 7.8 | 0.001813 | 0.001651 | 有 |
|
||||
| ZROUSDT | SELL | 4.7 | 1.5763 | 1.4348 | 有 |
|
||||
| SAHARAUSDT | BUY | 2.5 | 0.01829 | 0.02356 | 有 |
|
||||
| ASTERUSDT | SELL | -0.0 | 0.7152 | 0.651 | 有 |
|
||||
| MYXUSDT | SELL | -0.5 | 无 | 无 | 无 |
|
||||
| FARTCOINUSDT | SELL | -0.8 | 无 | 无 | 无 |
|
||||
| HYPEUSDT | SELL | -3.8 | 无 | 无 | 无 |
|
||||
| VIRTUALUSDT | BUY | -9.5 | 无 | 无 | 无 |
|
||||
| **ICPUSDT** | **BUY** | **-24.5** | **无** | **无** | **无** |
|
||||
|
||||
- **无任何止损/止盈的共 7 笔**:VIRTUAL, ZEC, HYPE, FARTCOIN, VVV, ICP, WIF, MYX。其中 **ICP 已亏 24.5%**,若无止损会继续放大亏损。
|
||||
|
||||
---
|
||||
|
||||
## 三、策略执行问题分析
|
||||
|
||||
### 1. 为何大量持仓「无止损/无止盈」?
|
||||
|
||||
- 若这些仓位是**本系统开仓**:开仓后应调用 `_ensure_exchange_sltp_orders` 在交易所挂 SL/TP;若仍无挂单,可能是:
|
||||
- 开仓流程中未成功挂单(网络/权限/参数错误)且未重试或告警;
|
||||
- 或仓位来自**同步/补建**(币安有仓、DB 无记录),补建时若未同时挂 SL/TP,就会一直处于「无保护」状态。
|
||||
- **建议**:
|
||||
- 对「有持仓但无 SL/TP」的 symbol,在同步/健康检查中**自动补挂**(至少止损,止盈可按配置或保守价);
|
||||
- 开仓后若挂单失败,要有重试与日志/告警,便于排查。
|
||||
|
||||
### 2. 做空(SELL)移动止损方向是否正确?
|
||||
|
||||
- 做空盈利时,应**下移止损价**(从高位往当前价方向移)才能锁利;当前 BCH 空头止损仍在 479,未下移。
|
||||
- 代码中做空分支(`position_manager` 定时检查)有:
|
||||
- `new_stop_loss = entry_price + (pnl_amount - protect_amount) / quantity`
|
||||
- `new_stop_loss = min(new_stop_loss, breakeven)`,再判断 `new_stop_loss > current_sl` 才更新。
|
||||
- 做空时 `pnl_amount = (entry - current)*q > 0`,`entry + (pnl - protect)/q` 可能**大于**初始止损 479,导致条件 `new_stop_loss > current_sl` 不成立,从而从不更新;即便更新,也是把止损往**更上方**移(更宽松),而不是往下锁利。这与「盈利后锁利」的目标相反。
|
||||
- **建议**:复查做空移动止损公式与更新条件,确保「盈利后新止损比当前止损更靠近当前价」(空头即新止损 < 当前止损),并只在「锁利方向」上更新。
|
||||
|
||||
### 3. 亏损单 ICP -24.5% 且无止损
|
||||
|
||||
- 单笔已亏 24.5%,若无止损会继续暴露风险。
|
||||
- **建议**:立即对该仓设止损(或减仓/平仓);并检查为何该仓从未挂上止损(是否补建、是否开仓失败挂单等)。
|
||||
|
||||
### 4. 多账号/多数据源一致性
|
||||
|
||||
- 持仓记录中 `id`、`entry_time`、`created_at` 多为 null,说明可能来自**交易所快照 + 部分本地合并**,而非全部来自本系统 DB。要确保:
|
||||
- 凡在交易所存在的仓位,只要被本系统「认领」或展示,就应纳入监控并在缺失时补挂 SL/TP;
|
||||
- 移动止损/滞涨早止盈等逻辑应对**所有被监控仓位**生效,包括同步/补建进来的。
|
||||
|
||||
---
|
||||
|
||||
## 四、建议汇总
|
||||
|
||||
| 优先级 | 建议 |
|
||||
|--------|------|
|
||||
| **P0** | **WIF、ZEC**:立即在交易所或通过系统挂上止损(至少保本或锁 5%~10% 利润),避免 40%/26% 盈利回吐。 |
|
||||
| **P0** | **ICP**:已亏 24.5% 且无止损,立即设止损或减仓/平仓,并排查为何无 SL。 |
|
||||
| **P1** | **BCH**:检查该仓是否在 `active_positions`、是否参与移动止损;若在,复查做空移动止损公式与更新条件,确保盈利后下移止损锁利。 |
|
||||
| **P1** | 对所有「有仓但无 SL/TP」的持仓(含同步/补建)在同步或健康检查中**自动补挂止损**(止盈可选)。 |
|
||||
| **P2** | 开仓后 SL/TP 挂单失败时增加重试与告警;移动止损(尤其做空)逻辑做代码审查与单测。 |
|
||||
| **P2** | 滞涨早止盈:若已开启,确认对 20%+ 盈利的仓位在「长时间不创新高」时能触发分批减仓+抬止损。 |
|
||||
|
||||
---
|
||||
|
||||
## 五、小结
|
||||
|
||||
- **3 笔 20%+ 盈利**:2 笔(WIF、ZEC)**完全没有止损**,1 笔(BCH)有止损但**未随盈利下移锁利**,整体「止损不对」的观感成立。
|
||||
- **7 笔无任何 SL/TP**,其中 1 笔已亏 24.5%(ICP),风险突出。
|
||||
- 策略执行上需:**补挂缺失 SL/TP**、**修正做空移动止损方向与条件**、**保证同步/补建仓位也纳入监控并补挂保护单**。
|
||||
127
docs/trade_analysis_2026-02-28.md
Normal file
127
docs/trade_analysis_2026-02-28.md
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
# 交易复盘分析:binance_trades_2_2026-02-28(近一日)
|
||||
|
||||
## 一、整体表现
|
||||
|
||||
| 指标 | 数值 |
|
||||
|------|------|
|
||||
| 总成交笔数 | 83(开仓相关 47 + 平仓相关 36) |
|
||||
| 盈利次数 / 亏损次数 | 7 / 29 |
|
||||
| **胜率** | **19.4%** |
|
||||
| 总已实现盈亏 | -2.10 USDT |
|
||||
| 总手续费 | 0.60 USDT |
|
||||
| **净盈亏** | **-2.70 USDT** |
|
||||
| 总成交额(quote) | 1810.26 USDT |
|
||||
| 手续费率 | ≈0.033% |
|
||||
|
||||
**结论**:胜率明显偏低,亏损单数量约为盈利单的 4 倍,单笔平均亏损虽被止损控制,但累积亏损 + 手续费导致净损。需要从**入场质量、止损止盈平衡、同一交易对重复交易、时段/币种过滤**等多环节优化。
|
||||
|
||||
---
|
||||
|
||||
## 二、按交易对表现
|
||||
|
||||
### 亏损集中(建议重点关注或加入黑名单/降权)
|
||||
|
||||
| 交易对 | 盈亏(USDT) | 胜/负 | 说明 |
|
||||
|--------|------------|-------|------|
|
||||
| PENGUUSDT | -1.75 | 0/2 | 连续 2 笔亏损 |
|
||||
| AAVEUSDT | -1.73 | 0/1 | 单笔大亏 |
|
||||
| HYPEUSDT | -1.43 | 0/1 | 单笔大亏 |
|
||||
| WIFUSDT | -1.34 | 0/3 | **同一天 3 笔亏损**,重复交易严重 |
|
||||
| ENAUSDT | -1.11 | 0/1 | 单笔大亏 |
|
||||
| PUMPUSDT | -1.10 | 0/3 | **同一天 3 笔亏损** |
|
||||
| SIRENUSDT | -0.71 | 0/3 | **同一天 3 笔亏损** |
|
||||
| RIVERUSDT | -0.66 | 0/2 | 连续 2 笔亏损 |
|
||||
| WLDUSDT | -0.51 | 0/3 | **同一天 3 笔亏损** |
|
||||
|
||||
### 盈利交易对(可作白名单或维持当前逻辑)
|
||||
|
||||
| 交易对 | 盈亏(USDT) | 胜/负 |
|
||||
|--------|------------|-------|
|
||||
| ARUSDT | +3.47 | 1/0 |
|
||||
| ZECUSDT | +2.19 | 1/0 |
|
||||
| TAOUSDT | +1.13 | 2/3(有盈有亏,整体小正) |
|
||||
| VVVUSDT | +1.83 | 1/0 |
|
||||
| 1000LUNCUSDT | +1.41 | 2/0 |
|
||||
|
||||
**问题**:WIF、PUMP、SIREN、WLD 等同一天内多次亏损,说明要么**冷却时间不足**,要么**同一交易对当日开仓次数**未做上限,导致在弱势品种上反复试错。
|
||||
|
||||
---
|
||||
|
||||
## 三、按时段表现
|
||||
|
||||
- **亏损集中时段**:0 时(-1.43)、1 时(-1.64)、7 时(-0.42)、8 时(-1.02)、17 时(-0.97)、19 时(-1.74)、20 时(-1.34)、21 时(-1.75)。
|
||||
- **盈利集中时段**:5 时(+1.41)、6 时(+3.41)、10 时(+0.73)、12 时(+0.85)、22 时(+2.19)。
|
||||
- **按星期**:周五 48 笔、-2.42 USDT;周六 35 笔、+0.31 USDT。
|
||||
|
||||
**结论**:凌晨 0–1 时、早 7–8 时、晚 17–21 时表现较差,可与「按小时统计过滤/黑名单」结合,在这些时段对部分品种降权或减少开仓。
|
||||
|
||||
---
|
||||
|
||||
## 四、策略环节诊断与优化建议
|
||||
|
||||
### 1. 入场与信号质量
|
||||
|
||||
- **现象**:胜率 19.4%,多数单子被止损打掉,说明**假突破或逆势入场**较多。
|
||||
- **建议**:
|
||||
- 将 **MIN_SIGNAL_STRENGTH** 从 7 提高到 **8**,减少弱信号开仓。
|
||||
- 确认 **LOW_VOLATILITY_MIN_SIGNAL_STRENGTH**(当前 9)在低波动期已生效。
|
||||
- 对近期统计中**连续亏损或胜率极低的交易对**使用黑名单(硬/软)或降权,避免在 PENGU、WIF、PUMP、SIREN、WLD 等上重复开仓。
|
||||
|
||||
### 2. 同一交易对重复交易与冷却
|
||||
|
||||
- **现象**:WIF、PUMP、SIREN、WLD 同一天内 3 笔亏损,说明冷却或「同一 symbol 当日次数」未充分限制。
|
||||
- **建议**:
|
||||
- **SYMBOL_LOSS_COOLDOWN_SEC** 从 3600 提高到 **7200(2 小时)** 或更长,观察同一 symbol 亏损后是否仍频繁再开。
|
||||
- 增加「**同一交易对每日最大开仓次数**」(如 2 次),超过则当日不再开该 symbol。
|
||||
- 若已有基于 `trade_stats` 的黑名单/降权,确保这些近期大亏或连亏的 symbol 被纳入并生效。
|
||||
|
||||
### 3. 止损与止盈平衡
|
||||
|
||||
- **现象**:亏损单多、盈利单少,但单笔亏损被止损控制在约 -0.2~-1.7 USDT,说明止损在执行;盈利单如 AR、ZEC、TAO、VVV 能拿住一部分利润。
|
||||
- **建议**:
|
||||
- 当前 **STOP_LOSS_PERCENT** 5%、**TAKE_PROFIT_1_PERCENT** 12%、**TAKE_PROFIT_PERCENT** 25%:若多数单在未到第一目标就被止损,可考虑:
|
||||
- **略放宽止损**(如 ATR 倍数从 2.0 调到 2.2)或 **MIN_STOP_LOSS_PRICE_PCT** 略增,减少「刚入场就被震荡扫损」;
|
||||
- 或**提高入场门槛**(提高 MIN_SIGNAL_STRENGTH),从源头减少劣质单,而不是一味放宽止损。
|
||||
- **滞涨早止盈**(STAGNATION_EARLY_EXIT):若已开启,可观察是否在「曾涨到约 10% 后长时间不创新高」时锁利,减少由盈转亏。
|
||||
|
||||
### 4. 手续费与频率
|
||||
|
||||
- **现象**:83 笔、手续费 0.60 USDT、费率约 0.033%,单笔平均约 0.007 USDT,占比不高,但**交易频率偏高**会放大亏损和手续费。
|
||||
- **建议**:
|
||||
- 在提高信号门槛、冷却和 symbol 限制后,**自然降低开仓频率**,优先质量而非数量。
|
||||
- 若使用市价单较多,可评估在能接受延迟的前提下部分改用限价单以降低 taker 费率。
|
||||
|
||||
### 5. 时段与品种过滤(统计过滤)
|
||||
|
||||
- **现象**:0–1 时、7–8 时、17–21 时亏损集中;PENGU、WIF、PUMP、SIREN、WLD、AAVE、HYPE、ENA 等明显偏弱。
|
||||
- **建议**:
|
||||
- 使用现有 **trade_stats 按 symbol / 按小时** 的统计:对**亏损集中时段**做降权或禁止开仓,对**近期连亏/大亏的 symbol** 加入黑名单或软黑名单(降权)。
|
||||
- 白名单可考虑优先 AR、ZEC、TAO、VVV、1000LUNC 等近期有盈利记录的品种(需结合更长周期再确认)。
|
||||
|
||||
### 6. 风控与仓位
|
||||
|
||||
- **现象**:单笔亏损多在 -0.2~-1.7 USDT,未出现单笔爆仓式亏损,说明**单笔风险**受控。
|
||||
- **建议**:
|
||||
- 保持 **MAX_OPEN_POSITIONS**、**FIXED_RISK_PERCENT** 等不变,重点放在**减少开仓次数、提高单笔质量**上,而非加大仓位。
|
||||
|
||||
---
|
||||
|
||||
## 五、优化项汇总(按优先级)
|
||||
|
||||
| 优先级 | 优化项 | 说明 |
|
||||
|--------|--------|------|
|
||||
| P0 | 提高 MIN_SIGNAL_STRENGTH 到 8 | 减少弱信号开仓,提升胜率 |
|
||||
| P0 | 延长 SYMBOL_LOSS_COOLDOWN_SEC 到 7200 | 降低同一 symbol 连续亏损次数 |
|
||||
| P1 | 同一交易对每日最大开仓次数上限 | 避免 WIF/PUMP/SIREN/WLD 类重复试错 |
|
||||
| P1 | 基于统计的黑名单/时段降权 | 对近期连亏 symbol、亏损集中时段过滤或降权 |
|
||||
| P2 | 评估略放宽止损(ATR 或 MIN_STOP) | 在提高入场质量前提下,减少震荡扫损 |
|
||||
| P2 | 滞涨早止盈观察与调参 | 确认 STAGNATION_* 是否在「涨后横盘」时锁利 |
|
||||
| P3 | 盈利品种白名单/优先 | 结合更长周期后,对稳定盈利的 symbol 做优先或白名单 |
|
||||
|
||||
---
|
||||
|
||||
## 六、结论
|
||||
|
||||
- **主要问题**:胜率低(19.4%)、同一交易对同一天多次亏损、部分时段和品种持续贡献亏损。
|
||||
- **策略环节**:入场信号偏松、同一 symbol 冷却与次数限制不足、缺少基于近期统计的 symbol/时段过滤,是当前最值得改动的环节;止损执行正常,可先通过「提高质量、减少次数」再考虑是否微调止损/止盈。
|
||||
- **建议执行顺序**:先做 P0(信号门槛 + 冷却),观察 1~2 天;再上 P1(每日同 symbol 上限 + 统计黑名单/时段),最后按需微调止损与滞涨早止盈(P2/P3)。
|
||||
|
|
@ -2254,13 +2254,15 @@ class PositionManager:
|
|||
exc_info=False,
|
||||
)
|
||||
else:
|
||||
new_stop_loss = entry_price + (remaining_pnl - protect_amount) / remaining_quantity
|
||||
new_stop_loss = min(new_stop_loss, self._breakeven_stop_price(entry_price, 'SELL'))
|
||||
# 做空锁利:止损下移,锁住 protect_amount 利润。(entry - stop)*q = protect → stop = entry - protect/q
|
||||
new_stop_loss = entry_price - protect_amount / remaining_quantity
|
||||
new_stop_loss = max(new_stop_loss, self._breakeven_stop_price(entry_price, 'SELL'))
|
||||
current_sl = float(position_info['stopLoss']) if position_info.get('stopLoss') is not None else None
|
||||
if current_sl is not None and new_stop_loss > current_sl and remaining_pnl > 0:
|
||||
# 仅当新止损低于当前止损(下移锁利)且高于市价(锁住的是利润)时更新
|
||||
if (current_sl is None or new_stop_loss < current_sl) and new_stop_loss > current_price and remaining_pnl > 0:
|
||||
position_info['stopLoss'] = new_stop_loss
|
||||
logger.info(
|
||||
f"{symbol} 移动止损更新(剩余仓位): {new_stop_loss:.4f} "
|
||||
f"{symbol} 移动止损更新(剩余仓位-做空锁利): {new_stop_loss:.4f} "
|
||||
f"(保护{trailing_protect*100:.1f}% of remaining margin = {protect_amount:.4f} USDT, "
|
||||
f"剩余数量: {remaining_quantity:.4f})"
|
||||
)
|
||||
|
|
@ -2300,17 +2302,15 @@ class PositionManager:
|
|||
exc_info=False,
|
||||
)
|
||||
else:
|
||||
# 做空:止损价 = 开仓价 + (当前盈亏 - 保护金额) / 数量
|
||||
# 注意:对于做空,止损价应该高于开仓价,所以用加法
|
||||
# 当盈利时(pnl_amount > 0),止损价应该往上移(更宽松)
|
||||
# 当亏损时(pnl_amount < 0),不应该移动止损(保持初始止损)
|
||||
new_stop_loss = entry_price + (pnl_amount - protect_amount) / quantity
|
||||
new_stop_loss = min(new_stop_loss, self._breakeven_stop_price(entry_price, 'SELL'))
|
||||
# 做空锁利:止损下移(从初始高位往市价方向移),锁住 protect_amount。(entry - stop)*q = protect → stop = entry - protect/q
|
||||
new_stop_loss = entry_price - protect_amount / quantity
|
||||
new_stop_loss = max(new_stop_loss, self._breakeven_stop_price(entry_price, 'SELL'))
|
||||
current_sl = float(position_info['stopLoss']) if position_info.get('stopLoss') is not None else None
|
||||
if current_sl is not None and new_stop_loss > current_sl and pnl_amount > 0:
|
||||
# 仅当新止损低于当前止损(下移锁利)且高于市价(锁住的是利润)时更新
|
||||
if (current_sl is None or new_stop_loss < current_sl) and new_stop_loss > current_price and pnl_amount > 0:
|
||||
position_info['stopLoss'] = new_stop_loss
|
||||
logger.info(
|
||||
f"{symbol} 移动止损更新: {new_stop_loss:.4f} "
|
||||
f"{symbol} 移动止损更新(做空锁利): {new_stop_loss:.4f} "
|
||||
f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)"
|
||||
)
|
||||
_log_trailing_stop_event(self.account_id, symbol, "trailing_update", new_stop_loss=new_stop_loss, source="定时检查")
|
||||
|
|
@ -2820,6 +2820,24 @@ class PositionManager:
|
|||
except Exception as e:
|
||||
logger.debug(f"{symbol} 载入 active_positions 失败: {e}")
|
||||
|
||||
# 2.6 对「有仓但交易所无 SL/TP」的持仓自动补挂止损止盈(含仅在本系统 active 的仓)
|
||||
for symbol in list(self.active_positions.keys()):
|
||||
if symbol not in binance_symbols:
|
||||
continue
|
||||
position_info = self.active_positions[symbol]
|
||||
if not position_info.get('stopLoss') and not position_info.get('takeProfit'):
|
||||
continue
|
||||
try:
|
||||
sl_from_ex, tp_from_ex = await self._get_sltp_from_exchange(symbol, position_info['side'])
|
||||
if sl_from_ex is not None and tp_from_ex is not None:
|
||||
continue
|
||||
ticker = await self.client.get_ticker_24h(symbol)
|
||||
current_price = float(ticker.get('price', 0) or position_info.get('entryPrice', 0))
|
||||
await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price)
|
||||
logger.info(f"[账号{self.account_id}] {symbol} [同步] 检测到交易所无止损/止盈,已补挂 SL/TP")
|
||||
except Exception as e:
|
||||
logger.warning(f"[账号{self.account_id}] {symbol} [同步] 补挂 SL/TP 失败: {e}", exc_info=False)
|
||||
|
||||
# 3. 找出在数据库中open但在币安已不存在的持仓
|
||||
missing_in_binance = db_open_symbols - binance_symbols
|
||||
|
||||
|
|
@ -4412,10 +4430,10 @@ class PositionManager:
|
|||
new_stop_loss = entry_price + (pnl_amount - protect_amount) / quantity
|
||||
breakeven = self._breakeven_stop_price(entry_price, 'BUY')
|
||||
new_stop_loss = max(new_stop_loss, breakeven)
|
||||
else: # SELL
|
||||
new_stop_loss = entry_price + (pnl_amount - protect_amount) / quantity
|
||||
else: # SELL 做空锁利:止损下移,锁住 protect_amount。(entry - stop)*q = protect → stop = entry - protect/q
|
||||
new_stop_loss = entry_price - protect_amount / quantity
|
||||
breakeven = self._breakeven_stop_price(entry_price, 'SELL')
|
||||
new_stop_loss = min(new_stop_loss, breakeven)
|
||||
new_stop_loss = max(new_stop_loss, breakeven)
|
||||
|
||||
position_info['stopLoss'] = new_stop_loss
|
||||
logger.info(
|
||||
|
|
@ -4448,7 +4466,8 @@ class PositionManager:
|
|||
if position_info['side'] == 'BUY':
|
||||
new_stop_loss = entry_price + (pnl_amount - protect_amount) / quantity
|
||||
new_stop_loss = max(new_stop_loss, self._breakeven_stop_price(entry_price, 'BUY'))
|
||||
if new_stop_loss > position_info['stopLoss']:
|
||||
current_sl_buy = position_info.get('stopLoss')
|
||||
if current_sl_buy is None or new_stop_loss > current_sl_buy:
|
||||
position_info['stopLoss'] = new_stop_loss
|
||||
logger.info(
|
||||
f"[账号{self.account_id}] {symbol} [实时监控] 移动止损更新: {new_stop_loss:.4f} "
|
||||
|
|
@ -4465,13 +4484,15 @@ class PositionManager:
|
|||
f"[账号{self.account_id}] {symbol} [实时监控] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}",
|
||||
exc_info=False,
|
||||
)
|
||||
else: # SELL
|
||||
new_stop_loss = entry_price + (pnl_amount - protect_amount) / quantity
|
||||
new_stop_loss = min(new_stop_loss, self._breakeven_stop_price(entry_price, 'SELL'))
|
||||
if new_stop_loss > position_info['stopLoss'] and pnl_amount > 0:
|
||||
else: # SELL 做空锁利:止损下移,锁住 protect_amount。(entry - stop)*q = protect → stop = entry - protect/q
|
||||
new_stop_loss = entry_price - protect_amount / quantity
|
||||
new_stop_loss = max(new_stop_loss, self._breakeven_stop_price(entry_price, 'SELL'))
|
||||
current_sl = position_info.get('stopLoss')
|
||||
# 仅当新止损低于当前止损(下移锁利)且高于市价时更新
|
||||
if (current_sl is None or new_stop_loss < current_sl) and new_stop_loss > current_price_float and pnl_amount > 0:
|
||||
position_info['stopLoss'] = new_stop_loss
|
||||
logger.info(
|
||||
f"[账号{self.account_id}] {symbol} [实时监控] 移动止损更新: {new_stop_loss:.4f} "
|
||||
f"[账号{self.account_id}] {symbol} [实时监控] 移动止损更新(做空锁利): {new_stop_loss:.4f} "
|
||||
f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)"
|
||||
)
|
||||
_log_trailing_stop_event(self.account_id, symbol, "trailing_update", new_stop_loss=new_stop_loss, source="实时监控")
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user