a
This commit is contained in:
parent
4d084d7166
commit
b45f6121b1
|
|
@ -168,8 +168,10 @@ def _get_trading_config():
|
|||
'MIN_CHANGE_PERCENT': 0.5, # 降低到0.5%以获取更多推荐(推荐系统可以更宽松)
|
||||
'TOP_N_SYMBOLS': 50, # 每次扫描后处理的交易对数量(增加到50以获取更多推荐)
|
||||
'MAX_SCAN_SYMBOLS': 500, # 扫描的最大交易对数量(0表示扫描所有)
|
||||
'STOP_LOSS_PERCENT': 0.03,
|
||||
'TAKE_PROFIT_PERCENT': 0.05,
|
||||
'STOP_LOSS_PERCENT': 0.03, # 止损百分比(相对于保证金),默认3%
|
||||
'TAKE_PROFIT_PERCENT': 0.05, # 止盈百分比(相对于保证金),默认5%
|
||||
'MIN_STOP_LOSS_PRICE_PCT': 0.01, # 最小止损价格变动百分比(如0.01表示1%),防止止损过紧,默认1%
|
||||
'MIN_TAKE_PROFIT_PRICE_PCT': 0.015, # 最小止盈价格变动百分比(如0.015表示1.5%),防止止盈过紧,默认1.5%
|
||||
'SCAN_INTERVAL': 3600,
|
||||
'KLINE_INTERVAL': '1h',
|
||||
'PRIMARY_INTERVAL': '1h',
|
||||
|
|
|
|||
|
|
@ -668,57 +668,45 @@ class PositionManager:
|
|||
stop_loss = position_info.get('stopLoss')
|
||||
if stop_loss is None:
|
||||
logger.warning(f"{symbol} 止损价未设置,跳过止损检查")
|
||||
elif position_info['side'] == 'BUY' and current_price <= stop_loss:
|
||||
logger.warning(
|
||||
f"{symbol} 触发止损: {current_price:.4f} <= {stop_loss:.4f} "
|
||||
f"(盈亏: {pnl_percent:.2f}%)"
|
||||
)
|
||||
# 确定平仓原因
|
||||
exit_reason = 'trailing_stop' if position_info.get('trailingStopActivated') else 'stop_loss'
|
||||
# 更新数据库
|
||||
if DB_AVAILABLE:
|
||||
trade_id = position_info.get('tradeId')
|
||||
if trade_id:
|
||||
try:
|
||||
Trade.update_exit(
|
||||
trade_id=trade_id,
|
||||
exit_price=current_price,
|
||||
exit_reason=exit_reason,
|
||||
pnl=pnl_percent * entry_price * quantity / 100,
|
||||
pnl_percent=pnl_percent
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"更新止损记录失败: {e}")
|
||||
if await self.close_position(symbol, reason=exit_reason):
|
||||
closed_positions.append(symbol)
|
||||
continue
|
||||
# 检查止损(基于保证金收益比)
|
||||
stop_loss = position_info.get('stopLoss')
|
||||
if stop_loss is not None:
|
||||
# 计算止损对应的保证金百分比目标
|
||||
if position_info['side'] == 'BUY':
|
||||
stop_loss_amount = (entry_price - stop_loss) * quantity
|
||||
else: # SELL
|
||||
stop_loss_amount = (stop_loss - entry_price) * quantity
|
||||
|
||||
stop_loss_pct_margin = (stop_loss_amount / margin * 100) if margin > 0 else 0
|
||||
|
||||
# 直接比较当前盈亏百分比与止损目标(基于保证金)
|
||||
if pnl_percent_margin <= -stop_loss_pct_margin:
|
||||
logger.warning(
|
||||
f"{symbol} 触发止损(基于保证金): "
|
||||
f"当前盈亏={pnl_percent_margin:.2f}% of margin <= 止损目标=-{stop_loss_pct_margin:.2f}% of margin | "
|
||||
f"当前价={current_price:.4f}, 止损价={stop_loss:.4f}"
|
||||
)
|
||||
# 确定平仓原因
|
||||
exit_reason = 'trailing_stop' if position_info.get('trailingStopActivated') else 'stop_loss'
|
||||
# 更新数据库
|
||||
if DB_AVAILABLE:
|
||||
trade_id = position_info.get('tradeId')
|
||||
if trade_id:
|
||||
try:
|
||||
Trade.update_exit(
|
||||
trade_id=trade_id,
|
||||
exit_price=current_price,
|
||||
exit_reason=exit_reason,
|
||||
pnl=pnl_amount,
|
||||
pnl_percent=pnl_percent_margin
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"更新止损记录失败: {e}")
|
||||
if await self.close_position(symbol, reason=exit_reason):
|
||||
closed_positions.append(symbol)
|
||||
continue
|
||||
|
||||
if stop_loss is not None and position_info['side'] == 'SELL' and current_price >= stop_loss:
|
||||
logger.warning(
|
||||
f"{symbol} 触发止损: {current_price:.4f} >= {stop_loss:.4f} "
|
||||
f"(盈亏: {pnl_percent:.2f}%)"
|
||||
)
|
||||
# 确定平仓原因
|
||||
exit_reason = 'trailing_stop' if position_info.get('trailingStopActivated') else 'stop_loss'
|
||||
# 更新数据库
|
||||
if DB_AVAILABLE:
|
||||
trade_id = position_info.get('tradeId')
|
||||
if trade_id:
|
||||
try:
|
||||
Trade.update_exit(
|
||||
trade_id=trade_id,
|
||||
exit_price=current_price,
|
||||
exit_reason=exit_reason,
|
||||
pnl=pnl_percent * entry_price * quantity / 100,
|
||||
pnl_percent=pnl_percent
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"更新止损记录失败: {e}")
|
||||
if await self.close_position(symbol, reason=exit_reason):
|
||||
closed_positions.append(symbol)
|
||||
continue
|
||||
|
||||
# 检查分步止盈
|
||||
# 检查分步止盈(基于保证金收益比)
|
||||
take_profit_1 = position_info.get('takeProfit1') # 第一目标(盈亏比1:1)
|
||||
take_profit_2 = position_info.get('takeProfit2', position_info.get('takeProfit')) # 第二目标
|
||||
partial_profit_taken = position_info.get('partialProfitTaken', False)
|
||||
|
|
@ -726,10 +714,19 @@ class PositionManager:
|
|||
|
||||
# 第一目标:盈亏比1:1,了结50%仓位
|
||||
if not partial_profit_taken and take_profit_1 is not None:
|
||||
if position_info['side'] == 'BUY' and current_price >= take_profit_1:
|
||||
# 计算第一目标对应的保证金百分比
|
||||
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): {current_price:.4f} >= {take_profit_1:.4f} "
|
||||
f"(盈亏: {pnl_percent:.2f}%)"
|
||||
f"{symbol} 触发第一目标止盈(盈亏比1:1,基于保证金): "
|
||||
f"当前盈亏={pnl_percent_margin:.2f}% of margin >= 目标={take_profit_1_pct_margin:.2f}% of margin | "
|
||||
f"当前价={current_price:.4f}, 目标价={take_profit_1:.4f}"
|
||||
)
|
||||
# 部分平仓50%
|
||||
partial_quantity = quantity * 0.5
|
||||
|
|
@ -754,11 +751,7 @@ class PositionManager:
|
|||
logger.info(f"{symbol} 剩余仓位止损移至成本价,配合移动止损博取更大利润")
|
||||
except Exception as e:
|
||||
logger.error(f"{symbol} 部分止盈失败: {e}")
|
||||
elif take_profit_1 is not None and position_info['side'] == 'SELL' and current_price <= take_profit_1:
|
||||
logger.info(
|
||||
f"{symbol} 触发第一目标止盈(盈亏比1:1): {current_price:.4f} <= {take_profit_1:.4f} "
|
||||
f"(盈亏: {pnl_percent:.2f}%)"
|
||||
)
|
||||
# 做空方向已经在上面统一处理了(基于保证金收益比)
|
||||
# 部分平仓50%
|
||||
partial_quantity = quantity * 0.5
|
||||
try:
|
||||
|
|
@ -782,12 +775,29 @@ class PositionManager:
|
|||
except Exception as e:
|
||||
logger.error(f"{symbol} 部分止盈失败: {e}")
|
||||
|
||||
# 第二目标:原始止盈价,平掉剩余仓位
|
||||
# 第二目标:原始止盈价,平掉剩余仓位(基于保证金收益比)
|
||||
if partial_profit_taken and take_profit_2 is not None:
|
||||
if position_info['side'] == 'BUY' and current_price >= take_profit_2:
|
||||
# 计算第二目标对应的保证金百分比
|
||||
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 - entry_price) * remaining_quantity
|
||||
else:
|
||||
remaining_pnl_amount = (entry_price - current_price) * 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:
|
||||
logger.info(
|
||||
f"{symbol} 触发第二目标止盈: {current_price:.4f} >= {take_profit_2:.4f} "
|
||||
f"(盈亏: {pnl_percent:.2f}%)"
|
||||
f"{symbol} 触发第二目标止盈(基于保证金): "
|
||||
f"剩余仓位盈亏={remaining_pnl_pct_margin:.2f}% of margin >= 目标={take_profit_2_pct_margin:.2f}% of margin | "
|
||||
f"当前价={current_price:.4f}, 目标价={take_profit_2:.4f}"
|
||||
)
|
||||
exit_reason = 'take_profit'
|
||||
# 更新数据库
|
||||
|
|
@ -799,31 +809,8 @@ class PositionManager:
|
|||
trade_id=trade_id,
|
||||
exit_price=current_price,
|
||||
exit_reason=exit_reason,
|
||||
pnl=pnl_percent * entry_price * quantity / 100,
|
||||
pnl_percent=pnl_percent
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"更新止盈记录失败: {e}")
|
||||
if await self.close_position(symbol, reason=exit_reason):
|
||||
closed_positions.append(symbol)
|
||||
continue
|
||||
elif take_profit_2 is not None and position_info['side'] == 'SELL' and current_price <= take_profit_2:
|
||||
logger.info(
|
||||
f"{symbol} 触发第二目标止盈: {current_price:.4f} <= {take_profit_2:.4f} "
|
||||
f"(盈亏: {pnl_percent:.2f}%)"
|
||||
)
|
||||
exit_reason = 'take_profit'
|
||||
# 更新数据库
|
||||
if DB_AVAILABLE:
|
||||
trade_id = position_info.get('tradeId')
|
||||
if trade_id:
|
||||
try:
|
||||
Trade.update_exit(
|
||||
trade_id=trade_id,
|
||||
exit_price=current_price,
|
||||
exit_reason=exit_reason,
|
||||
pnl=pnl_percent * entry_price * quantity / 100,
|
||||
pnl_percent=pnl_percent
|
||||
pnl=pnl_amount,
|
||||
pnl_percent=pnl_percent_margin
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"更新止盈记录失败: {e}")
|
||||
|
|
@ -831,55 +818,41 @@ class PositionManager:
|
|||
closed_positions.append(symbol)
|
||||
continue
|
||||
else:
|
||||
# 如果未部分止盈,但达到第二目标,直接全部平仓
|
||||
# 如果未部分止盈,但达到止盈目标,直接全部平仓(基于保证金收益比)
|
||||
take_profit = position_info.get('takeProfit')
|
||||
if take_profit is not None and position_info['side'] == 'BUY' and current_price >= take_profit:
|
||||
logger.info(
|
||||
f"{symbol} 触发止盈: {current_price:.4f} >= {take_profit:.4f} "
|
||||
f"(盈亏: {pnl_percent:.2f}%)"
|
||||
)
|
||||
exit_reason = 'take_profit'
|
||||
# 更新数据库
|
||||
if DB_AVAILABLE:
|
||||
trade_id = position_info.get('tradeId')
|
||||
if trade_id:
|
||||
try:
|
||||
Trade.update_exit(
|
||||
trade_id=trade_id,
|
||||
exit_price=current_price,
|
||||
exit_reason=exit_reason,
|
||||
pnl=pnl_percent * entry_price * quantity / 100,
|
||||
pnl_percent=pnl_percent
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"更新止盈记录失败: {e}")
|
||||
if await self.close_position(symbol, reason=exit_reason):
|
||||
closed_positions.append(symbol)
|
||||
continue
|
||||
|
||||
if take_profit is not None and position_info['side'] == 'SELL' and current_price <= take_profit:
|
||||
logger.info(
|
||||
f"{symbol} 触发止盈: {current_price:.4f} <= {take_profit:.4f} "
|
||||
f"(盈亏: {pnl_percent:.2f}%)"
|
||||
)
|
||||
exit_reason = 'take_profit'
|
||||
# 更新数据库
|
||||
if DB_AVAILABLE:
|
||||
trade_id = position_info.get('tradeId')
|
||||
if trade_id:
|
||||
try:
|
||||
Trade.update_exit(
|
||||
trade_id=trade_id,
|
||||
exit_price=current_price,
|
||||
exit_reason=exit_reason,
|
||||
pnl=pnl_percent * entry_price * quantity / 100,
|
||||
pnl_percent=pnl_percent
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"更新止盈记录失败: {e}")
|
||||
if await self.close_position(symbol, reason=exit_reason):
|
||||
closed_positions.append(symbol)
|
||||
continue
|
||||
if take_profit is not None:
|
||||
# 计算止盈对应的保证金百分比
|
||||
if position_info['side'] == 'BUY':
|
||||
take_profit_amount = (take_profit - entry_price) * quantity
|
||||
else: # SELL
|
||||
take_profit_amount = (entry_price - take_profit) * quantity
|
||||
take_profit_pct_margin = (take_profit_amount / margin * 100) if margin > 0 else 0
|
||||
|
||||
# 直接比较当前盈亏百分比与止盈目标(基于保证金)
|
||||
if pnl_percent_margin >= take_profit_pct_margin:
|
||||
logger.info(
|
||||
f"{symbol} 触发止盈(基于保证金): "
|
||||
f"当前盈亏={pnl_percent_margin:.2f}% of margin >= 目标={take_profit_pct_margin:.2f}% of margin | "
|
||||
f"当前价={current_price:.4f}, 止盈价={take_profit:.4f}"
|
||||
)
|
||||
exit_reason = 'take_profit'
|
||||
# 更新数据库
|
||||
if DB_AVAILABLE:
|
||||
trade_id = position_info.get('tradeId')
|
||||
if trade_id:
|
||||
try:
|
||||
Trade.update_exit(
|
||||
trade_id=trade_id,
|
||||
exit_price=current_price,
|
||||
exit_reason=exit_reason,
|
||||
pnl=pnl_amount,
|
||||
pnl_percent=pnl_percent_margin
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"更新止盈记录失败: {e}")
|
||||
if await self.close_position(symbol, reason=exit_reason):
|
||||
closed_positions.append(symbol)
|
||||
continue
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"检查止损止盈失败: {e}")
|
||||
|
|
@ -1434,75 +1407,68 @@ class PositionManager:
|
|||
f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)"
|
||||
)
|
||||
|
||||
# 检查止损
|
||||
stop_loss = position_info['stopLoss']
|
||||
# 检查止损(基于保证金收益比)
|
||||
stop_loss = position_info.get('stopLoss')
|
||||
should_close = False
|
||||
exit_reason = None
|
||||
|
||||
if position_info['side'] == 'BUY' and current_price <= stop_loss:
|
||||
should_close = True
|
||||
exit_reason = 'trailing_stop' if position_info.get('trailingStopActivated') else 'stop_loss'
|
||||
logger.warning(
|
||||
f"{symbol} [实时监控] 触发止损: {current_price:.4f} <= {stop_loss:.4f} "
|
||||
f"(盈亏: {pnl_percent:.2f}%)"
|
||||
)
|
||||
elif position_info['side'] == 'SELL' and current_price >= stop_loss:
|
||||
should_close = True
|
||||
exit_reason = 'trailing_stop' if position_info.get('trailingStopActivated') else 'stop_loss'
|
||||
logger.warning(
|
||||
f"{symbol} [实时监控] 触发止损: {current_price:.4f} >= {stop_loss:.4f} "
|
||||
f"(盈亏: {pnl_percent:.2f}%)"
|
||||
)
|
||||
|
||||
# 检查止盈
|
||||
if not should_close:
|
||||
take_profit = float(position_info['takeProfit'])
|
||||
# 计算止盈百分比(用于诊断)
|
||||
if stop_loss is not None:
|
||||
# 计算止损对应的保证金百分比目标
|
||||
# 止损金额 = (开仓价 - 止损价) × 数量 或 (止损价 - 开仓价) × 数量
|
||||
if position_info['side'] == 'BUY':
|
||||
take_profit_pct = ((take_profit - entry_price) / entry_price) * 100
|
||||
stop_loss_amount = (entry_price - stop_loss) * quantity
|
||||
else: # SELL
|
||||
take_profit_pct = ((entry_price - take_profit) / entry_price) * 100
|
||||
stop_loss_amount = (stop_loss - entry_price) * quantity
|
||||
|
||||
# 每5%盈利记录一次诊断日志(帮助排查问题)
|
||||
# 使用更宽松的条件,避免因为浮点数精度问题导致日志不输出
|
||||
if pnl_percent >= 5.0:
|
||||
# 每5%记录一次,但允许一些容差
|
||||
should_log = (int(pnl_percent) % 5 == 0) or (pnl_percent >= 10.0 and pnl_percent < 10.5)
|
||||
if should_log:
|
||||
trigger_condition = current_price_float >= take_profit if position_info['side'] == 'BUY' else current_price_float <= take_profit
|
||||
logger.warning(
|
||||
f"{symbol} [实时监控] 诊断: 盈利{pnl_percent:.2f}% | "
|
||||
f"当前价: {current_price_float:.4f} | "
|
||||
f"入场价: {entry_price:.4f} | "
|
||||
f"止盈价: {take_profit:.4f} ({take_profit_pct:.2f}%) | "
|
||||
f"方向: {position_info['side']} | "
|
||||
f"是否触发: {trigger_condition} | "
|
||||
f"价格差: {abs(current_price_float - take_profit):.4f} | "
|
||||
f"监控状态: {'运行中' if symbol in self._monitor_tasks else '未启动'}"
|
||||
)
|
||||
|
||||
# 如果盈利超过止盈目标但未触发,记录警告
|
||||
if pnl_percent > take_profit_pct and not trigger_condition:
|
||||
logger.error(
|
||||
f"{symbol} [实时监控] ⚠️ 异常: 盈利{pnl_percent:.2f}% > 止盈目标{take_profit_pct:.2f}%,但未触发平仓!"
|
||||
stop_loss_pct_margin = (stop_loss_amount / margin * 100) if margin > 0 else 0
|
||||
|
||||
# 直接比较当前盈亏百分比与止损目标(基于保证金)
|
||||
if pnl_percent_margin <= -stop_loss_pct_margin:
|
||||
should_close = True
|
||||
exit_reason = 'trailing_stop' if position_info.get('trailingStopActivated') else 'stop_loss'
|
||||
logger.warning(
|
||||
f"{symbol} [实时监控] 触发止损(基于保证金): "
|
||||
f"当前盈亏={pnl_percent_margin:.2f}% of margin <= 止损目标=-{stop_loss_pct_margin:.2f}% of margin | "
|
||||
f"当前价={current_price_float:.4f}, 止损价={stop_loss:.4f}"
|
||||
)
|
||||
|
||||
# 检查止盈(基于保证金收益比)
|
||||
if not should_close:
|
||||
take_profit = position_info.get('takeProfit')
|
||||
if take_profit is not None:
|
||||
# 计算止盈对应的保证金百分比目标
|
||||
# 止盈金额 = (止盈价 - 开仓价) × 数量 或 (开仓价 - 止盈价) × 数量
|
||||
if position_info['side'] == 'BUY':
|
||||
take_profit_amount = (take_profit - entry_price) * quantity
|
||||
else: # SELL
|
||||
take_profit_amount = (entry_price - take_profit) * quantity
|
||||
|
||||
take_profit_pct_margin = (take_profit_amount / margin * 100) if margin > 0 else 0
|
||||
|
||||
# 每5%盈利记录一次诊断日志(帮助排查问题)
|
||||
if pnl_percent_margin >= 5.0:
|
||||
should_log = (int(pnl_percent_margin) % 5 == 0) or (pnl_percent_margin >= 10.0 and pnl_percent_margin < 10.5)
|
||||
if should_log:
|
||||
trigger_condition = pnl_percent_margin >= take_profit_pct_margin
|
||||
logger.warning(
|
||||
f"{symbol} [实时监控] 诊断: 盈利{pnl_percent_margin:.2f}% of margin | "
|
||||
f"当前价: {current_price_float:.4f} | "
|
||||
f"入场价: {entry_price:.4f} | "
|
||||
f"止盈价: {take_profit:.4f} (目标: {take_profit_pct_margin:.2f}% of margin) | "
|
||||
f"方向: {position_info['side']} | "
|
||||
f"是否触发: {trigger_condition} | "
|
||||
f"监控状态: {'运行中' if symbol in self._monitor_tasks else '未启动'}"
|
||||
)
|
||||
price_diff = current_price_float - take_profit if position_info['side'] == 'BUY' else take_profit - current_price_float
|
||||
logger.error(f" 当前价: {current_price_float:.4f}, 止盈价: {take_profit:.4f}, 价格差: {price_diff:.4f}")
|
||||
|
||||
if position_info['side'] == 'BUY' and current_price_float >= take_profit:
|
||||
should_close = True
|
||||
exit_reason = 'take_profit'
|
||||
logger.info(
|
||||
f"{symbol} [实时监控] 触发止盈: {current_price_float:.4f} >= {take_profit:.4f} "
|
||||
f"(盈亏: {pnl_percent:.2f}%, 止盈目标: {take_profit_pct:.2f}%)"
|
||||
)
|
||||
elif position_info['side'] == 'SELL' and current_price_float <= take_profit:
|
||||
should_close = True
|
||||
exit_reason = 'take_profit'
|
||||
logger.info(
|
||||
f"{symbol} [实时监控] 触发止盈: {current_price_float:.4f} <= {take_profit:.4f} "
|
||||
f"(盈亏: {pnl_percent:.2f}%, 止盈目标: {take_profit_pct:.2f}%)"
|
||||
)
|
||||
|
||||
# 直接比较当前盈亏百分比与止盈目标(基于保证金)
|
||||
if pnl_percent_margin >= take_profit_pct_margin:
|
||||
should_close = True
|
||||
exit_reason = 'take_profit'
|
||||
logger.info(
|
||||
f"{symbol} [实时监控] 触发止盈(基于保证金): "
|
||||
f"当前盈亏={pnl_percent_margin:.2f}% of margin >= 止盈目标={take_profit_pct_margin:.2f}% of margin | "
|
||||
f"当前价={current_price_float:.4f}, 止盈价={take_profit:.4f}"
|
||||
)
|
||||
|
||||
# 如果触发止损止盈,执行平仓
|
||||
if should_close:
|
||||
|
|
@ -1510,8 +1476,8 @@ class PositionManager:
|
|||
f"{symbol} [自动平仓] 开始执行平仓操作 | "
|
||||
f"原因: {exit_reason} | "
|
||||
f"入场价: {entry_price:.4f} | "
|
||||
f"当前价: {current_price:.4f} | "
|
||||
f"盈亏: {pnl_percent:.2f}% | "
|
||||
f"当前价: {current_price_float:.4f} | "
|
||||
f"盈亏: {pnl_percent_margin:.2f}% of margin ({pnl_amount:.4f} USDT) | "
|
||||
f"数量: {quantity:.4f}"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -432,13 +432,38 @@ class RiskManager:
|
|||
# 计算止损金额(相对于保证金)
|
||||
stop_loss_amount = margin * stop_loss_percent
|
||||
|
||||
# 计算止损价(基于止损金额)
|
||||
# 计算基于保证金的止损价
|
||||
# 止损金额 = (开仓价 - 止损价) × 数量
|
||||
# 所以:止损价 = 开仓价 - (止损金额 / 数量)
|
||||
if side == 'BUY': # 做多,止损价低于入场价
|
||||
stop_loss_price = entry_price - (stop_loss_amount / quantity)
|
||||
stop_loss_price_margin = entry_price - (stop_loss_amount / quantity)
|
||||
else: # 做空,止损价高于入场价
|
||||
stop_loss_price = entry_price + (stop_loss_amount / quantity)
|
||||
stop_loss_price_margin = entry_price + (stop_loss_amount / quantity)
|
||||
|
||||
# 同时计算基于价格百分比的止损价(作为最小值保护)
|
||||
# 获取最小价格变动百分比(如果配置了)
|
||||
min_price_change_pct = self.config.get('MIN_STOP_LOSS_PRICE_PCT', None)
|
||||
if min_price_change_pct is not None:
|
||||
# 基于价格百分比的止损价
|
||||
if side == 'BUY':
|
||||
stop_loss_price_price = entry_price * (1 - min_price_change_pct)
|
||||
else:
|
||||
stop_loss_price_price = entry_price * (1 + min_price_change_pct)
|
||||
|
||||
# 取更宽松的止损价(对做多取更大的值,对做空取更小的值)
|
||||
if side == 'BUY':
|
||||
stop_loss_price = max(stop_loss_price_margin, stop_loss_price_price)
|
||||
else:
|
||||
stop_loss_price = min(stop_loss_price_margin, stop_loss_price_price)
|
||||
|
||||
logger.info(
|
||||
f"止损计算 ({side}): 基于保证金={stop_loss_price_margin:.4f}, "
|
||||
f"基于价格={stop_loss_price_price:.4f}, "
|
||||
f"最终止损={stop_loss_price:.4f} (取更宽松)"
|
||||
)
|
||||
else:
|
||||
# 没有配置最小价格变动,直接使用基于保证金的止损价
|
||||
stop_loss_price = stop_loss_price_margin
|
||||
|
||||
# 如果提供了技术分析数据,可以调整止损价(但不能超过基于保证金的止损范围)
|
||||
if klines and len(klines) >= 10:
|
||||
|
|
@ -543,13 +568,38 @@ class RiskManager:
|
|||
# 计算止盈金额(相对于保证金)
|
||||
take_profit_amount = margin * take_profit_percent
|
||||
|
||||
# 计算止盈价(基于止盈金额)
|
||||
# 计算基于保证金的止盈价
|
||||
# 止盈金额 = (止盈价 - 开仓价) × 数量
|
||||
# 所以:止盈价 = 开仓价 + (止盈金额 / 数量)
|
||||
if side == 'BUY': # 做多,止盈价高于入场价
|
||||
take_profit_price = entry_price + (take_profit_amount / quantity)
|
||||
take_profit_price_margin = entry_price + (take_profit_amount / quantity)
|
||||
else: # 做空,止盈价低于入场价
|
||||
take_profit_price = entry_price - (take_profit_amount / quantity)
|
||||
take_profit_price_margin = entry_price - (take_profit_amount / quantity)
|
||||
|
||||
# 同时计算基于价格百分比的止盈价(作为最小值保护)
|
||||
# 获取最小价格变动百分比(如果配置了)
|
||||
min_price_change_pct = self.config.get('MIN_TAKE_PROFIT_PRICE_PCT', None)
|
||||
if min_price_change_pct is not None:
|
||||
# 基于价格百分比的止盈价
|
||||
if side == 'BUY':
|
||||
take_profit_price_price = entry_price * (1 + min_price_change_pct)
|
||||
else:
|
||||
take_profit_price_price = entry_price * (1 - min_price_change_pct)
|
||||
|
||||
# 取更宽松的止盈价(对做多取更大的值,对做空取更小的值)
|
||||
if side == 'BUY':
|
||||
take_profit_price = max(take_profit_price_margin, take_profit_price_price)
|
||||
else:
|
||||
take_profit_price = min(take_profit_price_margin, take_profit_price_price)
|
||||
|
||||
logger.info(
|
||||
f"止盈计算 ({side}): 基于保证金={take_profit_price_margin:.4f}, "
|
||||
f"基于价格={take_profit_price_price:.4f}, "
|
||||
f"最终止盈={take_profit_price:.4f} (取更宽松)"
|
||||
)
|
||||
else:
|
||||
# 没有配置最小价格变动,直接使用基于保证金的止盈价
|
||||
take_profit_price = take_profit_price_margin
|
||||
|
||||
logger.info(
|
||||
f"止盈计算 ({side}): 入场价={entry_price:.4f}, 数量={quantity:.4f}, "
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user