diff --git a/trading_system/position_manager.py b/trading_system/position_manager.py index 3d9d0c3..37f0715 100644 --- a/trading_system/position_manager.py +++ b/trading_system/position_manager.py @@ -2574,88 +2574,88 @@ class PositionManager: # 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) - remaining_quantity = position_info.get('remainingQuantity', quantity) + 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) + 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': + take_profit_1_amount = (take_profit_1 - entry_price) * quantity + else: # SELL + take_profit_1_amount = (entry_price - take_profit_1) * quantity + take_profit_1_pct_margin = (take_profit_1_amount / margin * 100) if margin > 0 else 0 - # 第一目标:盈亏比1:1,了结50%仓位 - if not partial_profit_taken and take_profit_1 is not None: - # 计算第一目标对应的保证金百分比 - if position_info['side'] == 'BUY': - take_profit_1_amount = (take_profit_1 - entry_price) * quantity - else: # SELL - take_profit_1_amount = (entry_price - take_profit_1) * quantity - take_profit_1_pct_margin = (take_profit_1_amount / margin * 100) if margin > 0 else 0 - - # 直接比较当前盈亏百分比与第一目标(基于保证金) - if pnl_percent_margin >= take_profit_1_pct_margin: - logger.info( - f"{symbol} [实时监控] 触发第一目标止盈(盈亏比1:1,基于保证金): " - f"当前盈亏={pnl_percent_margin:.2f}% of margin >= 目标={take_profit_1_pct_margin:.2f}% of margin | " - f"当前价={current_price_float:.4f}, 目标价={take_profit_1:.4f}" - ) - # 部分平仓50% - partial_quantity = quantity * 0.5 - try: - close_side = 'SELL' if position_info['side'] == 'BUY' else 'BUY' - close_position_side = 'LONG' if position_info['side'] == 'BUY' else 'SHORT' - live_amt = await self._get_live_position_amt(symbol, position_side=close_position_side) - if live_amt is None or abs(live_amt) <= 0: - logger.warning(f"{symbol} [实时监控] 部分止盈:实时持仓已为0,跳过部分平仓") - else: - partial_quantity = min(partial_quantity, abs(live_amt)) - partial_quantity = await self._adjust_close_quantity(symbol, partial_quantity) - if partial_quantity > 0: - partial_order = await self.client.place_order( - symbol=symbol, - side=close_side, - quantity=partial_quantity, - order_type='MARKET', - reduce_only=True, - position_side=close_position_side, + # 直接比较当前盈亏百分比与第一目标(基于保证金) + if pnl_percent_margin >= take_profit_1_pct_margin: + logger.info( + f"{symbol} [实时监控] 触发第一目标止盈(盈亏比1:1,基于保证金): " + f"当前盈亏={pnl_percent_margin:.2f}% of margin >= 目标={take_profit_1_pct_margin:.2f}% of margin | " + f"当前价={current_price_float:.4f}, 目标价={take_profit_1:.4f}" + ) + # 部分平仓50% + partial_quantity = quantity * 0.5 + try: + close_side = 'SELL' if position_info['side'] == 'BUY' else 'BUY' + close_position_side = 'LONG' if position_info['side'] == 'BUY' else 'SHORT' + live_amt = await self._get_live_position_amt(symbol, position_side=close_position_side) + if live_amt is None or abs(live_amt) <= 0: + logger.warning(f"{symbol} [实时监控] 部分止盈:实时持仓已为0,跳过部分平仓") + else: + partial_quantity = min(partial_quantity, abs(live_amt)) + partial_quantity = await self._adjust_close_quantity(symbol, partial_quantity) + if partial_quantity > 0: + partial_order = await self.client.place_order( + symbol=symbol, + side=close_side, + quantity=partial_quantity, + order_type='MARKET', + reduce_only=True, + position_side=close_position_side, + ) + if partial_order: + position_info['partialProfitTaken'] = True + position_info['remainingQuantity'] = remaining_quantity - partial_quantity + logger.info( + f"{symbol} [实时监控] 部分止盈成功: 平仓{partial_quantity:.4f},剩余{position_info['remainingQuantity']:.4f}" ) - if partial_order: - position_info['partialProfitTaken'] = True - position_info['remainingQuantity'] = remaining_quantity - partial_quantity - logger.info( - f"{symbol} [实时监控] 部分止盈成功: 平仓{partial_quantity:.4f},剩余{position_info['remainingQuantity']:.4f}" - ) - # 分步止盈后的"保本"处理:将剩余仓位止损移至成本价(保本) - position_info['stopLoss'] = entry_price - logger.info( - f"{symbol} [实时监控] 部分止盈后:剩余仓位止损移至成本价 {entry_price:.4f}(保本)," - f"剩余50%仓位追求1.5:1止盈目标" - ) - except Exception as e: - logger.error(f"{symbol} [实时监控] 部分止盈失败: {e}") + # 分步止盈后的"保本"处理:将剩余仓位止损移至成本价(保本) + position_info['stopLoss'] = entry_price + logger.info( + f"{symbol} [实时监控] 部分止盈后:剩余仓位止损移至成本价 {entry_price:.4f}(保本)," + f"剩余50%仓位追求1.5:1止盈目标" + ) + except Exception as e: + logger.error(f"{symbol} [实时监控] 部分止盈失败: {e}") + + # 第二目标:1.5:1止盈,平掉剩余仓位 + if partial_profit_taken and take_profit_2 is not None and not should_close: + # 计算第二目标对应的保证金百分比(基于剩余仓位) + if position_info['side'] == 'BUY': + take_profit_2_amount = (take_profit_2 - entry_price) * remaining_quantity + else: # SELL + take_profit_2_amount = (entry_price - take_profit_2) * remaining_quantity + remaining_margin = (entry_price * remaining_quantity) / leverage if leverage > 0 else (entry_price * remaining_quantity) + take_profit_2_pct_margin = (take_profit_2_amount / remaining_margin * 100) if remaining_margin > 0 else 0 + # 计算剩余仓位的当前盈亏 + if position_info['side'] == 'BUY': + remaining_pnl_amount = (current_price_float - entry_price) * remaining_quantity + else: + remaining_pnl_amount = (entry_price - current_price_float) * remaining_quantity + remaining_pnl_pct_margin = (remaining_pnl_amount / remaining_margin * 100) if remaining_margin > 0 else 0 - # 第二目标:1.5:1止盈,平掉剩余仓位 - if partial_profit_taken and take_profit_2 is not None and not should_close: - # 计算第二目标对应的保证金百分比(基于剩余仓位) - if position_info['side'] == 'BUY': - take_profit_2_amount = (take_profit_2 - entry_price) * remaining_quantity - else: # SELL - take_profit_2_amount = (entry_price - take_profit_2) * remaining_quantity - remaining_margin = (entry_price * remaining_quantity) / leverage if leverage > 0 else (entry_price * remaining_quantity) - take_profit_2_pct_margin = (take_profit_2_amount / remaining_margin * 100) if remaining_margin > 0 else 0 - # 计算剩余仓位的当前盈亏 - if position_info['side'] == 'BUY': - remaining_pnl_amount = (current_price_float - entry_price) * remaining_quantity - else: - remaining_pnl_amount = (entry_price - current_price_float) * remaining_quantity - remaining_pnl_pct_margin = (remaining_pnl_amount / remaining_margin * 100) if remaining_margin > 0 else 0 - - # 直接比较剩余仓位盈亏百分比与第二目标(基于保证金) - if remaining_pnl_pct_margin >= take_profit_2_pct_margin: - should_close = True - exit_reason = 'take_profit' - logger.info( - f"{symbol} [实时监控] 触发第二目标止盈(1.5:1,基于保证金): " - f"剩余仓位盈亏={remaining_pnl_pct_margin:.2f}% of margin >= 目标={take_profit_2_pct_margin:.2f}% of margin | " - f"当前价={current_price_float:.4f}, 目标价={take_profit_2:.4f}, " - f"剩余数量={remaining_quantity:.4f}" - ) + # 直接比较剩余仓位盈亏百分比与第二目标(基于保证金) + if remaining_pnl_pct_margin >= take_profit_2_pct_margin: + should_close = True + exit_reason = 'take_profit' + logger.info( + f"{symbol} [实时监控] 触发第二目标止盈(1.5:1,基于保证金): " + f"剩余仓位盈亏={remaining_pnl_pct_margin:.2f}% of margin >= 目标={take_profit_2_pct_margin:.2f}% of margin | " + f"当前价={current_price_float:.4f}, 目标价={take_profit_2:.4f}, " + f"剩余数量={remaining_quantity:.4f}" + ) # 检查止盈(基于保证金收益比)- 用于未启用分步止盈的情况 if not should_close: