diff --git a/api/server.go b/api/server.go index 36e582fe..0bc6ebb4 100644 --- a/api/server.go +++ b/api/server.go @@ -2294,28 +2294,14 @@ func (s *Server) handleOrders(c *gin.Context) { return } - // Get all orders for this trader - allOrders, err := store.Order().GetTraderOrders(trader.GetID(), limit) + // Get orders with filters applied at database level + orders, err := store.Order().GetTraderOrdersFiltered(trader.GetID(), symbol, statusFilter, limit) if err != nil { SafeInternalError(c, "Get orders", err) return } - // Filter by symbol and status if specified - result := make([]interface{}, 0) - for _, order := range allOrders { - // Filter by symbol - if symbol != "" && order.Symbol != symbol { - continue - } - // Filter by status - if statusFilter != "" && order.Status != statusFilter { - continue - } - result = append(result, order) - } - - c.JSON(http.StatusOK, result) + c.JSON(http.StatusOK, orders) } // handleOrderFills Order fill details (all fills for a specific order) diff --git a/store/order.go b/store/order.go index 235485f5..f632ab3f 100644 --- a/store/order.go +++ b/store/order.go @@ -237,6 +237,27 @@ func (s *OrderStore) GetTraderOrders(traderID string, limit int) ([]*TraderOrder return orders, nil } +// GetTraderOrdersFiltered gets trader's order list with optional symbol and status filters +func (s *OrderStore) GetTraderOrdersFiltered(traderID string, symbol string, status string, limit int) ([]*TraderOrder, error) { + var orders []*TraderOrder + query := s.db.Where("trader_id = ?", traderID) + + if symbol != "" { + query = query.Where("symbol = ?", symbol) + } + if status != "" { + query = query.Where("status = ?", status) + } + + err := query.Order("created_at DESC"). + Limit(limit). + Find(&orders).Error + if err != nil { + return nil, fmt.Errorf("failed to query orders: %w", err) + } + return orders, nil +} + // GetOrderFills gets order's fill records func (s *OrderStore) GetOrderFills(orderID int64) ([]*TraderFill, error) { var fills []*TraderFill diff --git a/web/src/components/AdvancedChart.tsx b/web/src/components/AdvancedChart.tsx index 01b5cdff..4a6cd758 100644 --- a/web/src/components/AdvancedChart.tsx +++ b/web/src/components/AdvancedChart.tsx @@ -179,9 +179,15 @@ export function AdvancedChart({ return 0 } - // 如果已经是数字(Unix 时间戳),直接返回 + // 如果已经是数字(Unix 时间戳) if (typeof time === 'number') { - console.log('[AdvancedChart] ✅ Unix timestamp:', time, '(', new Date(time * 1000).toISOString(), ')') + // 判断是毫秒还是秒:如果大于 10^12 则认为是毫秒(2001年之后的毫秒时间戳) + if (time > 1000000000000) { + const seconds = Math.floor(time / 1000) + console.log('[AdvancedChart] ✅ Unix timestamp (ms→s):', time, '→', seconds, '(', new Date(time).toISOString(), ')') + return seconds + } + console.log('[AdvancedChart] ✅ Unix timestamp (s):', time, '(', new Date(time * 1000).toISOString(), ')') return time } @@ -221,8 +227,8 @@ export function AdvancedChart({ const fetchOrders = async (traderID: string, symbol: string): Promise => { try { console.log('[AdvancedChart] Fetching orders for trader:', traderID, 'symbol:', symbol) - // 获取已成交的订单,限制50条避免标记太多重叠 - const result = await httpClient.get(`/api/orders?trader_id=${traderID}&symbol=${symbol}&status=FILLED&limit=50`) + // 获取已成交的订单,增加到200条以显示更多历史订单 + const result = await httpClient.get(`/api/orders?trader_id=${traderID}&symbol=${symbol}&status=FILLED&limit=200`) console.log('[AdvancedChart] Orders API response:', result) @@ -580,15 +586,8 @@ export function AdvancedChart({ return klineTimes[left] } - // 过滤并对齐订单到 K 线时间 - const markers: Array<{ - time: Time - position: 'belowBar' - color: string - shape: 'circle' - text: string - size: number - }> = [] + // 按 K 线时间分组统计订单 + const ordersByCandle = new Map() orders.forEach(order => { // 使用二分查找找到对应的 K 线蜡烛时间 @@ -600,15 +599,48 @@ export function AdvancedChart({ return } - const isBuy = order.rawSide === 'buy' - markers.push({ - time: candleTime as Time, - position: 'belowBar' as const, - color: isBuy ? '#0ECB81' : '#F6465D', - shape: 'circle' as const, - text: isBuy ? 'B' : 'S', - size: 1, - }) + const existing = ordersByCandle.get(candleTime) || { buys: 0, sells: 0 } + if (order.rawSide === 'buy') { + existing.buys++ + } else { + existing.sells++ + } + ordersByCandle.set(candleTime, existing) + }) + + // 为每个有订单的 K 线创建标记 + const markers: Array<{ + time: Time + position: 'belowBar' | 'aboveBar' + color: string + shape: 'circle' + text: string + size: number + }> = [] + + ordersByCandle.forEach((counts, candleTime) => { + // 显示买入标记(绿色,在K线下方) + if (counts.buys > 0) { + markers.push({ + time: candleTime as Time, + position: 'belowBar' as const, + color: '#0ECB81', + shape: 'circle' as const, + text: counts.buys > 1 ? `B${counts.buys}` : 'B', + size: 1, + }) + } + // 显示卖出标记(红色,在K线上方) + if (counts.sells > 0) { + markers.push({ + time: candleTime as Time, + position: 'aboveBar' as const, + color: '#F6465D', + shape: 'circle' as const, + text: counts.sells > 1 ? `S${counts.sells}` : 'S', + size: 1, + }) + } }) // 按时间排序(lightweight-charts 要求标记按时间顺序) diff --git a/web/src/components/ChartWithOrders.tsx b/web/src/components/ChartWithOrders.tsx index 73c97a17..5d25ae25 100644 --- a/web/src/components/ChartWithOrders.tsx +++ b/web/src/components/ChartWithOrders.tsx @@ -63,9 +63,15 @@ export function ChartWithOrders({ return 0 } - // 如果已经是数字(Unix 时间戳),直接返回 + // 如果已经是数字(Unix 时间戳) if (typeof time === 'number') { - console.log('[ChartWithOrders] ✅ Unix timestamp:', time, '(', new Date(time * 1000).toISOString(), ')') + // 判断是毫秒还是秒:如果大于 10^12 则认为是毫秒(2001年之后的毫秒时间戳) + if (time > 1000000000000) { + const seconds = Math.floor(time / 1000) + console.log('[ChartWithOrders] ✅ Unix timestamp (ms→s):', time, '→', seconds, '(', new Date(time).toISOString(), ')') + return seconds + } + console.log('[ChartWithOrders] ✅ Unix timestamp (s):', time, '(', new Date(time * 1000).toISOString(), ')') return time }