diff --git a/backend/api/routes/trades.py b/backend/api/routes/trades.py index 9b4e6a5..326ff56 100644 --- a/backend/api/routes/trades.py +++ b/backend/api/routes/trades.py @@ -426,33 +426,50 @@ async def sync_trades_from_binance( start_ts_sec = start_time_ms // 1000 end_ts_sec = end_time_ms // 1000 - # 仅对 DB 中在时间范围内有 open/closed 记录的 symbol 拉取订单(WS 已回写订单号,大幅减少请求) + # 获取需要同步的 symbol 列表 + # 策略:先查时间范围内的记录,如果没有,则查所有有记录的 symbol(用于补全历史订单号) symbol_list = [] try: + # 先尝试用 "both" 过滤,确保能找到所有相关记录(包括3天前开仓但最近平仓的) trades_in_range = Trade.get_all( start_timestamp=start_ts_sec, end_timestamp=end_ts_sec, account_id=account_id or DEFAULT_ACCOUNT_ID, + time_filter="both", # 使用 both 确保能找到所有相关记录 ) symbol_list = list({t.get("symbol") for t in (trades_in_range or []) if t.get("symbol")}) + logger.info(f"从 DB 查询到 {len(trades_in_range or [])} 条记录,涉及 {len(symbol_list)} 个交易对") + + # 如果时间范围内没有记录,尝试获取所有有记录的 symbol(用于补全历史订单号) + if not symbol_list: + logger.info(f"时间范围内({days}天)无记录,尝试获取所有有记录的 symbol 用于补全订单号") + all_trades = Trade.get_all( + account_id=account_id or DEFAULT_ACCOUNT_ID, + ) + symbol_list = list({t.get("symbol") for t in (all_trades or []) if t.get("symbol")}) + logger.info(f"获取到所有有记录的 symbol: {len(symbol_list)} 个") except Exception as e: - logger.warning(f"从 DB 获取 symbol 列表失败,将跳过同步: {e}") + logger.warning(f"从 DB 获取 symbol 列表失败,将跳过同步: {e}", exc_info=True) return { - "success": True, - "message": "未获取到需同步的交易对,跳过(WS 正常时订单号已由推送回写)", + "success": False, + "message": f"从数据库获取交易对列表失败: {str(e)}", "total_orders": 0, "updated_trades": 0, + "entry_order_id_filled": 0, + "exit_order_id_filled": 0, "close_orders": 0, "open_orders": 0, } if not symbol_list: - logger.info("DB 内在时间范围内无交易记录,跳过全量拉取订单(WS 为主时无需频繁同步)") + logger.info(f"DB 中无任何交易记录,跳过同步") return { "success": True, - "message": "近期无交易记录,未请求币安订单;WS 正常时订单号已由推送回写", + "message": f"数据库中没有交易记录,无法同步订单", "total_orders": 0, "updated_trades": 0, + "entry_order_id_filled": 0, + "exit_order_id_filled": 0, "close_orders": 0, "open_orders": 0, } @@ -470,7 +487,7 @@ async def sync_trades_from_binance( # 仅对上述 symbol 拉取订单 all_orders = [] try: - logger.info(f"仅对 {len(symbol_list)} 个有 DB 记录的 symbol 拉取订单(已跳过全市场请求)") + logger.info(f"仅对 {len(symbol_list)} 个有 DB 记录的 symbol 拉取订单(时间范围: {days}天,{datetime.fromtimestamp(start_ts_sec)} 至 {datetime.fromtimestamp(end_ts_sec)})") for symbol in symbol_list: try: orders = await client.client.futures_get_all_orders( @@ -479,12 +496,14 @@ async def sync_trades_from_binance( endTime=end_time_ms ) filled_orders = [o for o in orders if o.get('status') == 'FILLED'] + if filled_orders: + logger.debug(f" {symbol}: 获取到 {len(filled_orders)} 个已成交订单") all_orders.extend(filled_orders) await asyncio.sleep(0.1) except Exception as e: - logger.debug(f"获取 {symbol} 订单失败: {e}") + logger.warning(f"获取 {symbol} 订单失败: {e}") continue - logger.info(f"从币安获取到 {len(all_orders)} 个已成交订单") + logger.info(f"从币安获取到 {len(all_orders)} 个已成交订单(涉及 {len(symbol_list)} 个交易对)") except Exception as e: logger.error(f"获取币安订单失败: {e}") raise HTTPException(status_code=500, detail=f"获取币安订单失败: {str(e)}")