盘口 depth API 接上就能用?我先用一次真实调用验了 bids、asks 和时间
由bqawy3j1创建,最终由bqawy3j1 被浏览 4 用户
摘要:盘口数据、order book、bids/asks、depth API 看起来很直观:买盘一列、卖盘一列,再加一个时间戳,好像拿到就能塞进行情看板或研究脚本。但真正接入前,第一步不是判断买盘强不强,而是证明这张盘口快照能被程序解释:返回的是不是你请求的 symbol,bids 和 asks 是否有明确方向,价格排序是否符合契约,timestamp 能不能复查,raw response 有没有留下。本文用 TickDB 的一次真实 REST depth 调用,跑通一条最小验收链路。

这篇文章解决什么问题
很多人第一次接盘口 API,会先看两件事:有没有 bids,有没有 asks。有了,就觉得“盘口数据接上了”。
但工程里真正麻烦的地方,从来不是 JSON 里有没有这两个字段,而是这两个字段能不能被系统稳定解释。bids 里的第一档到底是不是最优买价?asks 里的第一档到底是不是最优卖价?每一档的结构是什么?排序对不对?timestamp 代表什么时间口径?这次返回的 raw response,后面还能不能拿出来复盘?
盘口数据进入系统前,先别急着谈信号。先证明它是一张合格的、可解释的、可留痕的盘口快照。
\
本文的核心方法论
这篇文章只做一件事:用一次真实 depth 请求,看 TickDB 返回了什么,再用代码验 bids、asks、排序和时间。全文的逻辑结构是——
是什么:一张合格的盘口快照,必须包含 symbol、timestamp、bids(降序)、asks(升序)和原始返回。这五样东西,缺任何一样,盘口快照就无法被程序稳定解释。
为什么:bids 排序错了,最优买价就不是第一档;asks 排序错了,最优卖价就不是第一档;timestamp 缺失或语义不清,快照就没有时间坐标;raw response 没保存,出问题后无法复盘。这四个问题,每一个都能让盘口展示变成误导。
怎么样:用一次真实 REST depth 调用,跑通请求 → 原始返回 → 字段和排序校验 → 可用快照四道证据门。每一步都配真实终端截图、代码片段和检查结论。最后给一张六项检查表,你可以直接拿去验自己的盘口数据源。
\
读完你能拿走什么
- 一条盘口快照的最小验收链路:请求、原始响应、排序校验、时间戳核对、留痕。
- 一份可直接运行的校验代码骨架,验 bids 降序、asks 升序、timestamp 可解释。
- 一张六项检查表,每次接入新数据源或切换品种时直接对照。
- 一套“能证明什么、不能证明什么”的边界声明,帮你区分字段验收、交易信号和生产稳定性。
\
一、本次真实调用:600519.SH 的 REST depth 快照
本次使用 TickDB REST API 调用。endpoint 为 GET https://api.tickdb.ai/v1/market/depth,REST 鉴权使用 X-API-Key,参数 symbol=600519.SH、limit=5,本地 checked_at 为 2026-07-13T23:33:15+08:00。
图中是本次真实调用的终端输出。API Key 已脱敏,价格、数量和 timestamp 来自本次返回样本。该图只证明本次 600519.SH 的一次 REST depth 快照可被脚本解析和校验,不代表交易信号、延迟、SLA 或所有市场表现。
本次返回的核心字段如下:
| 检查项 | 本次样本 |
|---|---|
| symbol | 600519.SH |
| type | stock |
| timestamp | 1783927855001 |
| timestamp 北京时间换算 | 2026-07-13T15:30:55+08:00 |
| bids 档位数 | 5 |
| asks 档位数 | 5 |
| best bid | 1210.99 |
| best ask | 1211 |
| 本地计算 spread | 0.01 |
| 校验结果 | PASS |
前三档样本:
| side | 第1档 | 第2档 | 第3档 |
|---|---|---|---|
| bids | ["1210.99","8"] | ["1210.98","1"] | ["1210.95","2"] |
| asks | ["1211","84"] | ["1211.03","1"] | ["1211.08","1"] |
注意:spread=0.01 不是接口原始字段,而是本地用 best_ask - best_bid 算出来的检查值。写系统时,这类本地派生字段要和原始返回字段分开存,别混在一起。
\
二、一张盘口快照,至少要过四个证据门

第一道门是请求。 你要知道自己请求了哪个 symbol,用了几档 limit,走的是哪个 endpoint,鉴权方式是什么。
第二道门是 raw response。 只看处理后的表格不够,原始 JSON 必须保存。以后发现盘口展示异常,能不能回到原始返回,是排查效率的分水岭。
第三道门是校验。 bids 和 asks 不是普通数组,它们有方向:bids 应按价格降序排列,asks 应按价格升序排列,每一档都应能解析成价格和数量,timestamp 应是可解释的毫秒时间戳。
第四道门才是可用快照。 前面三步过了,这张快照才适合进入行情看板、字段验收、落库或后续研究。
请求成功只是入口。能解释、能校验、能留痕,才是接入的开始。
\
三、bids 和 asks 的排序,最好用代码验,不要靠眼睛看
盘口表格很容易让人产生一种错觉:肉眼看起来顺着排,就没问题。但工程里不能靠肉眼。因为一旦排序错了,最优买价可能不是第一档,最优卖价可能不是第一档,本地计算的 spread 会错,行情面板上展示的盘口状态会错,入库后再排查会很难定位。

下面是本次真实 runner 中的请求片段。它从环境变量读取 API Key,用 REST 的 X-API-Key 调用 /v1/market/depth,不把 Key 写进代码或截图。
import json
import os
import time
import urllib.parse
import urllib.request
\
API_URL = "https://api.tickdb.ai/v1/market/depth"
SYMBOL = "600519.SH"
LIMIT = 5
\
def fetch_depth():
api_key = os.getenv("TICKDB_API_KEY")
if not api_key:
raise EvidenceError("TICKDB_API_KEY is not set")
params = {"symbol": SYMBOL, "limit": str(LIMIT)}
query = urllib.parse.urlencode(params)
url = f"{API_URL}?{query}"
request = urllib.request.Request(
url,
headers={
"X-API-Key": api_key,
"User-Agent": "TickDB-PA02-depth-evidence/1.0",
"Accept": "application/json",
},
)
started = time.perf_counter()
with urllib.request.urlopen(request, timeout=20) as response:
status = response.status
body = response.read().decode("utf-8")
elapsed_ms = round((time.perf_counter() - started) * 1000, 1)
return status, elapsed_ms, params, json.loads(body)
拿到 payload 后,再进入字段和排序校验。下面是本次真实 runner 中用于校验盘口数组的核心代码。完整脚本路径见文末编辑卡,公开代码中不包含 API Key。
from decimal import Decimal, InvalidOperation
\
class EvidenceError(Exception):
pass
\
def parse_level(level, side, index):
if not isinstance(level, list) or len(level) != 2:
raise EvidenceError(f"{side}[{index}] must be [price, quantity]")
try:
price = Decimal(str(level[0]))
quantity = Decimal(str(level[1]))
except (InvalidOperation, ValueError) as exc:
raise EvidenceError(f"{side}[{index}] price/quantity is not decimal: {level}") from exc
if not price.is_finite() or not quantity.is_finite():
raise EvidenceError(f"{side}[{index}] has non-finite value: {level}")
if price <= 0 or quantity < 0:
raise EvidenceError(f"{side}[{index}] has invalid price/quantity: {level}")
return {"price": price, "quantity": quantity}
\
def validate_book(payload, symbol):
if payload.get("code") != 0:
raise EvidenceError(f"business code is not 0: {payload.get('code')}")
data = payload.get("data")
if not isinstance(data, dict):
raise EvidenceError("data must be object")
if data.get("symbol") != symbol:
raise EvidenceError(f"symbol mismatch: request={symbol} response={data.get('symbol')}")
timestamp = data.get("timestamp")
if not isinstance(timestamp, int) or len(str(timestamp)) != 13:
raise EvidenceError(f"timestamp should be 13-digit milliseconds: {timestamp}")
bids = data.get("bids")
asks = data.get("asks")
if not isinstance(bids, list) or not bids:
raise EvidenceError("bids must be non-empty array")
if not isinstance(asks, list) or not asks:
raise EvidenceError("asks must be non-empty array")
parsed_bids = [parse_level(level, "bids", i) for i, level in enumerate(bids)]
parsed_asks = [parse_level(level, "asks", i) for i, level in enumerate(asks)]
bids_desc = all(
parsed_bids[i]["price"] >= parsed_bids[i + 1]["price"]
for i in range(len(parsed_bids) - 1)
)
asks_asc = all(
parsed_asks[i]["price"] <= parsed_asks[i + 1]["price"]
for i in range(len(parsed_asks) - 1)
)
if not bids_desc:
raise EvidenceError("bids are not sorted by price descending")
if not asks_asc:
raise EvidenceError("asks are not sorted by price ascending")
best_bid = parsed_bids[0]["price"]
best_ask = parsed_asks[0]["price"]
if best_ask < best_bid:
raise EvidenceError(f"best ask is lower than best bid: bid={best_bid}, ask={best_ask}")
return {
"best_bid": str(best_bid),
"best_ask": str(best_ask),
"spread": str(best_ask - best_bid),
"bids_descending": bids_desc,
"asks_ascending": asks_asc,
}
这段代码有一个原则:遇到解释不了的字段,直接失败,不要用默认值糊过去。 例如 bids 不是数组就失败,某档不是 [价格, 数量] 就失败,price 或 quantity 不能转成数字就失败,timestamp 不是 13 位毫秒时间戳就失败,bids 排序不对就失败,asks 排序不对就失败。
这不是吹毛求疵。盘口数据如果连“第一档是谁”都不能稳定解释,就不应该继续往行情面板或数据库里送。
\
四、timestamp 的意义:它让快照可以被复查
本次返回里的 timestamp 是 1783927855001,换算成本地时间是 2026-07-13T15:30:55+08:00。
这个字段的价值,不只是“显示一个时间”。它让你能把三件事分开:接口返回快照中携带的时间字段、你本地运行校验脚本的时间、raw response 落盘的时间。这三者不要混用。尤其是做行情展示时,本地 checked_at 只能说明你什么时候检查了这份数据,不能替代接口返回里的 timestamp;本次文章也不把这个字段外推为交易所事件时间、端到端延迟或数据新鲜度承诺。
在本文这次证据里:timestamp 来自 TickDB 返回,checked_at 是本地脚本记录,spread 是本地根据 best bid / best ask 派生,raw response 已脱敏保存,方便之后复盘。
这就是“可留痕”的意义:不是为了把文章写得更严谨,而是为了出了问题还能追得回来。
\
五、TickDB 在这件事里解决哪一层
TickDB 在本文里的角色不是“告诉你盘口要涨还是要跌”,也不是证明某个盘口信号有效。它解决的是更前置的一层:给你一个可以程序化请求、可以解释字段、可以保存原始返回的 depth 数据入口。
官方文档里,TickDB 的 depth 接口使用 GET /v1/market/depth,返回字段包括 symbol / timestamp / bids / asks,其中 bids 和 asks 都是 [价格, 数量] 这种结构。对开发者来说,这比“页面上能看到盘口”更重要,因为你的系统可以围绕这些字段写校验、日志和失败分支。
如果你要做的是行情看板的盘口展示、order book 快照入库、盘口字段验收、AI 工具或研究脚本里的行情取数、多市场行情数据入口的初步验证,那 TickDB 适合作为候选的数据入口之一。它的核心价值不是让你少写一行请求,而是把多市场 symbol、REST/WebSocket/MCP 等入口、结构化字段和时间戳口径放在一套体系里,便于你做工程化验收。
但接入责任仍然在你这边。 你仍然要决定:raw response 保存在哪里,校验失败要不要阻断入库,本地派生字段如何标记,行情看板如何展示 stale / unavailable,后续要不要接 WebSocket 持续更新。
\
六、最小检查表:depth 返回进系统前先验这 6 项
| 检查项 | 要问什么 | 本次做法 |
|---|---|---|
| 请求对象 | 返回的是不是我请求的 symbol | 校验 data.symbol == 600519.SH |
| 时间字段 | timestamp 是否存在且可解释 | 校验 13 位毫秒时间戳 |
| bids 结构 | 买盘是否为非空数组 | 校验每档为 [price, quantity] |
| asks 结构 | 卖盘是否为非空数组 | 校验每档为 [price, quantity] |
| 排序 | bids 降序、asks 升序是否成立 | 用 Decimal 比较价格 |
| 留痕 | 原始返回和检查时间是否保存 | 保存 raw、summary、transcript |
这张表不复杂,但它能拦住很多后续问题。 你不需要一开始就设计一个庞大的数据质量平台。先把一张盘口快照验清楚:对象、时间、买盘、卖盘、排序、raw。能过,再谈展示;过不了,就别入库。
\
七、FAQ
Q1:有了 bids/asks,是不是就等于拿到了可用盘口?
不等于。bids 和 asks 只是字段名。可用盘口至少还要确认字段结构、排序、时间戳和 raw 留痕。本次脚本就是为了把“看到两列数组”升级成“这张快照能被程序解释”。
Q2:这篇文章是不是在判断盘口信号?
不是。本文不讨论盘口是否能预测价格,也不讨论交易策略。它只讨论接入前的字段验收:一张 depth 快照能不能被解释、校验和复查。
Q3:TickDB 在这个问题里解决哪一层?
TickDB 在本文中提供的是 REST depth 数据入口:用一次请求拿到 symbol/timestamp/bids/asks 这类结构化返回,再由你的系统做排序校验、异常处理和留痕。放到本文这个场景里,最直接的价值就是:先让盘口快照有一条可请求、可校验、可回看的工程入口。
Q4:这次 600519.SH 的样本能证明所有市场都可用吗?
不能。它只能证明本次真实请求下,600519.SH 的一次 REST depth 快照返回并通过字段校验。其他 symbol、其他市场、其他时段仍然需要按同样方法独立验证。
\
最后
盘口数据最容易让人过早兴奋。因为它看起来比单个价格更“专业”:有买盘,有卖盘,有档位,有数量。但真正进入系统前,你要先把兴奋压住。
先问四个问题:这是不是我请求的对象?买盘和卖盘的方向对不对?排序能不能被代码证明?原始返回能不能留下来复查?这四个问题答不清,盘口展示得再漂亮,也只是一个不可靠的界面。
盘口 depth API 接上,只是第一步。能解释、能校验、能留痕,才是它进入工程流程的门槛。
参考资料:TickDB Docs https://docs.tickdb.ai/zh-Hans/rest/api_depth ,TickDB 官方 GitHub https://github.com/TickDB/tickdb-unified-realtime-marketdata-api
本文只讨论盘口 depth API 的字段验收、排序校验与工程留痕,不构成任何投资建议,也不证明盘口信号或策略有效性。接口路径、字段语义与可用范围以官方文档和真实调用为准。