摘要
把 A 股、港股、美股的 ticker 拉到一张表里算相关性,三个市场的价格看起来规整地排在同一行,但每一列背后的时间坐标完全不同——市场时间决定了拿到的是盘中价还是集合竞价产生的收盘价,数据时间的 timestamp 精度因资产类型而不同,本地接收时间又因为网络延迟和时钟漂移打乱了跨市场事件的先后顺序。本文以 TickDB 作为行情验证入口,拆开这三种时间,给出一套可落地的对齐流程和下游记录字段设计。
你写了一个脚本,把 A 股 600519.SH、港股 700.HK、美股 AAPL.US 的 ticker 拉到同一张表里,标上 datetime.now(),然后算相关系数。
三个月后回测,策略在跨市场价差上的表现和预期差了 1.8 个标准差。你翻出那天的记录表,只有价格和代码。你不知道那条数据是盘中价还是收盘价,不知道 timestamp 是毫秒还是秒,也不知道是正常返回还是补过默认值。
这不是数据量不够,是可观测字段没记。 三只股票,三个市场,三种时间坐标。没对齐就合表,每一行都可能建在错误的基础上。
一、一张表里混进了三种“时间”
| 时间类型 | 回答的问题 | 错了会怎样 |
|---|---|---|
| 市场时间 | 这个价格是盘中价还是收盘价?收盘价是怎么形成的? | A 股收盘价 vs 美股收盘价,形成机制不同,不能当同一类数据对比 |
| 数据时间 | ticker 返回的 timestamp 是什么单位?毫秒还是秒?语义是什么? | 美股 trades 可能是秒级,ticker 是毫秒级,混在一起排序结果无意义 |
| 记录时间 | 这条数据什么时候被你的脚本记录下来的?能否回溯? | 一个月后回看,分不清正常数据、补过的默认值还是异常记录 |
二、市场时间:你拿到的价格是怎么形成的
同一个 UTC 时刻发请求,A 股和港股可能还在交易,美股还没开盘。你拿到的美股价格是前一个交易日的收盘价。三个数写进同一行,被当成了同一个横截面。
更隐蔽的问题在收盘价的形成机制。
| 市场 | 收盘机制 | 本质 |
|---|---|---|
| A 股 | 收盘集合竞价 | 最后三分钟所有人同时出价,系统按最大成交量撮合——一次性集中对决 |
| 港股(非收市竞价) | 最后一分钟多次采样取中位数 | 统计平滑,过滤极端报价——中心趋势而非瞬间价格 |
| 美股(NYSE/Nasdaq) | 收盘竞价,持续公布不平衡信息 | 公开博弈,参与者可反向操作——信息持续消化后的均衡结果 |
把不同形成机制的收盘价直接放在一起算相关性,结论的偏差可能不来自市场,而来自价格形成机制本身的差异。
三、数据时间:同一个 timestamp 字段,不同的生成机制
每个 ticker 返回都有 timestamp。你可能以为它代表“交易发生的时间”。但同一字段名,不同资产类型、不同端点的语义可能不同——股票交易所的 timestamp 可能来自撮合引擎,加密资产的 timestamp 可能是快照生成时刻。
更致命的错误是混淆精度。ticker 的 timestamp 通常是 13 位毫秒,但 recent_trades 在美股上可能返回 10 位秒级时间戳。你把这两个放在一起排序,秒级那条数据会被错位到相邻的时间格上。
精度不等于新鲜度。 一个毫秒级 timestamp 只能说明源头记录得够细,不承诺数据在多少时间内送达你的脚本。
四、记录时间:为什么必须单独记 checked_at
网络延迟不均衡会让事件顺序颠倒。A 股的请求可能几十毫秒返回,跨洋美股链路可能几百毫秒。一个实际上先发生的港股成交,因为网络抖动,可能被排在后发生的美股成交后面。
服务器时钟漂移是另一个隐患。不同区域的服务器 NTP 同步状态不同,本地时间之间的偏差会直接污染排序。
checked_at 是客户端在校验完成后立刻打上的时间戳。 它不替代 payload 里的 timestamp,而是给每条数据附上一个可回溯的身份信息——什么时候被记录的、通过哪个端点拿到的、字段核对是否通过。
五、下游记录表:三种时间分开存
发 ticker 请求之前,先把记录表设计好。以下字段写入每一行:
| 字段 | 类型 | 作用 |
|---|---|---|
symbol | 请求参数 | 600519.SH |
market | 客户端填写 | A 股 / 港股 / 美股 |
endpoint | 客户端填写 | 调用的数据端点 |
payload_timestamp | ticker 返回 | 原始 timestamp,保留单位,不自行转换 |
checked_at | 客户端生成 | 字段核对完成时刻 |
note | 自动或手动 | 字段核对通过 或异常原因(data 为空 / timestamp 类型异常) |
last_price | ticker 返回 | 接口返回的字符串值(不在此展示) |
anomaly_flag | 自动 | note 非“通过”时置 1,下游可据此过滤异常数据 |
last_price为字段占位说明,不构成实时报价展示。timestamp 精度不等于行情新鲜度、延迟或 SLA。
六、验证清单
选 A 股、港股、美股各一个你真正会用的 symbol,逐项执行:
- 确认三个 symbol 对应三个市场(如
600519.SH/700.HK/AAPL.US) - 查每个市场当前交易状态,明确价格处于盘中还是收盘
- 理解各市场收盘价形成机制的差异
- 对每个 symbol 发 ticker 请求,记录
symbol、last_price、timestamp - 核
timestamp单位,不跨资产类型假设统一 - 将
market、symbol、endpoint、payload_timestamp、checked_at、note、anomaly_flag写入记录表 - 异常记录不静默跳过,
anomaly_flag置 1
七、诚实边界
- timestamp 精度不等于数据新鲜度、延迟或 SLA。不同资产类型、不同端点的 timestamp 语义可能不同,需分别核对。
- 一次 ticker 查询通过只证明本次路径可复核,不证明全市场、全端点可用。
- MCP、REST 和 WebSocket 是各自独立的命名空间,本文讨论 REST ticker 的字段核对,不能外推到其他通道。
- 各市场收盘机制描述基于公开规则,具体以各交易所最新官方文件为准。
- 本文不讨论投资策略、收益预测或买卖建议。
八、下一步
600519.SH、700.HK 和 AAPL.US 只是帮你确认验证流程。接下来:
- 换上你自己关注的品种,理解每个市场的交易时段和收盘价形成机制。
- 对每个 symbol 发 ticker 请求,核对 timestamp 的单位和语义。
- 把
market、symbol、endpoint、payload_timestamp、checked_at、note、anomaly_flag写进记录表——三种时间分开存。 - 查阅 TickDB 官方文档(
https://docs.tickdb.ai)了解 REST 和 WebSocket 的适用场景。
标签:A 股港股美股 / 跨市场合表 / 数据对齐 / timestamp / checked_at / TickDB / 火山引擎
📡 本文行情数据示例由 TickDB.ai 提供 ⚠️ 本文仅讨论多市场行情数据的工程接入方法,不构成任何投资建议
