diff --git a/backend/app/api/real_trading.py b/backend/app/api/real_trading.py index a1fe3cb..71c3d1e 100644 --- a/backend/app/api/real_trading.py +++ b/backend/app/api/real_trading.py @@ -24,17 +24,42 @@ class OrderResponse(BaseModel): @router.get("/orders") async def get_orders( symbol: Optional[str] = Query(None, description="交易对筛选"), - status: Optional[str] = Query(None, description="状态筛选: active, closed"), + status: Optional[str] = Query(None, description="状态筛选: active, closed, exchange"), limit: int = Query(100, description="返回数量限制") ): """ 获取实盘订单列表 - symbol: 可选,按交易对筛选 - - status: 可选,active=活跃订单, closed=已平仓订单 + - status: 可选 + - active: 本地数据库的活跃订单 + - closed: 本地数据库的历史订单 + - exchange: 交易所的历史订单(推荐) - limit: 返回数量限制,默认100 """ try: + # 如果请求交易所历史订单,直接从交易所获取 + if status == "exchange": + trading_api = get_bitget_trading_api() + + if not trading_api: + return { + "success": False, + "message": "Bitget API 未配置", + "count": 0, + "orders": [] + } + + orders = trading_api.get_closed_orders(symbol, limit) + + return { + "success": True, + "count": len(orders), + "orders": orders, + "source": "exchange" + } + + # 否则从本地数据库获取 service = get_real_trading_service() if not service: @@ -76,7 +101,8 @@ async def get_orders( return { "success": True, "count": len(orders), - "orders": orders + "orders": orders, + "source": "database" } except Exception as e: logger.error(f"获取实盘订单列表失败: {e}") diff --git a/backend/app/services/bitget_trading_api_sdk.py b/backend/app/services/bitget_trading_api_sdk.py index 4b50ddb..a6b15c4 100644 --- a/backend/app/services/bitget_trading_api_sdk.py +++ b/backend/app/services/bitget_trading_api_sdk.py @@ -364,6 +364,35 @@ class BitgetTradingAPI: return positions[0] return None + def get_closed_orders(self, symbol: str = None, limit: int = 100) -> List[Dict]: + """ + 查询历史成交订单(从交易所获取) + + Args: + symbol: 交易对(不传则查询所有) + limit: 返回数量 + + Returns: + 历史订单列表 + """ + try: + # 使用 CCXT 的 fetch_closed_orders 或 fetch_my_trades + if symbol: + ccxt_symbol = self._standardize_symbol(symbol) + orders = self.exchange.fetch_closed_orders(ccxt_symbol, limit=limit) + else: + orders = self.exchange.fetch_closed_orders(limit=limit) + + logger.debug(f"查询到 {len(orders)} 条历史订单") + return orders + + except ccxt.BaseError as e: + logger.error(f"❌ 查询历史订单失败: {e}") + return [] + except Exception as e: + logger.error(f"❌ 查询历史订单异常: {e}") + return [] + # ==================== 账户操作 ==================== def get_balance(self) -> Dict: diff --git a/frontend/real-trading.html b/frontend/real-trading.html index a91d606..4b2be5b 100644 --- a/frontend/real-trading.html +++ b/frontend/real-trading.html @@ -229,6 +229,14 @@ color: #ff4444; } + .fee-positive { + color: #00ff41; + } + + .fee-negative { + color: #ff4444; + } + .status-badge { display: inline-block; padding: 2px 8px; @@ -498,14 +506,11 @@ 交易对 方向 - 等级 - 入场价 - 当前价 + 类型 + 价格 数量 - 杠杆 - 止损 - 止盈 - 盈亏 + 成交金额 + 手续费 状态 时间 @@ -536,36 +541,28 @@ @@ -664,7 +661,8 @@ async fetchHistoryOrders() { try { - const response = await axios.get('/api/real-trading/orders?status=closed&limit=50'); + // 从交易所获取历史订单 + const response = await axios.get('/api/real-trading/orders?status=exchange&limit=50'); if (response.data.success) { this.historyOrders = response.data.orders; } @@ -710,6 +708,28 @@ // 例如:BTC/USDT:USDT -> BTCUSDT if (!symbol) return '-'; return symbol.replace('/', '').replace(':', ''); + }, + + formatOrderStatus(status) { + const map = { + 'open': '挂单中', + 'closed': '已成交', + 'canceled': '已取消', + 'cancelled': '已取消', + 'filled': '已成交', + 'partially_filled': '部分成交', + 'rejected': '已拒绝', + 'expired': '已过期' + }; + return map[status] || status; + }, + + getFeeClass(order) { + const fee = parseFloat(order.fee || 0); + if (fee === 0) return ''; + // 如果是 taker (fee > 0),显示为负(花费) + // 如果是 maker (fee < 0),显示为正(返还) + return fee > 0 ? 'fee-negative' : 'fee-positive'; } }, mounted() {