2、数据源接入基础:REST API 与 WebSocket 协议对比、交易所 API 鉴权机制、数据源连接池管理

做量化交易,第一步就是搞定数据源。没有数据,策略就是空中楼阁。今天咱们聊聊数据源接入的几个核心问题:选什么协议、怎么鉴权、如何管理连接池。

2.1 REST API 与 WebSocket:两种协议的实战选择

我个人习惯把这两个协议比作「打电话」和「挂电话」。REST API 是你主动打过去问行情,WebSocket 是交易所主动给你推送行情。听起来好像 WebSocket 更高级?其实各有各的用武之地。

2.1.1 REST API:简单可靠,但别滥用

REST API 说白了就是 HTTP 请求。你发一个 GET 请求,交易所返回 JSON 数据。优点是简单、调试方便、任何语言都能用。

适用场景:

  • 获取历史K线数据(比如回测用)
  • 查询账户余额、持仓信息
  • 下单、撤单等交易操作
  • 低频行情快照(比如每分钟查一次)

我在项目中遇到过一个问题: 有个同事用 REST API 轮询行情,每秒请求一次。结果交易所直接封了 IP。为什么?因为 REST API 有频率限制。大部分交易所对 REST 接口的限制是每秒 1-10 次,超过就给你 429 错误码。

避坑指南: 我曾经因为没处理 429 错误,导致整个行情系统崩溃。后来加了个重试机制,配合指数退避(Exponential Backoff),才算稳定下来。

2.1.2 WebSocket:实时推送,但连接维护有讲究

WebSocket 是长连接。建立一次连接后,交易所会持续推送数据给你。延迟低、带宽省,适合高频行情。

适用场景:

  • 实时 tick 级行情订阅
  • 订单簿深度更新
  • 交易对状态变化通知
  • 需要毫秒级响应的策略

你想想看,如果做高频交易,用 REST API 轮询,等你拿到数据黄花菜都凉了。WebSocket 才是正解。

但 WebSocket 有个坑: 连接会断。网络波动、交易所重启、防火墙超时,都可能断开。所以必须实现心跳检测和自动重连机制。

我的经验: 心跳间隔设为 30 秒比较合适。太频繁浪费带宽,太慢容易错过断连。重连时记得用指数退避,别一断就连,把交易所服务器打爆。

2.1.3 协议对比表

对比维度 REST API WebSocket
通信模式 请求-响应 订阅-推送
延迟 100-500ms 10-50ms
带宽消耗 高(每次全量数据) 低(增量推送)
连接数 可并发多个 通常限制 1-5 个
适用场景 低频、历史数据、交易 实时行情、高频策略
容错性 天然支持重试 需自行实现重连

2.2 交易所 API 鉴权机制:别让密钥裸奔

鉴权这事儿,说白了就是证明「你是你」。交易所 API 鉴权主要有三种方式,我按安全等级排个序。

2.2.1 API Key + Secret Key(最常用)

这是最基础的鉴权方式。交易所给你一对密钥:API Key 是公开的,Secret Key 是私密的。每次请求时,用 Secret Key 对参数签名,交易所验证签名是否匹配。

签名流程:

  1. 拼接请求参数(时间戳、API Key、请求体等)
  2. 用 Secret Key 做 HMAC-SHA256 签名
  3. 把签名放在请求头或参数里
# Python 示例:币安 API 签名
import hmac
import hashlib
import time

api_key = "your_api_key"
secret_key = "your_secret_key"

params = {
    "symbol": "BTCUSDT",
    "timestamp": int(time.time() * 1000)
}

# 拼接参数并签名
query_string = "&".join([f"{k}={v}" for k, v in sorted(params.items())])
signature = hmac.new(
    secret_key.encode(),
    query_string.encode(),
    hashlib.sha256
).hexdigest()

params["signature"] = signature
headers = {"X-MBX-APIKEY": api_key}
注意: 千万别把 Secret Key 硬编码在代码里!我曾经见过有人把密钥提交到 GitHub,结果被机器人扫到,账户里的币全被盗了。建议用环境变量或密钥管理服务。

2.2.2 JWT Token(较新趋势)

有些交易所开始用 JWT(JSON Web Token)。你拿 API Key 换一个临时 Token,后续请求带 Token 就行。Token 有过期时间,到期需要重新获取。

好处是:Token 泄露了也只是临时有效,不像 Secret Key 那样永久有效。坏处是:需要额外维护 Token 的刷新逻辑。

2.2.3 OAuth 2.0(第三方应用常用)

如果你做的是第三方量化平台,需要用户授权你的应用访问他的交易所账户,那就用 OAuth 2.0。用户授权后,你拿到一个 Access Token,用它来操作。

这个机制在量化场景用得少,因为大部分量化交易者都是自己管理密钥。

2.3 数据源连接池管理:别让连接成为瓶颈

连接池管理,说白了就是「复用连接」。每次请求都新建连接,效率太低。尤其 WebSocket 长连接,建立一次成本很高。

2.3.1 为什么需要连接池?

我举个例子:假设你订阅了 10 个交易对的实时行情。如果每个交易对都开一个 WebSocket 连接,那就是 10 个连接。交易所通常限制连接数,比如币安限制每个 IP 最多 5 个 WebSocket 连接。怎么办?

答案是用连接池。一个连接订阅多个交易对,通过消息通道区分。

2.3.2 连接池的核心参数

参数 说明 推荐值
最大连接数 同时保持的连接上限 交易所限制的 80%
最小空闲连接 保持空闲连接数,避免频繁创建 2-5 个
连接超时 建立连接的最大等待时间 5-10 秒
空闲超时 空闲连接多久后关闭 60 秒
最大重试次数 连接失败后的重试次数 3 次

2.3.3 实战:WebSocket 连接池实现思路

嗯,这里要注意。连接池不是简单的「创建一堆连接放着」。你需要考虑:

  • 连接复用: 多个订阅共享一个连接,通过订阅 ID 区分
  • 健康检查: 定期发 ping 检测连接是否存活
  • 自动重连: 断连后自动从池中移除,创建新连接
  • 负载均衡: 把订阅均匀分配到不同连接上
# 伪代码:WebSocket 连接池管理
class WebSocketPool:
    def __init__(self, max_connections=5):
        self.pool = []
        self.max_connections = max_connections
    
    def get_connection(self):
        # 找空闲连接
        for conn in self.pool:
            if conn.is_idle() and conn.is_alive():
                return conn
        # 没有空闲,创建新连接
        if len(self.pool) < self.max_connections:
            conn = self._create_connection()
            self.pool.append(conn)
            return conn
        # 连接池满了,等待或报错
        raise ConnectionPoolExhausted()
    
    def _create_connection(self):
        # 建立 WebSocket 连接
        # 设置心跳、重连回调
        pass
    
    def health_check(self):
        # 定期检查连接状态
        for conn in self.pool:
            if not conn.is_alive():
                conn.reconnect()
我的建议: 别自己造轮子。Python 用 websockets 库配合 asyncio,Java 用 Netty,Go 用 gorilla/websocket。这些库都内置了连接池和重连机制,比自己写稳定得多。

2.4 本章小结

数据源接入看似简单,其实坑不少。选协议要看场景:低频用 REST,高频用 WebSocket。鉴权要保护好密钥,别裸奔。连接池要管理好,别让连接成为瓶颈。

我个人觉得,最容易被忽视的是连接池的健康检查。很多系统上线后突然断连,就是因为没做心跳检测。嗯,这个坑我踩过,希望你别踩。

数据源接入核心架构 数据源层 交易所A (REST + WebSocket) 交易所B (REST + WebSocket) 交易所C (REST + WebSocket) 连接池管理层 连接复用 健康检查 自动重连 负载均衡 协议适配层 REST 请求封装 WebSocket 订阅管理 鉴权签名 业务层(行情聚合、策略执行)
核心要点: 数据源接入不是简单的「调 API」,而是一个分层架构。底层管连接,中间层管协议和鉴权,上层管业务逻辑。每一层都有坑,每一层都要精心设计。

蓝海数据掘金营,专注资料整理