From 129e9e4e62ad2a50086064db1c2a9cc563b6e8e3 Mon Sep 17 00:00:00 2001 From: aaron <> Date: Wed, 25 Feb 2026 00:10:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=A7=BB=E5=8A=A8=E6=AD=A2?= =?UTF-8?q?=E7=9B=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/services/paper_trading_service.py | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/backend/app/services/paper_trading_service.py b/backend/app/services/paper_trading_service.py index 98a4f73..5d6d671 100644 --- a/backend/app/services/paper_trading_service.py +++ b/backend/app/services/paper_trading_service.py @@ -736,36 +736,50 @@ class PaperTradingService: elif getattr(order, 'trailing_stop_triggered', 0) == 1: # 已触发过移动止损,持续跟随 - # 做空:止损只能下移(降低价格),做多止损只能上移(提高价格) - # 计算新的止损盈利 = 当前总盈利 × 跟随比例 - new_stop_profit = current_pnl_percent * self._get_dynamic_ratio(order, current_price) + # 重要:使用历史最高盈利(max_profit)作为基准,而不是当前盈利 + # 这样可以确保止损只上移不下移(做多)或只下移不上移(做空) + + # 使用历史最高盈利计算新的止损 + base_profit = order.max_profit + new_stop_profit = base_profit * self._get_dynamic_ratio(order, current_price) + + # 最小移动阶梯:只有当盈利增长至少0.5%时才移动止损 + MIN_MOVE_STEP = 0.5 # 0.5% if order.side == OrderSide.LONG: # 做多:新止损价 = 开仓价 × (1 + 新止损盈利%) new_stop_loss = order.filled_price * (1 + new_stop_profit / 100) - # 只有当新止损高于当前止损时才更新 - if new_stop_loss > order.stop_loss: + # 计算当前止损对应的盈利百分比 + current_stop_profit = (order.stop_loss - order.filled_price) / order.filled_price * 100 + + # 只有当新止损带来的盈利增长超过最小阶梯时才更新 + # 并且新止损必须高于当前止损(防止倒退) + if (new_stop_profit - current_stop_profit >= MIN_MOVE_STEP) and (new_stop_loss > order.stop_loss): old_stop = order.stop_loss order.stop_loss = new_stop_loss needs_update = True stop_moved = True stop_move_type = "trailing_update" logger.info(f"移动止损更新: {order.order_id} | {order.symbol} | " - f"盈利 {current_pnl_percent:.2f}% | 锁定 {new_stop_profit:.2f}% | 止损 ${old_stop:,.2f} -> ${new_stop_loss:,.2f}") + f"最高盈利 {base_profit:.2f}% | 锁定 {new_stop_profit:.2f}% | 止损 ${old_stop:,.2f} -> ${new_stop_loss:,.2f}") else: # 做空:新止损价 = 开仓价 × (1 - 新止损盈利%) new_stop_loss = order.filled_price * (1 - new_stop_profit / 100) - # 只有当新止损低于当前止损时才更新 - if new_stop_loss < order.stop_loss: + # 计算当前止损对应的盈利百分比 + current_stop_profit = (order.filled_price - order.stop_loss) / order.filled_price * 100 + + # 只有当新止损带来的盈利增长超过最小阶梯时才更新 + # 并且新止损必须低于当前止损(防止倒退) + if (new_stop_profit - current_stop_profit >= MIN_MOVE_STEP) and (new_stop_loss < order.stop_loss): old_stop = order.stop_loss order.stop_loss = new_stop_loss needs_update = True stop_moved = True stop_move_type = "trailing_update" logger.info(f"移动止损更新: {order.order_id} | {order.symbol} | " - f"盈利 {current_pnl_percent:.2f}% | 锁定 {new_stop_profit:.2f}% | 止损 ${old_stop:,.2f} -> ${new_stop_loss:,.2f}") + f"最高盈利 {base_profit:.2f}% | 锁定 {new_stop_profit:.2f}% | 止损 ${old_stop:,.2f} -> ${new_stop_loss:,.2f}") # === 保本止损逻辑(仅在未触发移动止损时生效) === if self.breakeven_threshold > 0 and current_pnl_percent >= self.breakeven_threshold: