mirror of
https://github.com/laoxong/nofx.git
synced 2026-06-04 01:48:22 +08:00
fix: chart order markers not displaying due to timestamp format mismatch
- Fix milliseconds to seconds conversion in parseCustomTime (AdvancedChart & ChartWithOrders) - Add GetTraderOrdersFiltered to filter orders at database level by symbol/status - Increase order limit from 50 to 200 for more historical orders - Group multiple orders at same candle time and show count (B3, S5, etc.) - Buy markers shown below bar (green), sell markers above bar (red)
This commit is contained in:
+3
-17
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<OrderMarker[]> => {
|
||||
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<number, { buys: number; sells: number }>()
|
||||
|
||||
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 要求标记按时间顺序)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user