A股实时行情看板怎么做:多股票监控里,WebSocket 有消息不等于全表已更新
作者: TickDB Research · 发布: 2026/9/2 · 阅读: 8
标签: 掘金
你的看板显示五只股票,价格都在。绿色红色交替,数字在跳。你扫一眼,觉得一切正常。
直到你发现其中一只的价格已经很久没变,但你无法从页面上判断它到底是在正常波动,还是停在了某个旧快照上。
有价格≠在更新。这是多股票行情看板最容易踩的坑。
30秒抓住重点
>
问题:看板上每格都有数字,不代表每格都收到过实时消息
根因:快照写入和消息写入,在应用层被混成了同一个"正常"状态
方案:加一个
state字段,把"只有快照"和"见过消息"分开效果:看板能告诉你,每个格子的"正常"是根据什么得出的
适合:自己写行情看板、多标的监控、WebSocket订阅的人
TickDB 在这条链路里做什么:REST ticker 取行情快照,WebSocket ticker 接收订阅消息。至于某一格到底处于什么状态,由应用自己逐标的记录。下面代码解决的就是这个应用层问题。
先看代码:两个函数解决状态混用
核心就一件事:快照写入和消息更新,不能共用同一个"正常"状态。
const board = new Map();
function rowFor(symbol) {
if (!board.has(symbol)) {
board.set(symbol, {
symbol,
last_price: null, // 来自 WebSocket 消息的最新价格
snapshot_price: null, // 来自 REST 快照的价格
last_message_at: null, // 最后收到消息的时间
last_snapshot_at: null, // 最后收到快照的时间
state: "unknown",
next_check: "waiting_for_snapshot"
});
}
return board.get(symbol);
}
// REST ticker 的返回行:只证明本次拿到了快照。
function applySnapshot(row) {
const item = rowFor(row.symbol);
// 记录快照时间和快照价格
item.snapshot_price = row.last_price;
item.last_snapshot_at = new Date().toISOString();
// 只有在尚未收到任何 WebSocket 消息时,才用快照价格填充显示价格。
// 如果已经收到过消息,不覆盖 last_price——否则旧快照可能把更新的价格盖掉。
if (item.state === "unknown") {
item.last_price = row.last_price;
item.state = "snapshot_only";
item.next_check = "wait_for_symbol_message";
}
}
// WebSocket ticker 已解析为 { symbol, last_price } 后再调用。
function applyTicker(ticker) {
const item = rowFor(ticker.symbol);
item.last_price = ticker.last_price;
item.last_message_at = new Date().toISOString();
item.state = "live_message_seen";
item.next_check = "monitor_freshness";
}
applySnapshot 和 applyTicker 是两种完全不同的写入路径。
快照只证明"我拿到过一次结果",消息只证明"本次观察中见过该标的消息"。如果两个函数把状态都设成同一个值,看板就无法告诉你某个价格到底来自哪里。
订阅 ticker 时,按你的监控列表传入标的:
{
"cmd": "subscribe",
"data": {
"channel": "ticker",
"symbols": ["YOUR_SYMBOL_1", "YOUR_SYMBOL_2"]
}
}
两种格子,看起来一样,实际不同
如果页面只保存最后价格,旧快照可能继续显示,而应用没有证据证明它仍在更新。这是常见的应用层风险,不是接口本身的问题。
| 页面上看到的内容 | 实际证据 | 应显示的状态 |
|---|---|---|
| 有价格,但没有该标的消息记录 | REST 快照已写入 | snapshot_only |
| 有价格,且记录到该标的消息时间 | WebSocket ticker 已到达 | live_message_seen |
看板至少要打印这五列,才能知道每个格子的"正常"是根据什么得出的:
| 字段 | 用途 |
|---|---|
symbol | 找到对应标的 |
last_price | 当前显示价格(来自消息或快照) |
last_message_at | 最后一次收到该标的消息的时间 |
state | 区分未知、只有快照、见过消息 |
next_check | 告诉应用下一步应等待消息还是持续监控新鲜度 |
TickDB 在这条链路里做什么
TickDB 提供两种可核对的输入:
- REST ticker:一次查询一个或多个标的的行情快照
- WebSocket ticker:订阅 ticker 消息
看板自己的职责是保存每个标的最后一次消息时间、当前状态和后续处置标记。断线后的重新订阅、快照补查、去重和陈旧告警,这些是应用层需要设计的后续动作,本次未验证恢复流程。接口连上了,不代表这些事会自动完成。
真实调用:同一张看板,两种状态
本次有限观察窗口内:
做了什么:
REST 查询多个标的快照 → 返回价格
WebSocket 订阅同一批标的 → 观察若干时间
看到了什么:
两个样本中,一个见到 ticker 消息,另一个只有快照
说明了什么:
同一张看板里的不同标的,证据状态可以不同
这次调用没有测试延迟、长期连接、全市场覆盖、断线重连或补查效果。它只证明一件事:快照和消息是两种证据,必须分开记录。
检查清单
- [ ] REST 快照写入后,是否只把状态设为
snapshot_only? - [ ] 每条 ticker 消息,是否只更新它对应的标的?
- [ ] 页面是否展示或至少保存
last_message_at? - [ ] 一旦需要恢复,是否重新确认每个标的的状态,而不是只确认连接对象还存在?
FAQ
怎么开始?
先拿自己的两三个监控标的,接入 REST 快照和 ticker 订阅,再把上面五列打印到控制台。先看状态是否符合预期,再做页面样式。
数据异常时怎么定位或补回?
不要覆盖原状态。先保留最后价格、最后消息时间和状态,再由应用决定是否重新订阅、重新取快照或标记为待核。这样复盘时能分清是没有拿到快照,还是没有看到消息。
如果我只用 REST 轮询,能省掉这个状态管理吗?
不能完全省掉。只用 REST 时,你仍然要保存 last_fetched_at、请求结果和陈旧阈值,自己判断数据是否还新鲜。区别在于不用 live_message_seen 来判断消息到达,但状态管理本身逃不掉。
重连后,旧的 live_message_seen 状态还有效吗?
无效。重连后,应用可以将每个标的暂时置为"等待本连接消息确认",待新消息到达后再回到 live_message_seen。这是建议的应用层设计,本次未实测。
把"最后价格"旁边加一个状态字段。它不会替你做交易判断,却能让你少把旧快照当成正在更新的数据。
风险提示:本文讨论行情数据接入与状态展示,不构成投资或交易建议。
通过 TickDB API 获取实时行情数据
一个 API 接入外汇、加密货币、美股、港股、A股、贵金属和全球指数的实时行情。支持 WebSocket 低延迟推送,免费开始使用。
免费领取 API Key查看 API 文档