From 1c10361a5513ac7f4235b6600b342621b3b1935c Mon Sep 17 00:00:00 2001 From: aaron <> Date: Tue, 10 Feb 2026 23:30:28 +0800 Subject: [PATCH] update --- backend/app/services/paper_trading_service.py | 74 ++++++++++++------- 1 file changed, 48 insertions(+), 26 deletions(-) diff --git a/backend/app/services/paper_trading_service.py b/backend/app/services/paper_trading_service.py index e91ab6a..f628d6f 100644 --- a/backend/app/services/paper_trading_service.py +++ b/backend/app/services/paper_trading_service.py @@ -254,12 +254,24 @@ class PaperTradingService: """ db = db_service.get_session() try: + # 从数据库重新查询订单,确保在当前会话中 + db_order = db.query(PaperOrder).filter(PaperOrder.order_id == order.order_id).first() + if not db_order: + logger.error(f"数据库中未找到订单: {order.order_id}") + return None + + # 更新订单状态 + db_order.status = OrderStatus.OPEN + db_order.filled_price = filled_price + db_order.opened_at = datetime.utcnow() + + db.commit() + db.refresh(db_order) + + # 同步更新内存缓存 order.status = OrderStatus.OPEN order.filled_price = filled_price - order.opened_at = datetime.utcnow() - - db.merge(order) - db.commit() + order.opened_at = db_order.opened_at logger.info(f"挂单已激活: {order.order_id} | {order.symbol} {order.side.value} @ ${filled_price:,.2f}") @@ -278,6 +290,8 @@ class PaperTradingService: } except Exception as e: logger.error(f"激活挂单失败: {e}") + import traceback + logger.error(traceback.format_exc()) db.rollback() return None finally: @@ -319,53 +333,61 @@ class PaperTradingService: """平仓并计算盈亏""" db = db_service.get_session() try: - # 计算盈亏 - if order.side == OrderSide.LONG: - pnl_percent = ((exit_price - order.filled_price) / order.filled_price) * 100 - else: - pnl_percent = ((order.filled_price - exit_price) / order.filled_price) * 100 + # 从数据库重新查询订单,确保在当前会话中 + db_order = db.query(PaperOrder).filter(PaperOrder.order_id == order.order_id).first() + if not db_order: + logger.error(f"数据库中未找到订单: {order.order_id}") + return None - pnl_amount = order.quantity * pnl_percent / 100 + # 计算盈亏 + if db_order.side == OrderSide.LONG: + pnl_percent = ((exit_price - db_order.filled_price) / db_order.filled_price) * 100 + else: + pnl_percent = ((db_order.filled_price - exit_price) / db_order.filled_price) * 100 + + pnl_amount = db_order.quantity * pnl_percent / 100 # 计算持仓时间 - hold_duration = datetime.utcnow() - order.opened_at if order.opened_at else timedelta(0) + hold_duration = datetime.utcnow() - db_order.opened_at if db_order.opened_at else timedelta(0) # 更新订单 - order.status = status - order.exit_price = exit_price - order.closed_at = datetime.utcnow() - order.pnl_amount = round(pnl_amount, 2) - order.pnl_percent = round(pnl_percent, 4) + db_order.status = status + db_order.exit_price = exit_price + db_order.closed_at = datetime.utcnow() + db_order.pnl_amount = round(pnl_amount, 2) + db_order.pnl_percent = round(pnl_percent, 4) - db.merge(order) db.commit() + db.refresh(db_order) # 从活跃订单缓存中移除 if order.order_id in self.active_orders: del self.active_orders[order.order_id] result = { - 'order_id': order.order_id, - 'symbol': order.symbol, - 'side': order.side.value, + 'order_id': db_order.order_id, + 'symbol': db_order.symbol, + 'side': db_order.side.value, 'status': status.value, - 'entry_price': order.filled_price, + 'entry_price': db_order.filled_price, 'exit_price': exit_price, - 'quantity': order.quantity, - 'pnl_amount': order.pnl_amount, - 'pnl_percent': order.pnl_percent, + 'quantity': db_order.quantity, + 'pnl_amount': db_order.pnl_amount, + 'pnl_percent': db_order.pnl_percent, 'is_win': pnl_amount > 0, 'hold_duration': str(hold_duration).split('.')[0], # 去掉微秒 - 'signal_grade': order.signal_grade.value if order.signal_grade else None + 'signal_grade': db_order.signal_grade.value if db_order.signal_grade else None } status_text = "止盈" if status == OrderStatus.CLOSED_TP else "止损" - logger.info(f"订单{status_text}: {order.order_id} | {order.symbol} | 盈亏: {pnl_percent:+.2f}% (${pnl_amount:+.2f})") + logger.info(f"订单{status_text}: {db_order.order_id} | {db_order.symbol} | 盈亏: {pnl_percent:+.2f}% (${pnl_amount:+.2f})") return result except Exception as e: logger.error(f"平仓失败: {e}") + import traceback + logger.error(traceback.format_exc()) db.rollback() return None finally: