From b7210029d1172dcc6405fe2944e56641add25a92 Mon Sep 17 00:00:00 2001 From: ZhouYongyou <128128010+zhouyongyou@users.noreply.github.com> Date: Tue, 4 Nov 2025 10:54:49 +0800 Subject: [PATCH] fix(market): resolve price staleness issue in GetCurrentKlines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem GetCurrentKlines had two critical bugs causing price data to become stale: 1. Incorrect return logic: returned error even when data fetch succeeded 2. Race condition: returned slice reference instead of deep copy, causing concurrent data corruption ## Impact - BTC price stuck at 106xxx while actual market price was 107xxx+ - LLM calculated take-profit based on stale prices → orders failed validation - Statistics showed incorrect P&L (0.00%) due to corrupted historical data - Alt-coins filtered out due to failed market data fetch ## Solution 1. Fixed return logic: only return error when actual failure occurs 2. Return deep copy instead of reference to prevent race conditions 3. Downgrade subscription errors to warnings (non-blocking) ## Test Results ✅ Price updates in real-time ✅ Take-profit orders execute successfully ✅ P&L calculations accurate ✅ Alt-coins now tradeable Related: Price feed mechanism, concurrent data access --- market/monitor.go | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/market/monitor.go b/market/monitor.go index 23e126d98..a09763e87 100644 --- a/market/monitor.go +++ b/market/monitor.go @@ -239,19 +239,32 @@ func (m *WSMonitor) GetCurrentKlines(symbol string, _time string) ([]Kline, erro // 如果Ws数据未初始化完成时,单独使用api获取 - 兼容性代码 (防止在未初始化完成是,已经有交易员运行) apiClient := NewAPIClient() klines, err := apiClient.GetKlines(symbol, _time, 100) - m.getKlineDataMap(_time).Store(strings.ToUpper(symbol), klines) //动态缓存进缓存 + if err != nil { + return nil, fmt.Errorf("获取%v分钟K线失败: %v", _time, err) + } + + // 动态缓存进缓存 + m.getKlineDataMap(_time).Store(strings.ToUpper(symbol), klines) + + // 订阅 WebSocket 流 subStr := m.subscribeSymbol(symbol, _time) subErr := m.combinedClient.subscribeStreams(subStr) log.Printf("动态订阅流: %v", subStr) if subErr != nil { - return nil, fmt.Errorf("动态订阅%v分钟K线失败: %v", _time, subErr) + log.Printf("警告: 动态订阅%v分钟K线失败: %v (使用API数据)", _time, subErr) } - if err != nil { - return nil, fmt.Errorf("获取%v分钟K线失败: %v", _time, err) - } - return klines, fmt.Errorf("symbol不存在") + + // ✅ FIX: 返回深拷贝而非引用 + result := make([]Kline, len(klines)) + copy(result, klines) + return result, nil } - return value.([]Kline), nil + + // ✅ FIX: 返回深拷贝而非引用,避免并发竞态条件 + klines := value.([]Kline) + result := make([]Kline, len(klines)) + copy(result, klines) + return result, nil } func (m *WSMonitor) Close() {