幣安 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接入」分類完整列表。