3、REST API基础:HTTP请求方法(GET/POST/DELETE)、鉴权机制(Token/API Key)、请求与响应格式

做量化交易,说白了就是跟交易所的服务器打交道。你发一条指令,它给你一个结果。这个过程中,REST API 就是你们之间的「传话筒」。我个人习惯把 REST API 理解成一个「外卖系统」——你点菜(请求),厨房做菜(交易所处理),然后送餐员把菜送到你手上(响应)。

嗯,咱们今天就把这个「外卖系统」拆开看看。你想想看,如果连怎么点菜、怎么验明正身都不知道,那资金安全可就悬了。

3.1 HTTP请求方法:你是在查菜单,还是在下单?

HTTP 协议定义了几种「动作」,告诉服务器你想干嘛。在量化交易里,最常用的就三个:GET、POST、DELETE。

  • GET:查数据。比如查账户余额、查当前持仓、查历史成交。它不会改变服务器上的任何状态。
  • POST:下指令。比如提交一个限价单、撤单、修改订单。它会改变服务器上的数据。
  • DELETE:删除资源。在交易场景里,通常就是撤单。告诉交易所:「我之前下的那个单子,不要了。」

我在项目中遇到过不少新手,把 GET 请求用来下单。结果呢?交易所返回一个 405 Method Not Allowed,单子没下成,还白白浪费了行情时间。记住:查用 GET,改用 POST,删用 DELETE,这是铁律。

核心原则:GET 请求是幂等的,你查一万次余额,结果应该一样(除非别人转了钱进来)。POST 和 DELETE 是非幂等的,每次执行都可能改变状态。

3.2 鉴权机制:交易所怎么知道「你是你」?

你总不能随便发个请求,交易所就把你的钱转走吧?所以,鉴权机制就是你的「身份证」和「签名」。主流交易所通常用两种方式:API Key + Secret Key,或者 Token。

3.2.1 API Key + Secret Key 鉴权

这是最传统的方式。你从交易所后台生成一对密钥:

  • API Key:相当于你的用户名,公开可见。
  • Secret Key:相当于你的密码,必须保密,绝对不能硬编码在代码里,更不能上传到 GitHub。

具体流程是这样的:

  1. 你构造好请求参数(比如时间戳、请求体)。
  2. 用 Secret Key 对这些参数进行签名(通常是 HMAC-SHA256 加密)。
  3. 把 API Key 和签名一起发过去。
  4. 交易所收到后,用你的 API Key 查到对应的 Secret Key,重新算一遍签名。如果一致,就放行。

我曾经犯过一个低级错误:把 Secret Key 直接写在了配置文件的注释里,然后不小心提交到了公司内网仓库。虽然没泄露到外网,但被安全团队通报批评了。从那以后,我所有密钥都走环境变量或者专门的密钥管理服务。

避坑指南:千万不要把 Secret Key 放在代码里!我曾经见过有人把密钥写在 Python 脚本里,然后脚本被分享到群里……后果可想而知。建议用 os.environ.get('API_SECRET') 从环境变量读取。

3.2.2 Token 鉴权

有些交易所(尤其是新兴的)采用 Token 方式。你先用用户名密码登录,拿到一个临时 Token,后续所有请求都带着这个 Token 就行。Token 有过期时间,过期了需要重新获取。

Token 的好处是:你不用每次都算签名,省事。但坏处是:Token 一旦泄露,别人就能冒充你,直到 Token 过期。所以,Token 的有效期通常很短(比如 30 分钟),而且建议走 HTTPS 加密传输。

我的习惯:对于高频交易,我倾向于用 API Key + 签名,因为每次请求都独立验证,安全性更高。对于中低频策略,Token 方式更便捷,但一定要做好 Token 的刷新和存储。

3.3 请求与响应格式:说「人话」

交易所和你的程序之间,总得用一种双方都懂的语言交流。现在最通用的就是 JSON。你发一个 JSON 字符串过去,它回一个 JSON 字符串回来。

3.3.1 请求格式

一个标准的 REST API 请求,通常包含这几部分:

  • URL:接口地址,比如 https://api.exchange.com/v1/order
  • 请求头(Headers):放鉴权信息、内容类型等。比如 Content-Type: application/json,以及你的 API Key 和签名。
  • 请求体(Body):放具体参数。比如下单时,你要告诉交易所:交易对、方向、价格、数量。

举个例子,一个下单请求的 Body 长这样:

{
  "symbol": "BTCUSDT",
  "side": "BUY",
  "type": "LIMIT",
  "price": "50000.00",
  "quantity": "0.01",
  "timestamp": 1699000000000
}

注意那个 timestamp,很多交易所要求带上时间戳,防止重放攻击。你想想看,如果有人截获了你之前的请求,然后重放一遍,岂不是又下了一单?时间戳能有效防止这种情况。

3.3.2 响应格式

交易所处理完你的请求后,会返回一个 JSON 响应。通常包含:

  • 状态码:200 表示成功,4xx 表示你这边的问题(比如参数错误、鉴权失败),5xx 表示交易所那边的问题。
  • 响应体:具体数据。比如下单成功后,会返回订单 ID、成交状态等。

一个成功的下单响应:

{
  "code": 0,
  "msg": "success",
  "data": {
    "orderId": "123456789",
    "symbol": "BTCUSDT",
    "status": "NEW"
  }
}

一个失败的响应:

{
  "code": -1001,
  "msg": "Insufficient balance",
  "data": null
}

我在项目中遇到过最头疼的事:有些交易所的「成功」状态码不是 200,而是 0 或者 "ok"。所以,千万别硬编码状态码判断,一定要先看交易所的文档,或者动态解析响应里的 code 字段。

经验之谈:写代码时,一定要对响应做「防御性解析」。比如先检查 response.status_code 是不是 200,再检查 json_data.get('code') 是不是 0。两层校验,能避免很多坑。

3.4 知识体系总览

下面这张图,是我自己梳理的 REST API 核心逻辑。你一看就明白整个流程了:

REST API 核心流程 你的交易程序 HTTP 请求 鉴权验证 API Key / Token 交易所核心系统 处理订单 / 查询数据 HTTP 响应(JSON) 关键点: 1. GET 查数据,POST 下指令,DELETE 撤单 2. 鉴权用 API Key + 签名,或 Token 3. 请求和响应都用 JSON 格式,注意时间戳防重放

3.5 实战中的小细节

最后,分享几个我踩过的坑,希望能帮你省点时间:

  • 请求频率限制:交易所都有限流(Rate Limit),比如每秒最多 10 次请求。我刚开始做高频时,没注意这个,结果被交易所封了 IP 半小时。后来我加了个本地计数器,超过阈值就 sleep 一下。
  • 错误处理:别只处理 200 状态码。4xx 和 5xx 都要有对应的重试或告警逻辑。我曾经因为网络抖动,连续重试了 10 次同一个下单请求,结果下了 10 个单……亏了不少手续费。
  • 日志记录:每个请求和响应都记下来。出问题时,日志就是你最好的朋友。我习惯把请求 URL、Body、响应状态码、耗时都写到文件里,方便复盘。

一个小技巧:写一个统一的 HTTP 请求封装函数,把鉴权、签名、重试、日志都包在里面。这样你每次调用接口时,只需要传 URL 和参数,省心又安全。

好了,REST API 的基础就聊到这儿。说白了,就是「怎么发请求、怎么验身份、怎么读响应」这三件事。把这些搞明白了,后面对接实盘接口就会顺畅很多。


专注资料整理