实时行情面板最危险的状态:价格还在,数据其实已经停了

TickDB Research ·

实时行情面板最危险的状态:价格还在,数据其实已经停了

摘要:报价卡至少要回答“看谁、多少钱、什么时候、现在是否还可信”。本文用一个真实 BTCUSDT 样本跑通 REST 快照、WebSocket 更新和本地 stale 状态,把“流停了但价格还在”变成可感知的事故,并给出一份已有面板的自检清单。

你做过行情面板的话,一定见过这种画面:价格在动,刷新也正常。过了一会儿你偶然发现,某个报价已经好几分钟没变了。不是市场在横盘,而是数据流早就停了,但界面上最后一次收到的价格仍然留在那里,看起来一切正常。

这就是实时行情面板最危险的状态:价格还在,数据其实已经停了。 没有报错,没有空白,只有一个安静的数字,悄悄失去了时效性。

如果你已经在维护一个行情面板,这篇文章值得看。最大的风险不是界面难看,而是界面无法表达自己是否可信。一个能让人放心用的面板,不是价格跳得快就够了。在价格旁边,至少还要有“这个价格是什么时候的”和“现在还能不能信”。

下面用 BTCUSDT 跑一遍真实流程:先拿 REST 快照初始化,再用 WebSocket 持续更新,最后用本地 watchdog 检测过期。每一步对应一个状态迁移,每一次迁移对应一个产品判断。

一、第一版行情面板的最小单元:一行报价,四块信息

第一版行情面板的最小展示单元不是一个价格,而是一条“对象 + 数值 + 时间 + 当前数据状态”的报价记录。

image.png 图:这张状态图由本次实测时间线生成。loading -> snapshot -> live -> stale 是本文应用侧的状态链;view_state、checked_at、received_at、reason 不是 TickDB 原生返回字段。

  • 对象:symbol,也就是“看谁”。面板上至少要让用户知道这行报价属于哪个品种。
  • 数值:last_price,也就是“多少钱”。但价格单独存在意义有限。
  • 时间:timestamp,也就是“什么时候”。这条价格是什么时刻的快照,和你什么时候收到它是两回事。
  • 状态:view_state,也就是“现在还能不能信”。数据流正常推送时是 live;推送中断超过阈值后是 stale。

四块信息缺任何一块,报价卡就有一个盲区。下面把 BTCUSDT 真实跑一遍,看这四块信息如何在界面状态中一步步落地。

二、REST 快照只能证明“某一刻曾成功过”

loading -> snapshot

首次加载面板时,用 REST ticker 拉一次快照。

REST 成功只代表本次快照已经拿到并通过字段检查,不代表后续数据会持续更新。

本次请求:

GET /v1/market/ticker?symbols=BTCUSDT

接口返回 HTTP 200、业务码 0,其中:

symbol=BTCUSDT
last_price=64224.00000000
timestamp=1783733139013
timestamp_utc=2026-07-11T01:25:39.013Z
checked_at=2026-07-11T01:25:39.749Z

拿到快照后,界面状态从 loading 进入 snapshot。价格已经显示,但数据是否还在持续更新,此时还不知道。

不能因为一次 REST 查询成功就把状态标为 live。 快照只证明了“某一刻查询成功”,而实时面板需要的是“持续更新”。

三、真正的 live 需要一条真实 WebSocket 消息来触发

snapshot -> live

WebSocket 连接成功不代表数据已经在推送,订阅成功同样不代表。连接、订阅、收到第一条业务消息,是三个独立事件。

本次使用:

wss://api.tickdb.ai/v1/realtime?api_key=...

建立连接,并发送订阅命令:

{"cmd":"subscribe","data":{"channel":"ticker","symbols":["BTCUSDT"]}}

收到订阅确认后,第一条 ticker 到达:

last_price=64224.00000000
timestamp=1783733142016

第二条 ticker 随后到达:

last_price=64223.99000000
timestamp=1783733143016
received_at=2026-07-11T01:25:42.772Z

只有真实 ticker 消息到达后,状态才由 snapshot 迁移到 live。

此时面板上显示的不再是“曾经查到的价格”,而是“正在更新的价格”。

image.png 图:这张 LIVE 报价卡由同一次 BTCUSDT 实测数据生成,价格、行情 timestamp 与本地 received_at 分开显示。它用于解释界面设计,不是 TickDB 产品后台截图;view_state 和 reason 由本地应用派生。

四、价格还在不等于数据还活着

live -> stale

最容易被忽略的状态迁移,是 live 到 stale。

stale 与 unavailable 不能只按“连接是否断开”机械划分。

本文实际验证的是:更新被受控停止后,报价卡仍保留最后一个价格,本地 watchdog 随后将它标为 stale。

unavailable 是本文没有实测的失败设计分支,可用于请求失败、字段校验失败或数据入口不可用等场景,具体判定应由应用自己定义。

本次实测中,脚本在收到两条真实 ticker 后主动受控断开,用来验证界面状态。本地演示 watchdog 阈值设为 6.0 秒,实际等待约 7.0 秒后,应用状态从 live 迁移到 stale,原因是:

watchdog_timeout_after_controlled_disconnect

这只是应用层演示逻辑,不是 TickDB 原生字段,不是 TickDB SLA,也不是对真实网络事故的外推。

timestamp 与本地 received_at 必须分开:

  • timestamp 回答“这条数据是什么时候的”;
  • received_at 回答“客户端是什么时候收到它的”。

二者差值不能直接当作端到端延迟,因为时钟来源、数据通道和客户端处理都会影响这个差值。

stale 是应用责任。 数据源提供消息,界面是否过期以及过期后如何提示,由产品自身定义。错误分支应进入 unavailable,而不是把空值补成 0 或继续显示旧价格。

image.png 图:这张 STALE 报价卡由同一次实测数据和本地状态机生成。价格仍保留最后收到的值,但 UI 明确将数据标为过期;stale_after_seconds 为本地演示配置,不是 TickDB 原生字段或通用生产建议。

五、BTCUSDT 实测全程

image.png 图:这张证据图由真实终端输出原文生成,保留了同一次 BTCUSDT 实测中的 REST 快照、两条 WebSocket ticker 与受控断开后的 stale 迁移;它不是重新编写的模拟返回。view_state、checked_at、received_at、reason 为本地应用字段。

本次实测完整走完了面板从首屏加载到数据过期的状态链:

  1. REST 快照完成字段校验;
  2. WebSocket 收到两条真实 ticker,触发 live;
  3. 受控停止更新;
  4. 本地 watchdog 超时,将状态标记为 stale。

哪些字段来自 TickDB、哪些字段由应用侧派生,需要显式写清:

字段归属作用
symbolTickDB REST / WebSocket报价对象
last_priceTickDB REST / WebSocket行情数值
timestampTickDB REST / WebSocket行情消息时间字段
checked_at本地应用REST 校验完成时间
received_at本地应用客户端收到 WebSocket 消息的时间
view_state本地应用loading / snapshot / live / stale / unavailable
reason本地应用状态变化原因

六、已有面板快速自检

如果你的行情面板已经在运行,可以用下面四条快速检查:

  • 断开数据流后,界面是否仍然显示绿色或“正常”?
    如果连“数据可能过期”的提示都没有,用户会默认一切正常。

  • 每一行报价有没有独立的最后更新时间?
    没有时间戳的价格,等于没有生产日期的食品。

  • 长时间没有新数据时,能否解释过期原因?
    reason 字段不只是给开发者看的,也是给用户提示和事后复盘使用的。

  • 失败时价格是否变成了 0 或空?
    失败应进入明确的异常状态,不应通过默认值伪装成正常数据。

七、TickDB 在这套面板流程中的位置

上面整条链路跑下来,行情面板需要两样东西:

  1. 一个能主动查询快照的入口;
  2. 一个能持续接收推送的入口。

TickDB 是统一实时行情数据 API,面向开发者、量化研究者、AI 工具用户和金融应用团队提供结构化行情数据入口。

本次实测中,TickDB 真实承担了两个角色:

  • REST ticker 负责首屏快照,返回结构化 symbol、last_price、timestamp,让面板完成 loading -> snapshot 的初始化。
  • WebSocket ticker 负责持续更新,推送真实 ticker 消息,让面板完成 snapshot -> live 的激活。

TickDB 提供原始行情入口,客户端仍要自己实现:

  • received_at
  • watchdog
  • view_state
  • reason
  • UI 降级与异常提示

TickDB 不替应用判断 stale,不自动证明页面当前可信,也不替代产品自己的失败处理。

适合谁

需要在研究脚本、行情面板、AI 工具或数据管道中接入结构化实时行情的开发者、量化研究者和金融应用团队。

解决什么

通过 REST 和 WebSocket 提供可程序化调用的结构化行情数据。本文实测确认了 BTCUSDT 在两条入口中的 symbol、last_price、timestamp 可以被读取和核对;扩展到其他市场或端点时,仍应逐项确认字段路径与时间语义。

怎么验证

用自己的 symbol 跑一次 REST 快照校验,再接一次 WebSocket 订阅,同时记录 checked_at、received_at、view_state 和 reason。

不适合什么

TickDB 不替代投资判断,不证明策略有效,也不承诺最低延迟、全市场覆盖、无断流、自动回补、SLA 或排名。

八、FAQ

Q1:REST 已经返回价格,为什么不能直接显示 live?

REST 快照只能证明某一次查询成功,不证明后续数据还在更新。live 代表“正在持续更新”,只有真实 WebSocket 消息到达后才应触发状态迁移。

Q2:WebSocket connected、subscribed 和收到 ticker 有什么区别?

connected 是通道建立,subscribed 是订阅命令被接受,收到 ticker 业务消息才证明数据链路真正跑通。三件事各自独立,不能用一个代替另一个。

Q3:timestamp、received_at、checked_at 为什么不能混成一个时间?

timestamp 是行情消息自身携带的时间,checked_at 是 REST 校验完成时间,received_at 是客户端收到 WebSocket 消息的时间。三个时间回答不同问题,混在一起就无法区分数据本身与客户端处理过程。

Q4:stale 阈值应该固定为 6 秒吗?

不是。本文的 6 秒只是本地演示配置。不同品种、交易时段和产品场景的容忍度不同,stale 阈值应由产品侧根据实际需求定义,不能照搬本文演示值。

Q5:第一版实时行情卡片最低要展示哪些字段?

对象(symbol)、数值(last_price)、时间和当前数据状态(view_state)。

时间至少要包含行情 timestamp;如果还要判断数据流是否持续更新,应另外记录本地 received_at。四块信息缺任何一块,报价卡就有一个盲区。

Q6:REST 与 WebSocket 在行情面板里各负责什么?

REST 适合首屏加载和主动查询快照,WebSocket 适合持续推送和实时更新。两者互补,不能互相替代。

最后

先把一张报价卡做到可信:对象、数值、时间、状态四块信息齐全,loading -> snapshot -> live -> stale 状态迁移完整。

然后再考虑扩展品种列表、K线组件和多市场面板。

可信比复杂重要。

本文以 TickDB REST 与 WebSocket 真实调用为证据,仅讨论实时行情面板的产品状态与工程校验,不构成投资建议,不承诺延迟、SLA、生产稳定性或全市场覆盖。

相关文章

A股美股港股行情看板Demo三天、上线三个月:拆解7个返工点

同一张行情表,寒武纪的成交额自己算是5,414万元,接口给的是54.20亿元,差了100倍,原因只是一个单位。行情看板三天就能接通,上线后的返工,几乎都来自界面上说不清“自己是什么”的数字。 本文依据上交所、港交所的一手文件,加上10月12日盘中对7类资产的实测,给你四样东西: 一张“价格身份证”:每个数字上线前要答的5个问题 7个返工点逐条拆:钱在哪里算错、为什么会错 一份可以直接发给数据…

TickDB Research ·

拆解美股夜盘数据5个口径:12月6日起美股进入23小时交易

同一只苹果股票,同一个周六中午,三个“最新价”,1万股持仓估值差出 9,500 美元。12月6日起,美股将进入近23小时交易:夜盘数据的5个口径不说清,日K线、收益率、风控和对账都会悄悄算错。 本文依据纳斯达克、SEC、DTCC、FINRA 等一手文件,加上30只美股(含9只中概股)的实测数据,给你四样东西: 一张“北京时间 × 美股夜盘”全景图(含11月1日夏令时切换前后) 5个口径逐条拆…

TickDB Research ·

港股数据源选型:踩一个回测就假(富途/IBKR/TickDB)

回测里某个港股策略表现稳定,实盘跑了一个月,收益差了将近一半。 不是完全对不上,是那种“差异不大但一直在”的偏差。团队排查了三周——策略逻辑、滑点模型、手续费、执行延迟,全部查过。最后发现问题在数据层:数据源返回的港股代码是“700”,而团队数据库里存的是“00700”。两个格式查出来的数据,部分重叠,部分不重叠。回测用的样本,比实际可交易的样本少了一批。 这不是某个操作失误,是港股数据接入…

TickDB Research ·

A股休市10天,港股跌了,美联储还要开会,APEC即将落地深圳——8号开盘,你盘清楚了几件事?

后天开盘。10月8日,A股恢复交易。你手里的A股仓位,价格停在9月30日;但如果你同时持有港股、美股、QDII,这10天它们一直在动——港股10月2日就开盘了,美股全程正常交易。 这篇文章要说的不是“A股休市了”。有仓位的人都知道A股休市。它要说的是: 同一段时间里,你的三个市场仓位在动,你的信息却只跟得上一个。 核心概念是 信息时态差 ——港股和美股的信息是连续的,每天有K线;A股的信息是…

TickDB Research ·

自选股跨了A股港股美股,还在打开三个APP翻?盘中扫异动前,先定这五个字段

自选股四十只,A股港股美股都有,每天早上打开三个 APP 翻一遍。有天腾讯盘中跌了 3%,又弹回来,我在外面吃饭,完全没看到。下午再打开,只看到它跌了 2%。 这个 2% 是结果,不是过程。 问题不在我没有实时数据。问题在我看到的那个数字——涨跌幅——它只告诉我一个方向,没告诉我这个方向是怎么走出来的。 同一只股票,只看涨跌幅和看开高低收加成交额,你做出的判断可以完全相反。股票池越大,这个差…

TickDB Research ·