摘要
一个覆盖 A 股、美股、港股、外汇和数字货币的行情面板,接入实时数据源只是第一步。真正让面板从"能用"变成"可信"的,是用户扫一眼就能判断三件事:这个价格是什么时候的?这个市场现在开没开?这个空白是正常的还是出问题了?本文从前端/产品的视角出发,设计一套与数据源解耦的行情状态模型------6 个核心字段、5 类异常状态、1 份 MVP 检查清单。不写复杂代码,只讲清楚"数据怎么进来、状态怎么流转、异常怎么暴露"。
这篇文章写给谁
如果你正准备做第一个行情面板。 不管你是前端在画组件,还是产品在定义字段,这份设计稿每一步都能落地。
如果你的面板已经在跑了。 价格能正常显示,但你偶尔会觉得哪里不太对------某个市场的价格好像没更新?新增一个市场要改一大片代码?这篇文章是一份对照检查清单,帮你找出面板里那些"看起来正常但实际不可信"的角落。
核心洞见
行情面板不是价格墙,而是数据可信度界面。
把价格数字堆在屏幕上,那是价格墙。让用户看到每条数据背后的时间、状态和完整性,那是可信度界面。后面所有内容------6 个字段、5 类异常、隐蔽故障、MVP 验证------全部围绕这句话展开。

一、行情面板的及格线
先把行情面板不是什么说清楚。它不是交易终端,不负责下单和持仓管理。它的本职工作只有一件事:让用户扫一眼就知道,当前这条行情数据能不能用。

怎么判断?就三个问题:
- 这个价格是什么时候的?
- 这个市场现在开没开?
- 这个空白是正常的还是出问题了?
这三个问题回答不了,价格再实时,用户心里也在打鼓。而要回答这三个问题,你的面板至少需要承载 6 个字段。
二、第一版必须定义的 6 个核心字段
这 6 个字段不是你"想不想展示"的问题,而是多市场行情数据天然就必须携带的信息。少一个,面板就多一个不可信的死角。
字段 1:symbol
用户到底在看哪个品种。
A 股:600519.SH
美股:AAPL.US
港股:700.HK
外汇:EUR/USD
数字货币:BTC/USDT
为什么必须定义:多市场场景下,同一个数字代码可能出现在不同市场。只存"600519"不带后缀,你分不清是 A 股还是港股。全球证券代码体系本身就是一座"巴别塔"------国际证券识别码(ISIN)不包含交易场所信息。同一家公司在港交所和纽交所上市的股票,ISIN 可能相同,但交易规则完全不同。symbol 天然需要和市场标识符搭配使用。
最常见错误:数据源自动给代码加后缀,但面板没告诉用户。请求的是"600519",返回的是"600519.SH"。如果文档没约定,这就是一颗定时炸弹。
字段 2:market
这条数据属于哪个市场。
为什么必须定义:市场类型决定了交易规则。A 股有涨跌幅限制,美股没有;A 股 T+1,美股 T+0;港股有午休,外汇周末停摆,数字货币 7×24 不间断。同一个价格数字在不同规则下含义完全不同。
最常见错误:所有市场的价格用同一种样式展示。用户看不出区别,把不同规则下的价格当成同一类信息来理解。
字段 3:price
当前快照价格。
为什么必须定义:这是行情卡片上最显眼的数字------但也是最容易被误用的。最新价不等于"当前可成交价",它只是上一笔成交的快照。在流动性低的品种上,最新价可能已经过时好几分钟。
最常见错误:只给价格不给时间。用户以为看到的是实时价,实际是几秒前的快照。把价格和时间拆开展示,就等于给了用户一个没有保质期的食品。
字段 4:timestamp
这个价格是什么时候生成的。精确到秒,带时区。
为什么必须定义 :这里有一个极易被忽略的技术细节------更新时间必须是交易所生成这条行情的时间,不是你代码收到数据的时间。 这两个时间之间差了几十毫秒到几秒不等。把接收时间当更新时间,跨市场对比时会把不同时间线上的数据硬拼在一起。多市场场景下,所有时间戳都应该带上时区------A 股用 UTC+8,美股用美东时间,数字货币用 UTC。
最常见错误:直接用代码里的当前时间打戳。用户看到"更新于 15:00:05",以为是行情时间,实际是你收到数据的时间。
字段 5:market_status
交易中、已收盘、盘前、盘后、休市、停牌------至少能区分这几个。
为什么必须定义 :这不是"想加一个功能",而是交易所本身的行情数据规范就把市场状态作为标准字段。上海证券交易所 的官方接口文档中,定义了专门的字段来描述市场当前所处状态------开盘集合竞价、连续竞价、休市等。香港交易所的接口中同样有对应字段,取值包括"全日收市""开盘集合竞价时段""持续交易"等。市场状态是交易所官方行情数据不可分割的组成部分。如果面板只取价格和成交量,丢掉了市场状态,那不是"简化",是"丢失信息"。
最常见错误:非交易时段价格照常显示,没有任何"已收盘"标记。用户把昨天下午三点的收盘价当成当前价。
字段 6:error_state
当数据出问题时,面板主动告诉用户。至少覆盖四种情况------无数据、请求失败、字段缺失、时间过旧。
为什么必须定义:异常提示是面板的"健康指示灯"。用户看到空白,会猜"是不是还没加载出来"。但空白的真实原因可能是接口超时、字段缺失、品种停牌、或者这个市场根本没接入。如果面板不主动区分,用户会把猜测当事实。
最常见错误:空数据显示"-",正常负值也显示"-"。用户分不清"没有数据"和"数据是负值"。
三、展示层不要和数据源字段强耦合
上面 6 个字段是你面板的内部数据模型。它不应该等于任何一个数据源的原始返回结构。
原因很简单:不同数据源对同一个概念的字段名、枚举值、数据类型可能完全不同。A 股源的市场状态叫"交易中/已收盘",美股源叫"Regular/After Hours/Pre-Market",外汇和数字货币源可能根本没这个字段。如果展示层直接消费数据源的原始字段,每接入一个新市场就要改一次前端代码。
正确的做法:设计一个与数据源无关的内部数据模型(就是上面那 6 个字段)。所有外部数据进入系统时先做一层转换------把不同源的字段名映射到内部模型,把不同源的枚举值统一成内部状态。前端只消费这 6 个字段,不关心数据从哪来。
这层转换,就是你的行情面板的"数据底盘"。 底盘稳了,上面换数据源、加市场、改样式,都不需要动核心逻辑。
四、多市场最容易踩的 5 类异常状态
多市场会放大每一个细节。下面五类异常,每一类都以具体场景开头。
异常 1:交易时间天生不同
下午两点打开面板,A 股价格在跳,美股一动不动。这是美股在睡觉,不是系统坏了。
A 股上午 9:30 到 11:30,下午 13:00 到 15:00。美股北京时间晚上 9:30 到次日凌晨 4:00,还有夏令时冬令时切换。港股 9:30 到 12:00,13:00 到 16:00。三个市场的时钟,天生不重合。没有 market_status 标记,用户永远分不清"价格不动"是休市还是故障。
异常 2:交易节奏完全不同
周六早上打开面板,BTC 还在跳,EUR/USD 一动不动。用户第一反应不是"周末外汇休市",而是"数据源是不是挂了"。
外汇工作日 24 小时滚动,周末停摆。数字货币 7×24 不间断。两种节奏放在同一面板上,不标状态,用户就把"正常差异"当"系统故障"。
异常 3:symbol 格式没有统一标准
A 股纯数字带 .SH/.SZ。美股字母带 .US。港股数字带 .HK。外汇是货币对。数字货币是代币对。数据源没做统一规范时,同一个品种在列表页、详情页、搜索结果里显示三种写法。用户搜一个代码跳出三个结果,选了其中一个------但结果是港股市场里一个名字近似的标的。面板全程没报错,用户不知道自己盯错了。
异常 4:时间戳语义各说各话
面板上显示的时间,是行情生成时间、服务端处理时间、还是代码收到数据的时间?大部分第一版都没区分。
多市场场景下这个细节被放大:A 股延迟 2 秒,美股延迟 50 毫秒,港股延迟 5 秒。你把三种语义的时间当成同一个时钟排在一起,跨市场对比从一开始就歪了。
异常 5:非交易时段旧价格伪装成实时价
某些数据源在非交易时段不返回空,而是把最后一条收盘价原样推给你。面板不展示 market_status,用户把昨天下午三点的价格当成"最新价"。
这不只是体验问题。全球主要监管机构有一个核心原则:禁止可能导致投资者误判的误导性信息披露。 在非交易时段展示一个没有状态标记的价格,是在特定语境下省略了关键信息。
检验方法:盘后打开面板,看非交易品种的价格旁边有没有状态标记。如果价格还在但没有"已收盘",这个面板就是不可信的。
五、面板跑久了才会暴露的隐蔽故障

上面五类异常,搭过面板的人多少踩过。下面这些,是系统跑了一段时间之后才慢慢浮出来的。
隐蔽故障 1:数据过期了,面板没说。 价格照常跳。主源挂了,备用源补上,但数据新鲜度已经下降,面板没有任何提示。用户以为一切正常,实际看到的是缓存。
隐蔽故障 2:新增一个市场就要改很多代码。 这就是第四节说的"展示层和数据源耦合太深"的后果。A 股的市场状态叫"交易中/已收盘",美股叫"Regular/After Hours/Pre-Market",外汇和数字货币可能根本没这个字段。每接入一个新市场,前端就要改一次状态映射逻辑。解法就是那 6 个字段的内部模型------所有外部数据先标准化,再转换,前端只消费一套枚举值。
隐蔽故障 3:异常被静默处理了。 接口调失败,catch 分支用上一次的缓存填了上去。面板价格照常显示,用户看到的是半小时前的价格,毫不知情。这种现象有一个正式名称------静默数据损坏。数据在存储或传输中发生错误,但系统没检测到,也没发出警告。损坏的数据像正常数据一样继续流动,直到产生一个看似合理但完全错误的结果。
宕机你会知道系统坏了。静默失败会让你相信一个坏掉的系统。
六、一个验证方案:5 个 symbol 跑一天
不管你正准备搭第一版,还是面板已经在跑了,用这个方法花 24 小时测一遍。

| 步骤 | 操作 |
|---|---|
| 第一步 | 选 5 个 symbol:A 股、美股、港股、外汇、数字货币各选一个 |
| 第二步 | 每张卡只展示 6 项信息:symbol、market、price、timestamp、market_status、error_state。不做图表,不做历史数据,不自动刷新 |
| 第三步 | 连续观察 24 小时。只做一件事------任何时候打开这五张卡片,信息都是真实、完整、可理解的 |
| 第四步 | 记录异常。你会看到:下午两点 A 股在更新,美股静止,没标状态的那张卡看起来就像坏了。周末数字货币跳动,外汇卡在周五收盘价。某个品种突然无数据,没异常提示的那版悄无声息地吃掉了信息 |
| 第五步 | 根据观察决定下一步。哪些信息展示正确?哪些被漏掉?哪些异常被静默处理了? |
这里有一个设计理念:6 项信息不是主张"越多越好"。但这 6 项不是冗余------它们是判断一条数据能不能信的最小完备集 。少一项,信任不完整;多一项冗余,增加认知负担。我们追求的,不是一个"大而全"的面板,而是一个 "小而信" 的面板。
七、MVP 检查清单
在面板上线前,逐项确认:
- 6 个核心字段是否全部定义?
symbol/market/price/timestamp/market_status/error_state - 展示层是否只消费内部数据模型,不直接依赖数据源原始字段?
-
timestamp是否带时区?是否明确是行情生成时间而非接收时间? -
market_status是否覆盖交易中、已收盘、休市、停牌? -
error_state是否区分"无数据""请求失败""字段缺失""时间过旧"? - 非交易时段的价格旁边是否有状态标记?
- 空数据("-")和负值在视觉上是否可区分?
- 数据源切换或缓存回退时,面板是否有降级提示?
你的下一步
第一次做行情面板,从 5 张卡片开始,跑通 6 个字段的展示逻辑。如果面板已经跑了很久,用这份 MVP 清单做一次对照检查。
如果你需要一个快速验证的数据入口,TickDB 可以作为候选。TickDB 在字段设计上恰好对齐了上述 6 个字段的需求:symbol 格式统一带市场后缀,时间戳带时区,market_status 字段可读,异常返回结构化错误信息。用 TickDB 跑验证不需要改现有架构------几个 API 调用,五张卡片,24 小时观察。先看看你的面板在真实多市场环境下,哪些信息被正确展示,哪些被漏掉,哪些异常被静默处理。
TickDB 不是唯一选择。具体端点、字段定义和配置方式,以官方文档和你自己的测试结果为准。所有字段和状态枚举都需要你自己跑一遍来确认。
📡 本文行情数据验证示例由 TickDB.ai 提供。本文仅讨论行情面板的数据模型设计与工程实践,不构成投资建议。
标签: 前端, 产品设计, 行情面板, 数据模型, 多市场, TickDB