1
This commit is contained in:
parent
b779b7b9ec
commit
0a9377f5ac
|
|
@ -1627,20 +1627,23 @@ class PositionManager:
|
|||
continue
|
||||
|
||||
current_position = position_dict[symbol]
|
||||
entry_price = position_info['entryPrice']
|
||||
quantity = position_info['quantity'] # 修复:获取quantity
|
||||
# 统一转为 float,避免 Decimal 与 float 运算报错(DB/补建可能返回 Decimal)
|
||||
entry_price = float(position_info['entryPrice'])
|
||||
quantity = float(position_info['quantity'])
|
||||
# 获取当前标记价格
|
||||
current_price = current_position.get('markPrice', 0)
|
||||
if current_price == 0:
|
||||
# 如果标记价格为0,尝试从ticker获取
|
||||
ticker = await self.client.get_ticker_24h(symbol)
|
||||
if ticker:
|
||||
current_price = ticker['price']
|
||||
current_price = float(ticker.get('price', 0) or 0)
|
||||
else:
|
||||
current_price = entry_price
|
||||
else:
|
||||
current_price = float(current_price)
|
||||
|
||||
# 计算当前盈亏(基于保证金)
|
||||
leverage = position_info.get('leverage', 10)
|
||||
leverage = float(position_info.get('leverage', 10) or 10)
|
||||
position_value = entry_price * quantity
|
||||
margin = position_value / leverage if leverage > 0 else position_value
|
||||
|
||||
|
|
@ -1660,7 +1663,8 @@ class PositionManager:
|
|||
pnl_percent_price = ((entry_price - current_price) / entry_price) * 100
|
||||
|
||||
# 更新最大盈利(基于保证金)
|
||||
if pnl_percent_margin > position_info.get('maxProfit', 0):
|
||||
max_profit = float(position_info.get('maxProfit', 0) or 0)
|
||||
if pnl_percent_margin > max_profit:
|
||||
position_info['maxProfit'] = pnl_percent_margin
|
||||
|
||||
# 移动止损逻辑(盈利后保护利润,基于保证金)
|
||||
|
|
@ -1716,7 +1720,8 @@ class PositionManager:
|
|||
# 计算新的止损价(基于剩余仓位)
|
||||
if position_info['side'] == 'BUY':
|
||||
new_stop_loss = entry_price + (remaining_pnl - protect_amount) / remaining_quantity
|
||||
if new_stop_loss > position_info['stopLoss']:
|
||||
current_sl = float(position_info['stopLoss']) if position_info.get('stopLoss') is not None else None
|
||||
if current_sl is None or new_stop_loss > current_sl:
|
||||
position_info['stopLoss'] = new_stop_loss
|
||||
logger.info(
|
||||
f"{symbol} 移动止损更新(剩余仓位): {new_stop_loss:.4f} "
|
||||
|
|
@ -1730,7 +1735,8 @@ class PositionManager:
|
|||
new_stop_loss = entry_price + (remaining_pnl - protect_amount) / remaining_quantity
|
||||
# 对于做空,止损价应该越来越高(更宽松),所以检查 new_stop_loss > 当前止损
|
||||
# 同时,移动止损只应该在盈利时激活
|
||||
if new_stop_loss > position_info['stopLoss'] and remaining_pnl > 0:
|
||||
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:
|
||||
position_info['stopLoss'] = new_stop_loss
|
||||
logger.info(
|
||||
f"{symbol} 移动止损更新(剩余仓位): {new_stop_loss:.4f} "
|
||||
|
|
@ -1745,7 +1751,8 @@ class PositionManager:
|
|||
# 保护利润:当前盈亏 - 保护金额 = (止损价 - 开仓价) × 数量
|
||||
# 所以:止损价 = 开仓价 + (当前盈亏 - 保护金额) / 数量
|
||||
new_stop_loss = entry_price + (pnl_amount - protect_amount) / quantity
|
||||
if new_stop_loss > position_info['stopLoss']:
|
||||
current_sl = float(position_info['stopLoss']) if position_info.get('stopLoss') is not None else None
|
||||
if current_sl is None or new_stop_loss > current_sl:
|
||||
position_info['stopLoss'] = new_stop_loss
|
||||
logger.info(
|
||||
f"{symbol} 移动止损更新: {new_stop_loss:.4f} "
|
||||
|
|
@ -1759,7 +1766,8 @@ class PositionManager:
|
|||
new_stop_loss = entry_price + (pnl_amount - protect_amount) / quantity
|
||||
# 对于做空,止损价应该越来越高(更宽松),所以检查 new_stop_loss > 当前止损
|
||||
# 同时,移动止损只应该在盈利时激活,不应该在亏损时把止损往下移
|
||||
if new_stop_loss > position_info['stopLoss'] and pnl_amount > 0:
|
||||
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:
|
||||
position_info['stopLoss'] = new_stop_loss
|
||||
logger.info(
|
||||
f"{symbol} 移动止损更新: {new_stop_loss:.4f} "
|
||||
|
|
@ -1768,7 +1776,8 @@ class PositionManager:
|
|||
|
||||
# 检查止损(使用更新后的止损价,基于保证金收益比)
|
||||
# ⚠️ 重要:止损检查应该在时间锁之前,止损必须立即执行
|
||||
stop_loss = position_info.get('stopLoss')
|
||||
stop_loss_raw = position_info.get('stopLoss')
|
||||
stop_loss = float(stop_loss_raw) if stop_loss_raw is not None else None
|
||||
should_close_due_to_sl = False
|
||||
exit_reason_sl = None
|
||||
|
||||
|
|
@ -1873,10 +1882,12 @@ class PositionManager:
|
|||
# 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')) # 第二目标
|
||||
take_profit_1_raw = position_info.get('takeProfit1') # 第一目标(盈亏比1:1)
|
||||
take_profit_1 = float(take_profit_1_raw) if take_profit_1_raw is not None else None
|
||||
take_profit_2_raw = position_info.get('takeProfit2', position_info.get('takeProfit')) # 第二目标
|
||||
take_profit_2 = float(take_profit_2_raw) if take_profit_2_raw is not None else None
|
||||
partial_profit_taken = position_info.get('partialProfitTaken', False)
|
||||
remaining_quantity = position_info.get('remainingQuantity', quantity)
|
||||
remaining_quantity = float(position_info.get('remainingQuantity', quantity))
|
||||
|
||||
# 第一目标:TAKE_PROFIT_1_PERCENT 止盈(默认15%保证金),了结50%仓位
|
||||
# ✅ 已移除时间锁限制,可以立即执行
|
||||
|
|
@ -2022,12 +2033,13 @@ class PositionManager:
|
|||
# 如果未部分止盈,但达到【第二目标】止盈价对应的收益比时,才全部平仓
|
||||
# ⚠️ 修复:不再使用 TAKE_PROFIT_PERCENT(10%) 作为全平条件,否则会“刚赚一点就整仓止盈”
|
||||
# 改为使用 take_profit_2 价格对应的保证金收益%,与第一目标(20%) 取较大者,避免盈利过少
|
||||
take_profit_2 = position_info.get('takeProfit2', position_info.get('takeProfit'))
|
||||
if take_profit_2 is not None and margin and margin > 0:
|
||||
take_profit_2_full = position_info.get('takeProfit2', position_info.get('takeProfit'))
|
||||
take_profit_2_full = float(take_profit_2_full) if take_profit_2_full is not None else None
|
||||
if take_profit_2_full is not None and margin and margin > 0:
|
||||
if position_info['side'] == 'BUY':
|
||||
take_profit_2_amount = (take_profit_2 - entry_price) * quantity
|
||||
take_profit_2_amount = (take_profit_2_full - entry_price) * quantity
|
||||
else:
|
||||
take_profit_2_amount = (entry_price - take_profit_2) * quantity
|
||||
take_profit_2_amount = (entry_price - take_profit_2_full) * quantity
|
||||
take_profit_2_pct_margin = (take_profit_2_amount / margin * 100) if margin > 0 else 0
|
||||
# 至少要求达到第一目标对应的收益%(如 20%),避免过早全平
|
||||
take_profit_1_pct = (config.TRADING_CONFIG.get('TAKE_PROFIT_1_PERCENT', 0.20) or 0.20)
|
||||
|
|
@ -2039,7 +2051,7 @@ class PositionManager:
|
|||
logger.info(
|
||||
f"{symbol} 触发止盈(第二目标/保证金): "
|
||||
f"当前盈亏={pnl_percent_margin:.2f}% of margin >= 目标={min_pct_for_full_tp:.2f}% | "
|
||||
f"当前价={current_price:.4f}, 第二目标价={take_profit_2:.4f}"
|
||||
f"当前价={current_price:.4f}, 第二目标价={take_profit_2_full:.4f}"
|
||||
)
|
||||
exit_reason = 'take_profit'
|
||||
# 更新数据库
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user