5.7 KiB
5.7 KiB
百度财经 WebSocket 行情实时刷新 — 设计
日期: 2026-07-22
状态: 已口头确认,待书面复核
1. 背景与目标
当前行情通过 HTTP getStockQuotation 在页面打开时拉取一次全量(分时、盘口、成交明细)。quotation.ts 已预留「实时更新后续对接 WebSocket」。
本阶段目标:接入百度财经 WebSocket,在 HTTP 全量底之上做增量刷新,使报价、盘口、分时图、分时成交与大单分析实时更新。
2. 已确认决策
| 项 | 选择 |
|---|---|
| 初始全量 | 现有 HTTP getStockQuotation,成功后再连 WS |
| 数据映射 | tick → 成交明细(TradeTape)+ 大单分析;snapshot → 报价 / 盘口 / 分时点 |
| 架构 | 独立 BaiduQuoteWs 客户端 + mapper;状态仍落 quota store |
| 合约 | 仍读 contractConfig 单合约,不做多合约订阅 |
| WS 库 | 原生 WebSocket,不引入第三方 |
| 连接 UI | 本期不做连接指示灯 / 手动重连按钮 |
3. 架构与数据流
页面挂载
→ quota.fetchQuote() // HTTP 全量
→ BaiduQuoteWs.connect() // wss://finance-ws.pae.baidu.com/
→ subscribe tick + snapshot
→ 每 6s ping
→ 每 60s patch snapshot
→ onMessage
→ product=tick → 合并 trades(最新在前)
→ product=snapshot → 更新报价 / 盘口 / upsert intraday
页面卸载 / 主动 refresh
→ BaiduQuoteWs.disconnect()(refresh 成功后再 connect)
模块划分
| 文件 | 职责 |
|---|---|
src/api/baidu/ws.ts |
连接、心跳、订阅、重连、回调 |
src/api/baidu/wsTypes.ts |
tick / snapshot 消息 TypeScript 类型 |
src/api/baidu/mapWsQuote.ts |
增量消息映射并合并进 QuoteData |
src/stores/quota.ts |
HTTP 成功后启 WS;应用增量;卸载断开 |
src/composables/useQuote.ts |
onMounted 拉行情;onUnmounted 断开 WS |
大单分析已基于 quote.trades 计算,只需更新 trades,不改组件。
4. 协议细节
端点: wss://finance-ws.pae.baidu.com/
订阅(open 后立即发送两条):
{"method":"subscribe","source":"pc-web","product":"tick","items":[{"code":"FG609","name":"玻璃2609","market":"ab","financeType":"futures"}]}
{"method":"subscribe","source":"pc-web","product":"snapshot","items":[{"code":"FG609","name":"玻璃2609","market":"ab","financeType":"futures"}]}
code / name 来自 contractConfig;market 固定 ab;financeType 固定 futures。
保活:
- 每 6s:
{"method":"ping","source":"pc-web"} - 每 60s:snapshot 的
patch(items 同订阅)
重连: 断线后指数退避(1s → 2s → 4s … 上限 30s);重连成功后重新 subscribe;不自动重拉 HTTP。
disconnect: 清 ping/patch 定时器、关闭 socket、停止重连调度。
5. 合并规则
5.1 tick → trades
- 解析
data.detailinfos→TradeTick[](字段映射与现有 HTTPparseTrades一致:formatTime/price/volume/bsFlag;最新在前) - 前置合并到
quote.trades - 去重键:
time + price + volume + side - 上限:最近 200 条
5.2 snapshot → 报价 / 盘口 / 分时
cur:更新last/change/changePercent/avg;状态可从cur.status或update取pankouinfos(数组,按ename):更新 open / high / low / volume / amount / openInterest / amplitude / settlement / prevSettlement / outerVol / innerVol 等askinfos/buyinfos:刷新五档;过滤无效价;重算buyRatio/sellRatioupdate:刷新updatedAt/statuspoint:按分钟时间(从point.time取HH:mm)upsert 到intraday- 覆盖 / 写入:
price←point.price,avg←point.avgPrice volume:WS 只给totalVolume(全日累计)。分钟成交量 =max(0, totalVolume - 此前各分钟 volume 之和);同分钟再次推送时用同一公式重算并覆盖- 新分钟:append;同分钟:覆盖该点
- 覆盖 / 写入:
5.3 错误处理
resultCode !== "0":打日志,忽略本条- JSON / 字段解析失败:打日志,不中断连接
- 组件层无感;不暴露 WS 连接状态到 UI
6. 生命周期
useQuoteonMounted→store.fetchQuote()fetchQuote成功 →store.connectWs()(若已连接则先 disconnect 再 connect)useQuoteonUnmounted→store.disconnectWs()refresh()/fetchForAnalysis():仍走 HTTP 全量;成功后重连 WS,用最新全量覆盖后再接增量- K 线逻辑不变;WS 不修改
candles
7. 明确不做(本期)
- 连接状态 UI / 手动重连按钮
- 多合约同时订阅
- 修改 TradeTape / LargeOrderAnalysis / ChartPanel(仅消费响应式
quote) - 引入第三方 WS 库
- WS 失败时回退 HTTP 轮询
8. 验证要点
- HTTP 成功后会发送 tick + snapshot 两条 subscribe
- 约每 6s 有 ping,约每 60s 有 snapshot patch
- tick 合并 trades:去重生效、长度 ≤ 200;TradeTape / 大单分析随之刷新
- snapshot.point:同分钟覆盖、新分钟追加;分时图更新
- snapshot 盘口 / 现价字段正确刷新
- 页面卸载后无残留 timer / 未关闭的 socket
- 手动 refresh 后 WS 会断开并重新订阅
9. 风险与注意
- WS 与 HTTP 的 snapshot 字段结构不完全一致(HTTP 用
origin_pankou,WS 用pankouinfos数组);mapper 需独立,勿强行复用 HTTP mapper 全文 - 去重键不含服务端唯一 id(协议未提供);极端情况下同秒同价同量同向两笔可能被误去重,可接受
- 跨域 / 鉴权:浏览器直连百度 WS;若环境拦截再评估代理,本期先直连