3. REST API基础:HTTP协议回顾(GET/POST)、API密钥管理、使用requests库调用行情接口、处理JSON响应数据
各位同学,咱们今天聊点实在的。做量化交易,说白了就是跟数据打交道。而数据从哪来?绝大多数情况下,都是从交易所的API接口来。这一章,我就带你把这套东西彻底搞明白。
3.1 HTTP协议:你每天都在用,但可能没细想过
HTTP协议,全称超文本传输协议。嗯,这个名字听起来挺唬人。其实你可以把它想象成——你和交易所之间的一种「对话规则」。
你问:「今天比特币多少钱?」
交易所答:「当前价格是xxxxx。」
这个一问一答的过程,就是一次HTTP请求和响应。我个人习惯把HTTP理解成「快递员」——你写好请求内容,快递员帮你送到交易所,再把交易所的回复带回来。
3.1.1 GET vs POST:两种最常见的请求方式
这两种方式,你肯定听过。但它们的区别,很多人其实没搞透。
| 特性 | GET | POST |
|---|---|---|
| 用途 | 获取数据(查行情、查账户信息) | 提交数据(下单、撤单) |
| 参数位置 | URL后面(?symbol=BTCUSDT) | 请求体(body)里 |
| 安全性 | 参数暴露在URL中,不安全 | 参数在body里,相对安全 |
| 幂等性 | 是(多次请求结果一样) | 否(多次下单可能重复成交) |
举个例子。你想查一下比特币的当前价格,用GET就够了:
GET https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT
但如果你想下单买入1个比特币,那就得用POST。因为这是一个「动作」,不是「查询」。我在项目中遇到过有人用GET去下单,结果参数全暴露在URL里,被日志记录下来了……嗯,这是个很尴尬的安全事故。
核心原则:
- 查数据用GET
- 改数据用POST
- 千万别搞反
3.2 API密钥管理:你的数字身份证
做量化交易,光会调接口还不够。你得证明「你是谁」。这就是API密钥的作用。
每个交易所都会给你一对密钥:
- API Key:相当于你的用户名,公开可见
- Secret Key:相当于你的密码,必须保密
你想想看,如果你的Secret Key泄露了,别人就能用你的账户下单、提币。所以,密钥管理是重中之重。
3.2.1 密钥的存储方式
我见过最离谱的做法——把密钥硬编码在代码里。然后代码还上传到了GitHub……结果可想而知,账户被盗,损失惨重。
正确的做法是什么?
- 使用环境变量:把密钥放在系统的环境变量里,代码里用
os.getenv()读取 - 使用配置文件:比如
.env文件,但记得加入.gitignore - 使用密钥管理服务:比如AWS Secrets Manager、HashiCorp Vault
我个人习惯用环境变量。简单、安全、跨平台。看代码:
import os
API_KEY = os.getenv("BINANCE_API_KEY")
SECRET_KEY = os.getenv("BINANCE_SECRET_KEY")
if not API_KEY or not SECRET_KEY:
raise ValueError("请先设置环境变量 BINANCE_API_KEY 和 BINANCE_SECRET_KEY")
警告:千万不要把密钥提交到版本控制系统中。我曾经见过一个团队,因为代码仓库是私有的就觉得安全,结果被内部人员泄露了密钥……嗯,人心难测。
3.3 使用requests库调用行情接口
Python里最常用的HTTP库就是requests。它简洁、优雅、功能强大。说白了,它就是帮你完成「写请求→发请求→收响应」这一整套流程的工具。
3.3.1 安装与基本使用
pip install requests
然后,我们来调一个真实的行情接口。以币安为例,获取BTC/USDT的当前价格:
import requests
url = "https://api.binance.com/api/v3/ticker/price"
params = {"symbol": "BTCUSDT"}
response = requests.get(url, params=params)
print(response.status_code) # 200 表示成功
print(response.text) # 原始响应内容
运行一下,你会看到类似这样的输出:
200
{"symbol": "BTCUSDT", "price": "67500.00"}
嗯,成功了。但这里有个坑——response.text返回的是字符串,不是Python对象。你没法直接取里面的price字段。怎么办?往下看。
3.4 处理JSON响应数据
JSON(JavaScript Object Notation)是目前最主流的数据交换格式。交易所返回的数据,99%都是JSON格式。
Python的requests库贴心地提供了.json()方法,可以直接把JSON字符串解析成Python字典:
import requests
url = "https://api.binance.com/api/v3/ticker/price"
params = {"symbol": "BTCUSDT"}
response = requests.get(url, params=params)
data = response.json() # 解析成字典
print(data["symbol"]) # BTCUSDT
print(data["price"]) # 67500.00
你看,这样就能直接取数据了。方便吧?
3.4.1 处理更复杂的JSON结构
有时候,交易所返回的数据不是简单的键值对,而是嵌套的列表和字典。比如获取K线数据:
url = "https://api.binance.com/api/v3/klines"
params = {
"symbol": "BTCUSDT",
"interval": "1h",
"limit": 5
}
response = requests.get(url, params=params)
data = response.json()
# data 是一个列表,每个元素是一个K线
for kline in data:
open_time = kline[0]
open_price = kline[1]
high_price = kline[2]
low_price = kline[3]
close_price = kline[4]
print(f"时间: {open_time}, 开盘: {open_price}, 收盘: {close_price}")
小技巧:拿到JSON数据后,先用print(json.dumps(data, indent=2))格式化输出,看清楚结构再写解析代码。我每次调新接口都这么干,省得猜字段名。
3.5 本章知识体系
为了让你更直观地理解这一章的内容,我画了一张流程图:
这张图把整个流程串起来了。从准备请求,到发送,到接收响应,再到解析数据。每一步都有坑,每一步也都有技巧。
本章核心要点:
- GET用于查询,POST用于操作,别搞混
- API密钥必须安全存储,推荐环境变量
- requests库的
.json()方法直接解析JSON - 拿到数据先格式化输出,看清结构再动手
好了,这一章就到这里。记住我今天说的这些,后面写代码的时候能少踩很多坑。尤其是密钥管理那部分——我曾经因为一个不小心,把测试环境的密钥泄露了,结果被人刷了一堆垃圾订单……嗯,说多了都是泪。