休市提醒日股将于 2026-11-03 休市(文化日),距今天还有 5 天。全部公告
文章

行情 API 计费模型对比:WebSocket 流式为何比 REST 轮询更省

实时行情是推送型负载,不是查询型负载。本文用 500 个标的的真实数字,算清 REST 轮询与 WebSocket 流式的成本差异,并解释为什么按消息计费在实时场景里会失控。

选行情数据 API 时,大多数团队第一眼看单价:每百万次请求多少钱。但对实时行情场景来说,计费模型对总成本的影响远大于单价本身。原因不复杂——实时行情是持续推送型负载,不是查询型负载。用查询型的计费模型去承载推送型的负载,成本会随标的数量和时间双重膨胀。

两种计费模型,两种命运

市面上的计费方式基本分两类:

  • 按请求计费:每次 HTTP 调用消耗一次额度。适合历史数据拉取、定时快照、低频查询。
  • 按消息计费:WebSocket 每推送一条 tick 计一次费用。标的越多、行情越活跃,消息量增长越陡。

问题在于:不少平台把流式推送也做成按条计费。而实时行情的消息量,天生就是天文数字。

算一笔账:500 个标的的 REST 轮询成本

假设你要监控 500 个标的,要求秒级刷新。

TIQEX 的 多市场行情接口 单次最多支持 50 个 codes,因此一轮完整轮询需要 10 次请求:

  • 10 次请求/秒 × 86,400 秒 = 864,000 次/天
  • 月度约 2,592 万次请求

这个数字意味着什么?对照 套餐额度:Growth 每月 50 万次,Pro 每月 500 万次——秒级轮询 500 个标的,连 Pro 的额度都不够。

同样 500 个标的,换成 WebSocket 是多少

  • 1 条 WebSocket 连接订阅 500 个标的
  • 假设每个标的平均每秒 2 条 tick → 1,000 条消息/秒
  • 月度约 25.9 亿条消息

现在把这个数字乘以你供应商的每消息单价。即使单价低到每百万条 $0.5,月账单也超过 $1,300;若单价是每百万条 $5,月账单就是 $12,960——而这只是 500 个标的。上千标的的组合监控,成本会直接失控。

关键在于:标的数量是业务需求,不会因为你的预算而减少。 所以按消息计费在实时行情场景里,是一个会持续恶化的成本结构。

握手计费:唯一不会失控的成本结构

这正是 TIQEX 采用「握手计入额度、推送不计费」的原因:

  • WebSocket 建连握手计入每日额度与每分钟速率(RPM)
  • 握手之后的 tick 推送 不按条计费
  • 因此 500 个标的和 5,000 个标的,流式成本几乎恒定

换句话说:标的是可扩展的,成本不是。

两种模型各用在哪

场景推荐模型原因
实时监控、交易终端、告警WebSocket 流式持续推送,握手计费后成本恒定
历史 K 线回填、回测数据准备REST 查询一次性批量拉取,请求数可控
低频快照(分钟级 / 小时级)REST 查询请求量小,实现简单
上千标的组合监控WebSocket 流式REST 轮询成本会击穿任何套餐

TIQEX 的定价页把这条原则写得很直白:Use WebSocket for live ticks; REST for queries and backfill.

延迟:另一个被忽略的差异

成本之外,两种模型在延迟上的差异同样明显。

REST 轮询的延迟由两部分构成:轮询间隔 + 网络往返时间。秒级轮询意味着平均延迟 500ms(最坏 1,000ms),再加上每次请求的 RTT。对分钟级决策这无所谓,但对做市、套利、实时告警这类场景,500ms 已经足够让信号失效。

WebSocket 是服务端主动推送:行情一有变化立即下发,延迟只由服务端到客户端的网络路径决定,不必为等待下一次轮询付出额外代价。TIQEX 官方标注的数据延迟为 78ms。

换句话说,流式方案不只是更省,还更快——而这两个优势来自同一个设计决策。

用 Python 先验证你的用量结构

在选套餐之前,先算清楚你的真实请求量。下面这段脚本按接口的批量上限反推月消耗:

Python
import math

symbols = 500
batch_size = 50        # /api/v1/market/quote 单次最多 50 个 codes
interval_sec = 1       # 秒级刷新

requests_per_poll = math.ceil(symbols / batch_size)
per_day = requests_per_poll * (86400 // interval_sec)
per_month = per_day * 30

print(f"每轮请求数: {requests_per_poll}")
print(f"每日请求数: {per_day:,}")
print(f"每月请求数: {per_month:,}")
# 每轮请求数: 10
# 每日请求数: 864,000
# 每月请求数: 25,920,000

把 symbols 改成你的真实标的数,就能立刻看出 REST 轮询是否可行。如果月请求量已经超过套餐额度,正确的解法不是升级套餐,而是换成流式订阅。

从 REST 轮询迁移到流式:三步

迁移本身比想象中简单。以 Python 为例,用 websockets 订阅 TIQEX 的流式端点:

Python
import asyncio, json, os
import websockets

API_KEY = os.environ["TIQEX_API_KEY"]
SYMBOLS = ["BTCUSDT", "ETHUSDT", "AAPL", "EURUSD"]

async def main():
    async with websockets.connect(
        "wss://api.tiqex.io/api/v1/market/stream",
        additional_headers={"X-API-Key": API_KEY},   # websockets < 14 请用 extra_headers
    ) as ws:
        await ws.send(json.dumps({
            "action": "subscribe",     # 首条消息必须是 subscribe
            "market": "crypto",
            "symbols": SYMBOLS,
        }))
        async for raw in ws:
            frame = json.loads(raw)
            if not frame.get("succ"):
                print("error:", frame.get("code"), frame.get("msg"))
                continue
            data = frame["data"]
            if data.get("type") == "subscribed":
                print("subscribed:", data.get("symbols"))
            elif data.get("type") == "tick":
                tick = data["tick"]
                print(tick["symbol"], tick["last"], tick["at"])

asyncio.run(main())

三个关键点:

  1. 首条消息必须是 subscribe,并带上 market 与 symbols。符号数量受套餐上限约束。
  2. 订阅成功后会先收到一条 type=subscribed 的确认帧,之后才是连续的 type=tick 数据帧。生产代码应等确认帧到达后再开始处理业务。
  3. 鉴权用 X-API-Key 头(也接受 Authorization: Bearer)。WebSocket 与 REST 共用同一套密钥。

完整的订阅协议、字段定义与错误码见 WebSocket 流式接口文档;REST 与流式在语义上的差异可参考 轮询与流式对比。

迁移到流式的检查清单

  1. 确认套餐权限:不同套餐开放的市场不同。实时行情需要对应套餐,否则会返回 MARKET_NOT_ENABLED(403)。
  2. 检查 delayed 标志:REST 响应里的 delayed 字段为 true 表示该市场当前是延迟数据。生产环境务必校验这个字段。
  3. 实现心跳与重连:长连接必须有重连与退避策略,参见 WebSocket 实时报价指南。
  4. 区分握手与推送的额度影响:握手计入额度,所以不要用频繁重连来「刷新」连接。
  5. 处理 429:DAILY_LIMIT_EXCEEDED、MONTHLY_LIMIT_EXCEEDED、RATE_LIMIT_EXCEEDED 都返回 429,需要区分处理。
  6. 先用工具估算:配额计算器 可以快速试算不同标的规模下的额度需求。

怎么确认迁移成功

切换完成后,用三个信号验证:

  • 额度消耗曲线走平:握手计费下,日额度消耗应该只与连接次数相关,而不是随行情活跃度波动。
  • 端到端延迟下降:对比 tick 的 at 字段(RFC3339 时间戳)与本地接收时间。
  • 429 消失:迁移后如果仍出现 DAILY_LIMIT_EXCEEDED,说明还有残留的 REST 轮询在跑。

常见问题

WebSocket 推送会计入 REST 额度吗?

不会按条计入。建连握手会计入每日额度和 RPM,握手之后的 tick 推送不计费。这也是流式方案成本恒定的原因。

为什么秒级轮询 500 个标的会超额度?

因为批量上限是每次 50 个 codes,一轮需要 10 次请求。10 次/秒 × 86,400 秒 = 86.4 万次/天,月度约 2,592 万次,超过 Pro 套餐的 500 万次月额度。

REST 和 WebSocket 可以同时用吗?

可以,而且推荐这么做:用 WebSocket 承载实时推送,用 REST 做历史回填和低频查询。这也是 TIQEX 官方建议的用法。

标的规模扩大后成本会怎么变?

走流式的话基本不变——握手计费与订阅标的数量无关。走 REST 轮询则是线性增长,标的翻倍、成本翻倍。

怎么确认我拿到的是实时数据而不是延迟数据?

检查 REST 响应中的 delayed 字段,以及套餐的市场权限。Growth 套餐的 crypto 和金属是实时的,美股、A 股、港股等为延迟;Pro 套餐全市场实时。

下一步

先算清你的真实请求量,再决定计费模型。免费套餐包含延迟的 crypto、美股和金属数据,无需信用卡即可验证接入流程——用 Python 接入指南 十分钟就能跑通第一条请求。

按市场查看具体的实时 / 延迟权限:加密货币行情、美股行情、外汇行情。