A股实时行情看板怎么做:多股票监控里,WebSocket 有消息不等于全表已更新

TickDB Research ·

你的看板显示五只股票,价格都在。绿色红色交替,数字在跳。你扫一眼,觉得一切正常。

直到你发现其中一只的价格已经很久没变,但你无法从页面上判断它到底是在正常波动,还是停在了某个旧快照上。

有价格≠在更新。这是多股票行情看板最容易踩的坑。


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。这是建议的应用层设计,本次未实测。


把"最后价格"旁边加一个状态字段。它不会替你做交易判断,却能让你少把旧快照当成正在更新的数据。

风险提示:本文讨论行情数据接入与状态展示,不构成投资或交易建议。

相关文章

AI Agent 框架接金融行情数据前,先检查这 7 个工程风险

> 本文不是框架排名,而是一份金融行情数据接入前的工程风险清单。每个风险点都附了检查方法和修正示例。 --- 一、不同框架,同一个坑 假设你用三个不同的 Agent 框架跑同一个任务——“每 30 分钟查一次价格,超过阈值时汇总分析”。 其中一个 Agent 把 ticker 快照的 (24 小时成交量)当成了单根 K 线的成交量,量级差了几千倍。另一个在 API 限流后陷入重试死循环,两分钟烧掉

TickDB Research ·

Qwen 已返回 `tool_calls`,为什么你的行情回答仍可能不可信?

摘要: Qwen 返回 ,不代表行情查询已经成功。本文从掘金开发者常见排错场景出发,拆解“触发工具、应用执行、结果校验、工具回填、最终回答”的最小可信链路,并给出未触发工具、查询失败或空结果、回填错误三个必须阻断价格回答的失败分支。TickDB 仅作为应用端只读行情数据路径示例出现。 你在日志里看到了这样的返回: 这只能说明一件事:模型提出了一个工具调用请求。 它不等于应用程序已经拿到行情,不

TickDB Research ·

Kimi 金融数据接入避坑:用 `tool_calls` 查询实时行情,而不是让模型猜价格

> Kimi 可以判断用户何时需要查询行情,但当前价格不能依靠模型猜测。本文基于 Moonshot 官方 流程,以 TickDB REST 为示例,拆解模型协议、本地工具函数与行情 API 的三层边界,并提供字段速查、最小 Python 实现和发布前验证清单。如果你让一个大模型回答“ 现在多少钱”,最危险的情况不是它报错,而是它给出一个语气非常确定、却没有实时数据来源的答案。 对于使用 Kim

TickDB Research ·

LangGraph 多 Agent 行情接入:节点之间传递实时数据的 3 种姿势

目录 - 一、当你的金融 Agent 节点“各说各话” - 二、姿势 1:State 共享——最简单,但 reducer 行为容易忽略 - 三、姿势 2:Tool 封装——最灵活,但 API 调用量是隐藏成本 - 四、姿势 3:Subgraph 组合——最工程,但状态映射是调试重点 - 五、三种姿势权衡矩阵与数据一致性策略 - 六、完整示例:盘前-盘中-盘后多 Agent 协同 - 七、FAQ -

TickDB Research ·

Codex 接入实时行情 MCP:从配置、鉴权到字段踩坑

目录 - 一、AI 写的量化代码,行情接口全是编的 - 二、MCP:给 Codex 装上真实的工具目录 - 三、配置四步走:从零到跑通第一个查询 - 四、三个验证示例 - 五、踩坑实录 - 六、13 个 MCP 工具速查 - 七、进阶:让 AI 写一个双均线策略 - 八、配置前 vs 配置后 --- 一、AI 写的量化代码,行情接口全是编的 上周二下午 4 点,我在 Codex 里输入了这样一句话

TickDB Research ·