股票行情API怎么选?从报价看板需求到Python样本检查

用户头像Jacktick
2026-11-10 发布

摘要:面向参与股票报价看板交付的产品与开发人员,本文把“接入实时行情”拆成页面功能、数据口径和验收条件,说明报价、K线、盘口与成交明细各自何时需要。结合一份TickDB美股实际返回,给出数据需求表、样本获取步骤、完整Python检查程序和运行结果,帮助团队在开发界面之前确认数据是否支持已承诺的功能。

做一个股票报价看板,最先接通的往往是价格:请求成功,页面也出现了数字。

继续开发时,问题会逐渐变具体:涨跌幅相对哪个价格?休市后保留什么状态?盘口和成交记录的时间为什么与主报价不同?历史K线、逐笔成交和扩展交易时段,是否都要放进首版?

这些问题需要产品和技术共同确定。接口清单只告诉我们能请求什么;交付还要明确页面展示什么、采用什么口径,以及数据不足时怎样回应。

一个实用的顺序是:先定页面功能,再选数据,最后写验收条件。下面以美股自选报价看板为例,完成一份数据需求表,再用保存的真实返回做一次本地结构检查。

一、先给首版划定范围

本文的产品需求是构造案例:首版展示自选股票身份、所选交易时段的价格与涨跌,支持持续更新和数据过期提示;示例先选择常规交易时段,暂不提供盘口分析、成交明细、扩展时段切换和历史研究。

如果你的产品以历史走势或买卖价差为主要功能,相应数据就应进入首版。优先级取决于用户要完成的任务。

把“实时行情”拆成下面四项,开发任务会更明确:

需求 需要写清的内容
对象 目标市场、完整自选清单、代码和名称的对应关系
口径 价格属于哪个时段,涨跌相对哪个参考值
更新 目标时段内,什么条件下认定数据过期
异常 证券不存在、没有权限、字段缺失或连接中断时的页面行为

例如,“接上WebSocket”是一项实现任务;“目标时段内持续更新,更新停止后显示过期状态”是一项产品验收要求。两者需要通过应用逻辑连接起来。

image.png

图1:AI方法示意图。不同功能需要不同数据,历史、盘口或成交是否进入首版,由本次需求决定。

二、报价、K线、盘口与成交分别支持什么功能

1. 报价展示:身份、时间和参考值一起处理

首版报价列表至少需要建立证券身份、市场、币种与价格之间的明确关系。名称和币种可以来自目录或参考资料,报价响应则按自己的字段契约核对。

涨跌幅也需要有参考值。TickDB报价文档说明,除核心报价字段外,其他字段会根据产品、时段及可用性按条件返回。某条样本返回参考昨收和涨跌幅,不代表每只股票、每个时段都必然返回。

字段缺失时,界面应显示未提供或暂不可用。填成零涨跌会改变信息含义。如果自己计算涨跌幅,还要确认价格和参考值的时段与统计口径匹配。

时间至少保留两类:行情时间和接收时间。前者属于市场记录,后者属于程序获取过程。过期判断还需要交易时段规则:休市后保留最后一条目标时段报价,可以是正常状态;目标时段内停止更新,则需要明确提示。

2. 历史走势:先确定区间和周期

要展示历史曲线,就需要相应周期与范围的K线,并约定复权方式、缺失记录和未结束周期的处理。

当前报价功能不必因为接口提供多年历史而提前建设回测模块。即使曲线已经画出,是否适合回测仍涉及历史证券样本、数据版本和研究设计,需要另行判断。

3. 盘口:用于观察可见买卖报价

最新成交价描述已经发生的交易;盘口描述返回时可见的买卖报价及数量。观察价差需要对应买卖报价,观察价格层级时才进一步需要相应深度。

页面应按实际返回档数展示,处理单侧为空和档数不足。可见挂单可能变化,不能把静态盘口显示为保证可成交的价格和数量。

4. 成交明细:先约定记录范围

最近成交接口提供的是一个记录窗口。返回三条或一百条,不代表已经取得整天成交历史。

如果功能承诺连续记录,就需要进一步设计持续接收、断线处理、去重和缺口检查。反复刷新最近记录,不能直接作为完整归档的验收依据。

三、把功能选择写成数据需求表

下面是本文假设看板的填写示例。它用于需求与开发交接,尚不是已上线系统的验收报告。

功能与优先级 必要数据 可后加能力 验收方法
证券识别:首版 代码、名称、市场、币种及映射 跨市场搜索 逐项核对完整自选清单,检查代码与单位
价格展示:首版 目标时段价格和行情时间 扩展时段切换 价格、时间和时段标签采用同一对象
涨跌展示:首版 匹配口径的涨跌字段或计算基准 更多统计指标 核对参考值;缺失不填零
更新与异常状态:首版 更新记录、行情时间、接收时间和错误状态 增强恢复机制 测试目标时段更新及中断后的过期提示
历史走势:本示例后加 目标周期的K线 更多周期与研究工具 核对范围、复权、缺失及周期完成状态
盘口或成交:本示例后加 与选定功能匹配的买卖报价或成交记录 深度分析或连续归档 检查实际档数、记录范围、时间、数量单位与空态

这张表还应附上目标账户、预期负载和使用对象。内部研究、内部看板和客户展示的使用条件分别确认。目录里能找到证券,也不代表当前账户已经拥有所有相关数据权限。

后加功能如果进入首版,它的数据与异常处理也要一起进入验收范围。

四、先取真实样本,再开始写字段映射

本文使用TickDB提供的股票数据,通过已经连接的MCP取得一份美股样本。MCP适合这里的按需查询;本文没有用它验证持续推送,也没有在本例重新运行REST或WebSocket。

2026年11月10日,先从US股票目录核对Apple身份,再对AAPL.US分别查询报价、盘口与最近三条成交。目录中的代码为AAPL,报价工具使用AAPL.US;关联时同时核对市场与工具的代码规范。

实际返回摘要如下,未展示行情价格值:

模块 返回结构 数据时间,UTC
主报价 包含证券代码、价格、参考昨收、涨跌幅及时间字段 2026-11-09 21:00:01
盘口 买侧1档、卖侧1档 2026-11-10 04:01:56.484
最近成交 请求3条,返回3条,记录标签为overnight 2026-11-10 04:00:42至04:01:51

取数记录位于2026年11月10日UTC 04:01这一分钟。这是几次独立查询,不是同一时刻的原子快照,也不用于计算端到端延迟。

报价响应还包含扩展时段对象。页面若选择常规时段,就需要核对所选字段与时段要求是否一致;以后增加夜盘,必须同时处理夜盘价格、时间和标签。不能只选一个更晚的时间,配上另一个对象的价格。

在自己的MCP客户端取得输入文件

前提是客户端已经连接TickDB MCP,并配置了自己的有效凭证。密钥留在本地配置中,不放进下面的任务文本。

先调用get_available_symbols,在US股票目录中确认Apple。
可使用market="US"、type="stock"、limit=1000、offset=0;
如果目标不在这一页,按实际分页继续查找,不能视作不支持。

随后查询AAPL.US:
1. get_ticker:symbols="AAPL.US",type="stock";
2. get_order_book:symbol="AAPL.US",type="stock";
3. get_recent_trades:symbol="AAPL.US",type="stock",limit=3。

将工具返回的完整业务JSON(包含code、message、data),分别保存为
ticker_raw.json、depth_raw.json、trades_raw.json,并另记取数时间。
不要保存客户端界面截图或带text/content包装的展示文本来替代业务JSON。
失败时保留实际错误,不补造成功文件。

样本结构可用于检查字段映射。完整标的清单、持续更新、页面过期状态、账户等级和客户展示条件,本例没有验证,需要按需求表继续完成。

五、用完整Python程序检查保存的JSON

环境与文件布局

需要Python 3.10或以上版本,只使用标准库。程序不联网,不需要API Key,也不会输出行情价格。它读取三个保存文件,检查业务状态、证券一致性和必需报价字段,再整理各模块的结构与时间。

文件放在同一目录:

quote-api-check/
├── check_sample.py
├── ticker_raw.json
├── depth_raw.json
└── trades_raw.json

将下面代码保存为check_sample.py:

"""Python 3.10+; inspect saved TickDB MCP payloads, without network calls."""
import csv
import json
from datetime import datetime, timezone
from pathlib import Path


def read_payload(filename):
    payload = json.loads(Path(filename).read_text(encoding="utf-8-sig"))
    if payload.get("code") != 0:
        raise ValueError(f"Unsuccessful API response: {filename}")
    return payload["data"]


def utc(value):
    if type(value) is not int or value < 0:
        raise ValueError("Expected a nonnegative millisecond timestamp")
    return datetime.fromtimestamp(value / 1000, timezone.utc).isoformat()


def main():
    symbol = "AAPL.US"
    quotes = read_payload("ticker_raw.json")
    matching = [row for row in quotes if row.get("symbol") == symbol]
    if len(matching) != 1:
        raise ValueError("Expected exactly one matching quote")
    quote = matching[0]
    book = read_payload("depth_raw.json")
    tape = read_payload("trades_raw.json")
    if book.get("symbol") != symbol or tape.get("symbol") != symbol:
        raise ValueError("The payloads refer to different symbols")
    required = ("last_price", "timestamp")
    if any(quote.get(key) is None for key in required):
        raise ValueError("Missing a required quote field")
    bids, asks, trades = book["bids"], book["asks"], tape["trades"]
    times = [row["timestamp"] for row in trades]
    rows = [
        ["quote", symbol, "required_fields_present", utc(quote["timestamp"])],
        ["depth", symbol, f"bids={len(bids)};asks={len(asks)}", utc(book["timestamp"])],
        ["trades", symbol, f"rows={len(trades)}",
         f"{utc(min(times))} to {utc(max(times))}" if times else "empty"],
    ]
    with Path("sample_check.csv").open("w", newline="", encoding="utf-8-sig") as file:
        writer = csv.writer(file)
        writer.writerow(["module", "symbol", "observed_structure", "data_time_utc"])
        writer.writerows(rows)
    for row in rows:
        print(" | ".join(row))
    print("Saved sample_check.csv; structure check only, not release approval")


if __name__ == "__main__":
    try:
        main()
    except (OSError, ValueError, TypeError, KeyError) as error:
        raise SystemExit(f"STOP: {error}")

运行方式与实际输出

在上述目录运行:

python3 check_sample.py

使用本文2026年11月10日保存的样本,本地运行输出为:

quote | AAPL.US | required_fields_present | 2026-11-09T21:00:01+00:00
depth | AAPL.US | bids=1;asks=1 | 2026-11-10T04:01:56.484000+00:00
trades | AAPL.US | rows=3 | 2026-11-10T04:00:42+00:00 to 2026-11-10T04:01:51+00:00
Saved sample_check.csv; structure check only, not release approval

sample_check.csv使用UTF-8 BOM编码保存,便于Excel或WPS打开。使用自己的新样本时,数量和时间应以实际返回为准,不要求复现上面的数值。

程序还有两个停止条件:业务响应失败时输出STOP: Unsuccessful API response...;盘口或成交指向另一只证券时输出STOP: The payloads refer to different symbols。这两个错误分支已用单独的负向测试输入检查,未修改原始行情文件。

怎样理解检查结果

required_fields_present表示程序要求的字段在样本中存在。它不判断市场数据是否正确,不校验参考昨收的业务口径,也不会自动认定数据属于页面要求的交易时段。

同样,盘口每侧1档、成交3条,仅是本次观察。程序没有检查连续运行、成交完整性或页面异常状态,不能把CSV生成成功当成上线验收完成。

image.png

图2:AI方法示意图。样本结构检查之后,还要按目标时段、正常与异常状态继续验收。

六、开始开发前,留下一个可共同核对的交付依据

完成这一步,应能交出三份材料:填好的功能与数据需求表、保留时间及条件的真实样本、可逐项执行的验收清单。

需求表解释为什么要这类数据;样本帮助开发者看到实际字段与返回范围;验收清单说明更新正常、停止或缺失时应发生什么。首版是否完成,由这三份材料共同判断。

可以先挑一个已经承诺的功能,把它的数据、时段、缺失行为和验收方法写完整。接口、权限及后续数据模块,就能围绕具体任务来选择。

代码与接入参考

TickDB的公开工具仓库包含MCP服务端实现与Skill接入资料,适合在复现查询或检查客户端配置时参考:

https://github.com/TickDB/tickdb-unified-realtime-marketdata-api

仓库中的mcp/用于MCP服务端与接入参考,SKILL/包含对应的工具说明。本文的check_sample.py完整代码见第五节;仓库链接用于接入资料,不表示本文程序或样本已收录到仓库。公开工具代码的许可与行情数据使用权限应分别确认,实际数据调用仍需相应凭证和权限。

资料日期:2026年11月10日。行情样本来自当日TickDB MCP调用;GitHub仅作工具与接入参考。产品需求为构造案例,使用条件按目标市场、账户和用途确认。

评论