diff --git a/trading_system/position_manager.py b/trading_system/position_manager.py index a882895..7b25053 100644 --- a/trading_system/position_manager.py +++ b/trading_system/position_manager.py @@ -854,68 +854,58 @@ class PositionManager: position_info = self.active_positions[symbol] trade_id = position_info.get('tradeId') if trade_id: - try: - logger.info(f"{symbol} [平仓] 更新数据库状态为已平仓 (ID: {trade_id})...") - # 获取当前价格作为平仓价格 - ticker = await self.client.get_ticker_24h(symbol) - exit_price = float(ticker['price']) if ticker else float(position_info['entryPrice']) - - # 确保所有值都是float类型 - entry_price = float(position_info['entryPrice']) - quantity = float(position_info['quantity']) - if position_info['side'] == 'BUY': - pnl = (exit_price - entry_price) * quantity - pnl_percent = ((exit_price - entry_price) / entry_price) * 100 - else: - pnl = (entry_price - exit_price) * quantity - pnl_percent = ((entry_price - exit_price) / entry_price) * 100 - - # 同步平仓时没有订单号,设为None - # 计算持仓持续时间和策略类型 - entry_time = position_info.get('entryTime') - duration_minutes = None - if entry_time: - try: - if isinstance(entry_time, str): - entry_dt = datetime.strptime(entry_time, '%Y-%m-%d %H:%M:%S') - else: - entry_dt = entry_time - exit_dt = get_beijing_time() # 使用北京时间计算持续时间 - duration = exit_dt - entry_dt - duration_minutes = int(duration.total_seconds() / 60) - except Exception as e: - logger.debug(f"计算持仓持续时间失败: {e}") - - strategy_type = position_info.get('strategyType', 'trend_following') - - # 网络/DB 超时时可重试,避免 TimeoutError 导致状态未更新 - db_update_retries = 3 - for db_attempt in range(db_update_retries): - try: - Trade.update_exit( - trade_id=trade_id, - exit_price=exit_price, - exit_reason=reason, - pnl=pnl, - pnl_percent=pnl_percent, - exit_order_id=None, # 同步平仓时没有订单号 - strategy_type=strategy_type, - duration_minutes=duration_minutes + logger.info(f"{symbol} [平仓] 更新数据库状态为已平仓 (ID: {trade_id})...") + ticker = await self.client.get_ticker_24h(symbol) + exit_price = float(ticker['price']) if ticker else float(position_info['entryPrice']) + entry_price = float(position_info['entryPrice']) + quantity = float(position_info['quantity']) + if position_info['side'] == 'BUY': + pnl = (exit_price - entry_price) * quantity + pnl_percent = ((exit_price - entry_price) / entry_price) * 100 + else: + pnl = (entry_price - exit_price) * quantity + pnl_percent = ((entry_price - exit_price) / entry_price) * 100 + entry_time = position_info.get('entryTime') + duration_minutes = None + if entry_time: + try: + if isinstance(entry_time, str): + entry_dt = datetime.strptime(entry_time, '%Y-%m-%d %H:%M:%S') + else: + entry_dt = entry_time + exit_dt = get_beijing_time() + duration = exit_dt - entry_dt + duration_minutes = int(duration.total_seconds() / 60) + except Exception as e: + logger.debug(f"计算持仓持续时间失败: {e}") + strategy_type = position_info.get('strategyType', 'trend_following') + db_update_retries = 3 + for db_attempt in range(db_update_retries): + try: + Trade.update_exit( + trade_id=trade_id, + exit_price=exit_price, + exit_reason=reason, + pnl=pnl, + pnl_percent=pnl_percent, + exit_order_id=None, + strategy_type=strategy_type, + duration_minutes=duration_minutes + ) + logger.info(f"{symbol} [平仓] ✓ 数据库状态已更新") + updated = True + break + except Exception as e: + err_msg = str(e).strip() or f"{type(e).__name__}" + if db_attempt < db_update_retries - 1: + wait_sec = 2 + logger.warning( + f"{symbol} [平仓] 更新数据库失败 (第 {db_attempt + 1}/{db_update_retries} 次): {err_msg}," + f"{wait_sec}秒后重试" ) - logger.info(f"{symbol} [平仓] ✓ 数据库状态已更新") - updated = True - break - except Exception as e: - err_msg = str(e).strip() or f"{type(e).__name__}" - if db_attempt < db_update_retries - 1: - wait_sec = 2 - logger.warning( - f"{symbol} [平仓] 更新数据库失败 (第 {db_attempt + 1}/{db_update_retries} 次): {err_msg}," - f"{wait_sec}秒后重试" - ) - await asyncio.sleep(wait_sec) - else: - logger.error(f"{symbol} [平仓] ❌ 更新数据库状态失败: {err_msg}") + await asyncio.sleep(wait_sec) + else: + logger.error(f"{symbol} [平仓] ❌ 更新数据库状态失败: {err_msg}") # 清理本地记录 await self._stop_position_monitoring(symbol) @@ -1157,6 +1147,11 @@ class PositionManager: logger.error(f" 错误类型: {type(e).__name__}") import traceback logger.error(f" 错误详情:\n{traceback.format_exc()}") + except Exception as db_error: + logger.error(f"{symbol} [平仓] 更新平仓记录到数据库时发生异常: {db_error}") + logger.error(f" 错误类型: {type(db_error).__name__}") + import traceback + logger.error(f" 错误详情:\n{traceback.format_exc()}") else: logger.warning(f"{symbol} 没有关联的数据库交易ID,无法更新平仓记录") elif not DB_AVAILABLE: @@ -4077,4 +4072,4 @@ class PositionManager: except Exception as e: logger.error(f"{symbol} [诊断] 诊断失败: {e}") import traceback - logger.error(f" 错误详情:\n{traceback.format_exc()}") \ No newline at end of file + logger.error(f" 错误详情:\n{traceback.format_exc()}")