币安 Spot API 入门的最短路径是:准备好 API Key + Secret 后,先调 /api/v3/ping 验证连通性,再用 /api/v3/time 同步服务器时间,最后通过 /api/v3/account(签名接口)拉取余额确认权限正常,全程约 10 分钟 即可完成第一次下单。本文给出每一步的 curl 与 Python 完整代码,所有端点都是 https://api.binance.com 真实在用的地址。还没准备好 API 密钥的请先到 币安官网 完成 KYC,没有币安账号可 免费注册 开户。
一、Spot API 的接口分层
币安 Spot REST API 按 鉴权等级 分成三类:
| 类别 | 端点前缀示例 | 是否需签名 | Header 要求 | 典型接口 |
|---|---|---|---|---|
| NONE | /api/v3/ping, /api/v3/time | 否 | 无 | 服务器时间、系统状态 |
| MARKET_DATA | /api/v3/depth, /api/v3/klines | 否 | 无 | 行情、深度、K 线 |
| USER_DATA | /api/v3/account, /api/v3/order | 是 | X-MBX-APIKEY + signature | 下单、撤单、余额 |
| TRADE | /api/v3/order (POST) | 是 | X-MBX-APIKEY + signature | 买卖下单 |
| USER_STREAM | /api/v3/userDataStream | API Key only | X-MBX-APIKEY | WebSocket listenKey |
鉴权接口 必须在查询参数末尾拼接 signature=<HMAC-SHA256 签名>,并在请求头带上 X-MBX-APIKEY。
二、环境准备与连通性测试
1. 安装依赖
# Python 3.8+
pip install requests python-dotenv
# 或使用官方 SDK
pip install python-binance
2. 基础 URL 选择
币安 Spot API 提供 5 个镜像入口,代码中建议使用 api.binance.com,失败时回退到 api-gcp.binance.com:
ENDPOINTS = [
"https://api.binance.com", # 默认
"https://api-gcp.binance.com", # Google Cloud 线路
"https://api1.binance.com",
"https://api2.binance.com",
"https://api3.binance.com",
]
3. 第一次请求:ping
curl -X GET "https://api.binance.com/api/v3/ping"
# 返回 {} 代表连通
4. 同步服务器时间
curl -X GET "https://api.binance.com/api/v3/time"
# {"serverTime":1713027384562}
本地时间与 serverTime 差距超过 1000ms 会导致签名接口报 -1021,量化服务器必须开启 NTP。
三、查询账户余额(签名接口)
下面是一个完整可运行的 Python 封装,处理了签名、重试、时间戳偏移三个关键点:
import hmac, hashlib, time, requests
from urllib.parse import urlencode
API_KEY = "YOUR_API_KEY"
SECRET_KEY = "YOUR_SECRET_KEY"
BASE_URL = "https://api.binance.com"
def _sign(params: dict) -> dict:
params["timestamp"] = int(time.time() * 1000)
params["recvWindow"] = 5000
query = urlencode(params)
params["signature"] = hmac.new(
SECRET_KEY.encode(),
query.encode(),
hashlib.sha256
).hexdigest()
return params
def _request(method: str, path: str, params: dict = None, signed: bool = False):
params = params or {}
headers = {"X-MBX-APIKEY": API_KEY} if signed else {}
if signed:
params = _sign(params)
url = f"{BASE_URL}{path}"
r = requests.request(method, url, params=params, headers=headers, timeout=10)
r.raise_for_status()
return r.json()
def get_account():
return _request("GET", "/api/v3/account", signed=True)
# 调用
balances = get_account()["balances"]
non_zero = [b for b in balances if float(b["free"]) > 0]
for b in non_zero:
print(f"{b['asset']}: {b['free']} (冻结 {b['locked']})")
返回结构示例:
{
"makerCommission": 10,
"takerCommission": 10,
"canTrade": true,
"canWithdraw": true,
"canDeposit": true,
"accountType": "SPOT",
"balances": [
{"asset": "BTC", "free": "0.00123456", "locked": "0.00000000"},
{"asset": "USDT", "free": "128.45", "locked": "0.00"}
]
}
四、查询行情与 K 线(公开接口)
行情接口不需要签名,但同样有权重限制:
def get_price(symbol: str) -> float:
r = _request("GET", "/api/v3/ticker/price", {"symbol": symbol})
return float(r["price"])
def get_depth(symbol: str, limit: int = 20) -> dict:
return _request("GET", "/api/v3/depth", {"symbol": symbol, "limit": limit})
def get_klines(symbol: str, interval: str = "1h", limit: int = 500):
return _request("GET", "/api/v3/klines", {
"symbol": symbol,
"interval": interval, # 1m, 5m, 15m, 1h, 4h, 1d
"limit": limit
})
print(get_price("BTCUSDT")) # 68420.12
性能提示:查询单个价格用 /ticker/price(权重 1),查询全部交易对用 /ticker/24hr(权重 40)比循环每个交易对省 99% 权重。
五、下单与撤单(TRADE 接口)
现货下单端点是 POST /api/v3/order,必填参数按 type 不同而不同:
1. 限价单(LIMIT)
def place_limit_order(symbol: str, side: str, quantity: float, price: float):
return _request("POST", "/api/v3/order", {
"symbol": symbol,
"side": side, # BUY 或 SELL
"type": "LIMIT",
"timeInForce": "GTC", # GTC / IOC / FOK
"quantity": quantity,
"price": price,
}, signed=True)
order = place_limit_order("BTCUSDT", "BUY", 0.001, 60000.00)
print(order["orderId"], order["status"])
2. 市价单(MARKET)
市价单可以按 数量(quantity) 或 金额(quoteOrderQty) 下:
# 按 BTC 数量买(会消耗对应 USDT)
_request("POST", "/api/v3/order", {
"symbol": "BTCUSDT",
"side": "BUY",
"type": "MARKET",
"quantity": 0.001
}, signed=True)
# 按 USDT 金额买(更常用,避免滑点溢出)
_request("POST", "/api/v3/order", {
"symbol": "BTCUSDT",
"side": "BUY",
"type": "MARKET",
"quoteOrderQty": 100 # 用 100 USDT 买 BTC
}, signed=True)
3. 查询订单状态
def get_order(symbol: str, order_id: int):
return _request("GET", "/api/v3/order", {
"symbol": symbol,
"orderId": order_id
}, signed=True)
status = get_order("BTCUSDT", 12345678)
# status["status"] 可能是 NEW / PARTIALLY_FILLED / FILLED / CANCELED / REJECTED
4. 撤单
def cancel_order(symbol: str, order_id: int):
return _request("DELETE", "/api/v3/order", {
"symbol": symbol,
"orderId": order_id
}, signed=True)
cancel_order("BTCUSDT", 12345678)
六、测试网先行(避免真金白银试错)
币安提供独立的 Spot Testnet,免费领测试币:
# 测试网配置
BASE_URL = "https://testnet.binance.vision"
# API Key 需要单独在 testnet.binance.vision 注册
测试网的下单、撤单、余额查询完全模拟主网行为,但币种价格会与真实市场不同步。建议所有新代码先在 Testnet 跑通 24 小时再切主网。
七、常见问题 FAQ
Q1: 下单时 filter failure: LOT_SIZE 是什么原因?
A: 数量不符合交易对的 stepSize(最小步长)。例如 BTCUSDT 的 stepSize 是 0.00001,你不能下 0.000005 这种数量。调用 /api/v3/exchangeInfo 查询每个交易对的 LOT_SIZE / MIN_NOTIONAL / PRICE_FILTER 规则后做四舍五入。
Q2: Spot API 支持撤销所有挂单吗?
A: 支持。DELETE /api/v3/openOrders?symbol=BTCUSDT 会一次性撤销该交易对的所有未成交订单,权重 1,但不支持跨交易对撤单。
Q3: 一次性批量下单怎么做?
A: Spot 没有原生批量下单接口,可以并发调用 POST /api/v3/order 多次,但要注意 每 10 秒下单上限 100 单;合约有 /fapi/v1/batchOrders 一次最多 5 单。
Q4: SIDE 和 type 可以组合出哪些策略单?
A: 主流类型有 LIMIT, MARKET, STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT, LIMIT_MAKER。止损止盈单需要额外传 stopPrice。
Q5: 查询历史订单只返回 500 条够用吗?
A: /api/v3/allOrders 默认返回 500 条,通过 startTime/endTime/fromId 参数可以分页拉取历史。频繁量化建议接 WebSocket userDataStream 实时订阅订单变化,省权重。
更多合约 API 内容请回到 分类导航 查看「API接入」分类完整列表。