From e2de4e8d0b84de2ad61132263ab9e8d869b23a8e Mon Sep 17 00:00:00 2001 From: shinchan-zhai Date: Mon, 23 Mar 2026 09:20:38 +0800 Subject: [PATCH] feat: US stock pre-market/after-hours data support - Parse extended hours fields from Sina Finance API (field 21-24) - Display pre-market/after-hours price, change%, and time in stock quotes - Update system prompt: stocks have real-time data via search_stock tool - Remove incorrect 'no real-time stock data' disclaimer --- agent/agent.go | 24 ++++++++++++++---------- agent/stock.go | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/agent/agent.go b/agent/agent.go index 6dace1b4..12eca5bc 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -286,11 +286,13 @@ func (a *Agent) buildSystemPrompt(lang string) string { %s ## 数据说明 -- 加密货币(BTC/ETH等):我有实时数据,会在上下文中标注 [Real-time] -- A股/港股/美股/外汇:我**没有**实时价格数据 -- 对于没有实时数据的标的,**严禁编造具体价格** -- 必须明确告诉用户"以下分析基于历史知识,不含实时数据,请以实际行情为准" -- 可以分析趋势、逻辑、策略框架,但具体价位必须让用户自己查看 +- 加密货币(BTC/ETH等):交易所实时数据,标注 [Real-time] +- A股/港股/美股:通过 search_stock 工具获取**实时行情**(新浪财经数据源) +- 美股支持**盘前盘后数据**:search_stock 返回的 quote 中 ext_price/ext_change_pct/ext_time 为盘前盘后价格 +- 当返回数据包含 is_ext_hours=true 时,**必须**向用户展示盘前/盘后价格 +- 外汇:没有实时数据,需要说明 +- 对于没有实时数据的标的,严禁编造具体价格 +- **有数据就给数据,没有才说没有。诚实但不过度声明。** ## 工具使用 你可以调用以下工具来执行操作: @@ -331,11 +333,13 @@ func (a *Agent) buildSystemPrompt(lang string) string { %s ## Data Notice -- Crypto (BTC/ETH): I have real-time data, marked [Real-time] in context -- Stocks/Forex: I do NOT have real-time prices -- For assets without real-time data, NEVER fabricate specific prices -- Must tell user: "Analysis based on historical knowledge, not live data. Verify with actual quotes." -- Can analyze trends, logic, strategy frameworks — but specific prices must be verified by user +- Crypto (BTC/ETH): Exchange real-time data, marked [Real-time] +- A-shares/HK/US stocks: Real-time quotes via search_stock tool (Sina Finance data) +- US stocks include **pre-market/after-hours data**: ext_price/ext_change_pct/ext_time in quote +- When is_ext_hours=true, you MUST show pre-market/after-hours prices to the user +- Forex: No real-time data — must inform user +- NEVER fabricate prices for assets without data +- Show data when you have it. Only disclaim when you don't. ## Tools You can call these tools to take action: diff --git a/agent/stock.go b/agent/stock.go index 32c194bd..6ae3bb31 100644 --- a/agent/stock.go +++ b/agent/stock.go @@ -30,6 +30,12 @@ type StockQuote struct { Time string Change float64 ChangePct float64 + // 盘前盘后 (美股) + ExtPrice float64 // 盘前/盘后价格 + ExtChangePct float64 // 盘前/盘后涨跌幅% + ExtChange float64 // 盘前/盘后涨跌额 + ExtTime string // 盘前/盘后时间 + IsExtHours bool // 是否在盘前盘后时段 } // knownStocks maps Chinese names to stock codes. @@ -358,6 +364,21 @@ func parseUSShare(code, data string) (*StockQuote, error) { if len(f) > 25 { q.Date = f[25]; q.Time = f[26] } q.PrevClose = q.Price - q.Change _ = high52; _ = low52 + + // 盘前盘后数据 (字段21=价格, 22=涨跌幅%, 23=涨跌额, 24=时间) + if len(f) > 24 { + extPrice, _ := strconv.ParseFloat(f[21], 64) + extPct, _ := strconv.ParseFloat(f[22], 64) + extChg, _ := strconv.ParseFloat(f[23], 64) + if extPrice > 0 { + q.ExtPrice = extPrice + q.ExtChangePct = extPct + q.ExtChange = extChg + q.ExtTime = strings.TrimSpace(f[24]) + q.IsExtHours = true + } + } + return q, nil } @@ -376,7 +397,7 @@ func formatStockQuote(q *StockQuote) string { turnStr := fmt.Sprintf("%.0f", q.Turnover) if q.Turnover > 100000000 { turnStr = fmt.Sprintf("%.2f亿", q.Turnover/100000000) } - return fmt.Sprintf(`%s *%s* (%s · %s) + result := fmt.Sprintf(`%s *%s* (%s · %s) 💰 现价: %s%.2f (%+.2f%%) 📊 开盘: %s%.2f | 昨收: %s%.2f 📈 最高: %s%.2f | 最低: %s%.2f @@ -388,4 +409,18 @@ func formatStockQuote(q *StockQuote) string { sym, q.High, sym, q.Low, volStr, turnStr, q.Date) + + // 盘前盘后数据 + if q.IsExtHours && q.ExtPrice > 0 { + extEmoji := "🟢" + if q.ExtChangePct < 0 { extEmoji = "🔴" } + extLabel := "🌙 盘后" + if strings.Contains(strings.ToLower(q.ExtTime), "am") { + extLabel = "🌅 盘前" + } + result += fmt.Sprintf("\n%s %s: %s%.2f (%+.2f%%) %s", + extLabel, extEmoji, sym, q.ExtPrice, q.ExtChangePct, q.ExtTime) + } + + return result }