歐易 API Python 教程:獲取行情、K 線、查詢餘額與下單(附簽名程式碼)

用 Python 呼叫歐易(OKX)API v5 的入門教程:只依賴 requests 獲取即時行情和 K 線,按官方規則生成 OK-ACCESS-SIGN 簽名,查詢賬戶餘額、下限價單、查詢和撤銷訂單,附模擬盤請求頭、介面限速和常見錯誤碼說明,程式碼均經過實際執行。

拾階編輯部最後核對 約 7 分鐘讀完
要點速覽
  1. 行情、K 線等公共介面不需要 API Key,用 requests 發一個 GET 請求就能拿到資料。
  2. 私有介面要帶 4 個請求頭,簽名 = Base64(HMAC-SHA256(時間戳 + 請求方法 + 請求路徑 + 請求體, Secret Key))。
  3. GET 請求的查詢引數要拼進請求路徑一起簽名,時間戳必須是 UTC 毫秒格式,與伺服器相差超過 30 秒會被拒絕。
  4. 先用模擬盤 Key 加上 x-simulated-trading 請求頭把程式跑通,確認無誤後再考慮實盤。
本文目錄 11
  1. 準備工作
  2. API v5 基礎
  3. 公共介面:獲取行情和 K 線
  4. 簽名規則
  5. 私有介面:查餘額、下單、查單、撤單
  6. 模擬盤與實盤切換
  7. 介面限速
  8. 常見錯誤碼
  9. 官方 SDK 與第三方庫
  10. 下一步
  11. 常見問題

歐易提供 REST 和 WebSocket 兩套 API。本文用 Python 和 requests 庫演示最常用的 REST 操作:先拿公開行情和 K 線,再按官方規則生成簽名,查詢餘額、下單、查單和撤單。文中程式碼都在 2026 年 10 月實際執行過,介面和欄位名以歐易 API v5 官方文件為準。

本文是程式設計教程,不構成任何投資建議。涉及下單的程式碼請一律先在模擬盤執行,程式寫錯一個引數,在實盤就是真金白銀的損失。

準備工作

  1. 安裝 Python 3 和 requests:
pip install requests
  1. 只做第一部分(公共行情)不需要任何 Key。要呼叫私有介面,先按 歐易 API 申請教程 建立一把模擬盤 API Key,許可權勾選「讀取」和「交易」即可。

  2. 把金鑰放進環境變數,不要直接寫在程式碼裡。程式碼檔案容易被分享、截圖或上傳到網上,環境變數則只存在於你的電腦中。macOS / Linux 終端:

export OKX_API_KEY="你的 API Key"
export OKX_SECRET_KEY="你的 Secret Key"
export OKX_PASSPHRASE="你的 Passphrase"

Windows PowerShell 用 $env:OKX_API_KEY="你的 API Key" 的寫法,其餘兩項同理。

API v5 基礎

  • 介面地址:歐易文件當前給出的 REST 地址是 https://openapi.okx.com,實盤和模擬盤共用這個地址,靠請求頭區分。如果你是在歐易美國、澳洲站(app.okx.com)註冊的,要改用 us.okx.com;在歐洲站(my.okx.com)註冊的用 eea.okx.com;
  • 返回格式:統一是 JSON,包含 code、msg、data 三個欄位。code 為 "0" 表示成功,data 是一個數組;
  • 數值都是字串:價格、數量都以字串返回,計算前要用 float() 或 Decimal() 轉換。

公共介面:獲取行情和 K 線

公共介面不需要簽名:

from datetime import datetime, timezone

import requests

BASE_URL = "https://openapi.okx.com"


def public_get(path, params=None):
    resp = requests.get(BASE_URL + path, params=params, timeout=10)
    resp.raise_for_status()
    data = resp.json()
    if data["code"] != "0":
        raise RuntimeError(f"歐易返回錯誤:{data['code']} {data['msg']}")
    return data["data"]


# 1. 最新行情
ticker = public_get("/api/v5/market/ticker", {"instId": "BTC-USDT"})[0]
print("最新成交價:", ticker["last"])
print("買一 / 賣一:", ticker["bidPx"], "/", ticker["askPx"])
print("24 小時最高 / 最低:", ticker["high24h"], "/", ticker["low24h"])
print("24 小時成交量(BTC):", ticker["vol24h"])

# 2. 最近 5 根 1 小時 K 線(最新的在最前面)
candles = public_get(
    "/api/v5/market/candles",
    {"instId": "BTC-USDT", "bar": "1H", "limit": "5"},
)
for ts, o, h, l, c, vol, vol_ccy, vol_ccy_quote, confirm in candles:
    t = datetime.fromtimestamp(int(ts) / 1000, tz=timezone.utc)
    state = "已收盤" if confirm == "1" else "進行中"
    print(t.strftime("%m-%d %H:%M UTC"), "開", o, "高", h, "低", l, "收", c, state)

執行後會列印 BTC-USDT 的最新價、買一賣一,以及最近 5 根小時 K 線。要點:

  • instId 是產品 ID,現貨寫成 BTC-USDT,永續合約寫成 BTC-USDT-SWAP;
  • ticker 常用欄位:last 最新成交價、bidPx / askPx 買一 / 賣一價、high24h / low24h 24 小時最高 / 最低價、vol24h 24 小時成交量(現貨以交易幣計);
  • K 線的每一行是陣列,順序為 [ts, o, h, l, c, vol, volCcy, volCcyQuote, confirm],ts 是開盤時間的毫秒時間戳,confirm 為 "1" 表示這根 K 線已收盤;
  • bar 區分大小寫:分鐘用小寫 1m、15m,小時用大寫 1H、4H,日線 1D;寫成 1h 會返回 51000 引數錯誤;
  • limit 預設 100,最大 300,這個介面最多能取最近 1,440 根,更早的資料要用 /api/v5/market/history-candles。

簽名規則

私有介面的每個請求都必須帶上 4 個請求頭:

請求頭 內容
OK-ACCESS-KEY 你的 API Key
OK-ACCESS-SIGN 簽名(見下文)
OK-ACCESS-TIMESTAMP UTC 時間戳,ISO 8601 格式精確到毫秒,如 2026-10-22T08:30:15.123Z
OK-ACCESS-PASSPHRASE 建立 Key 時設定的 Passphrase

簽名的生成方法:

  1. 拼接字串:時間戳 + 請求方法 + 請求路徑 + 請求體;
  2. 請求方法必須大寫,如 GET、POST;
  3. GET 請求的查詢引數屬於請求路徑,例如 /api/v5/account/balance?ccy=BTC;GET 請求沒有請求體,這部分留空;
  4. POST 請求的請求體是 JSON 字串,簽名用的字串必須和實際傳送的一模一樣;
  5. 用 Secret Key 對拼接結果做 HMAC-SHA256,再做 Base64 編碼。

時間戳與歐易伺服器相差超過 30 秒會被拒絕(錯誤碼 50102),所以一定要用 UTC 時間,而不是本地時區。

把這些規則寫成一個通用函式,儲存為 okx_client.py:

import base64
import hashlib
import hmac
import json
import os
from datetime import datetime, timezone

import requests

BASE_URL = "https://openapi.okx.com"
API_KEY = os.environ["OKX_API_KEY"]
SECRET_KEY = os.environ["OKX_SECRET_KEY"]
PASSPHRASE = os.environ["OKX_PASSPHRASE"]
DEMO = True  # True = 模擬盤;確認一切正常前不要改成 False


def get_timestamp():
    # ISO 8601 UTC 時間,精確到毫秒,例如 2026-10-22T08:30:15.123Z
    now = datetime.now(timezone.utc)
    return now.isoformat(timespec="milliseconds").replace("+00:00", "Z")


def make_sign(timestamp, method, request_path, body):
    prehash = timestamp + method + request_path + body
    mac = hmac.new(SECRET_KEY.encode(), prehash.encode(), hashlib.sha256)
    return base64.b64encode(mac.digest()).decode()


def private_request(method, path, params=None, body=None):
    method = method.upper()
    request_path = path
    if params:  # GET 引數要拼進 requestPath 一起簽名
        request_path += "?" + "&".join(f"{k}={v}" for k, v in params.items())
    body_str = json.dumps(body, separators=(",", ":")) if body else ""

    timestamp = get_timestamp()
    headers = {
        "OK-ACCESS-KEY": API_KEY,
        "OK-ACCESS-SIGN": make_sign(timestamp, method, request_path, body_str),
        "OK-ACCESS-TIMESTAMP": timestamp,
        "OK-ACCESS-PASSPHRASE": PASSPHRASE,
        "Content-Type": "application/json",
    }
    if DEMO:
        headers["x-simulated-trading"] = "1"

    resp = requests.request(
        method, BASE_URL + request_path,
        headers=headers, data=body_str or None, timeout=10,
    )
    data = resp.json()
    if data.get("code") != "0":
        raise RuntimeError(
            f"歐易返回錯誤:code={data.get('code')} msg={data.get('msg')} data={data.get('data')}"
        )
    return data["data"]

注意 body_str 先生成、再同時用於簽名和傳送,這樣能保證兩者一致。

私有介面:查餘額、下單、查單、撤單

在 okx_client.py 同一目錄下新建一個指令碼:

from okx_client import private_request

# 1. 查詢交易賬戶餘額
for acct in private_request("GET", "/api/v5/account/balance", {"ccy": "USDT,BTC"}):
    print("賬戶總權益(美元):", acct["totalEq"])
    for d in acct["details"]:
        print(d["ccy"], "可用:", d["availBal"], "凍結:", d["frozenBal"])

# 2. 下一個遠低於市價的限價買單(模擬盤)
order = private_request("POST", "/api/v5/trade/order", body={
    "instId": "BTC-USDT",
    "tdMode": "cash",       # 現貨非槓桿
    "side": "buy",
    "ordType": "limit",
    "px": "50000",          # 限價:USDT
    "sz": "0.0001",         # 數量:BTC
    "clOrdId": "demo001",   # 自定義訂單號,可選
})[0]
print("下單結果:", order["sCode"], order["sMsg"], "訂單號:", order["ordId"])

# 3. 查詢訂單狀態
info = private_request("GET", "/api/v5/trade/order",
                       {"instId": "BTC-USDT", "ordId": order["ordId"]})[0]
print("狀態:", info["state"], "已成交數量:", info["accFillSz"])

# 4. 撤單
cancel = private_request("POST", "/api/v5/trade/cancel-order",
                         body={"instId": "BTC-USDT", "ordId": order["ordId"]})[0]
print("撤單結果:", cancel["sCode"], cancel["sMsg"])

幾個關鍵引數:

  • 餘額:totalEq 是以美元計的賬戶總權益;details 裡每個幣種的 availBal 是可用餘額,frozenBal 是被掛單等佔用的凍結餘額。ccy 可以不傳,表示查詢全部幣種;
  • 下單:tdMode 現貨非槓桿填 cash;side 為 buy 或 sell;ordType 為 limit(限價)時必須帶 px;現貨限價單的 sz 以交易幣計(這裡是 BTC)。最小下單量等規則可以用公共介面 /api/v5/public/instruments?instType=SPOT&instId=BTC-USDT 查詢 minSz、lotSz、tickSz;
  • 下單結果:每一筆訂單的成敗看 data 裡的 sCode,"0" 表示成功,同時返回歐易生成的 ordId;
  • 訂單狀態 state:live 等待成交、partially_filled 部分成交、filled 完全成交、canceled 已撤銷;
  • 查單和撤單都可以用 ordId 或你自定義的 clOrdId。

示例故意把價格設得遠低於當前市價,下單後不會立即成交,方便練習查詢和撤單,請根據當時行情調整。

模擬盤與實盤切換

模擬盤和實盤使用同一個介面地址和簽名方式,區別只有兩點:

  1. 使用在「交易 → 模擬交易 → 個人中心」裡建立的模擬盤 API Key;
  2. 請求頭加 x-simulated-trading: 1(上面程式碼裡 DEMO = True 時自動新增)。

用實盤 Key 訪問模擬盤,或者反過來,都會返回 50101。強烈建議先在模擬盤連續執行一段時間,確認下單數量、方向、異常處理都沒有問題,再考慮換成實盤 Key 並把 DEMO 改為 False。

介面限速

介面 限速 計算依據
行情 /api/v5/market/ticker 20 次 / 2 秒 IP
K 線 /api/v5/market/candles 40 次 / 2 秒 IP
餘額 /api/v5/account/balance 10 次 / 2 秒 使用者 ID
下單、撤單、查單 各 60 次 / 2 秒 使用者 ID + 產品 ID

超過限速會返回 50011。程式裡應控制請求頻率,需要即時推送行情時,官方推薦改用 WebSocket。

常見錯誤碼

錯誤碼 含義 常見原因
50011 超過限速 請求太頻繁
50101 API Key 與當前環境不匹配 實盤 / 模擬盤 Key 用錯,或請求頭漏加、多加
50102 時間戳過期 沒用 UTC 時間或電腦時鐘不準
50105 Passphrase 錯誤 口令輸錯
50110 IP 不在白名單內 換了伺服器或網路
50111 / 50119 API Key 無效 / 不存在 Key 複製錯誤或已被刪除
50113 簽名無效 見下方 FAQ 的排查步驟
51000 引數錯誤 引數名或取值不對
51008 餘額不足 可用餘額不夠下單

官方 SDK 與第三方庫

熟悉原理後,也可以使用現成的庫:歐易官方 Python SDK(pip install python-okx,官方文件的示例程式碼就基於它),或支援多家交易所的開源庫 ccxt。無論用哪個,金鑰都應當放在環境變數裡。

下一步

常見問題

呼叫歐易行情介面需要 API Key 嗎?

不需要。ticker、K 線、深度等公共行情介面可以直接訪問,按 IP 限速。只有查詢餘額、下單、撤單等涉及賬戶的私有接口才需要 API Key 和簽名。

簽名一直報 50113 怎麼辦?

50113 表示簽名無效。逐項檢查:請求方法是否大寫;GET 請求的查詢引數是否拼進了簽名用的路徑;POST 請求籤名用的 body 字串是否和實際傳送的完全一致;Secret Key 是否複製完整、沒有多餘空格。

報錯 50102 是什麼原因?

50102 表示時間戳過期,即請求時間和歐易伺服器相差超過 30 秒。最常見的原因是用了本地時區而不是 UTC 時間,或者電腦時鐘不準。可以呼叫 /api/v5/public/time 獲取伺服器時間對比。

模擬盤和實盤的程式碼有什麼區別?

介面地址和簽名方式完全一樣,區別只有兩點:要使用在模擬交易裡建立的 API Key,並在請求頭加上 x-simulated-trading 值為 1。實盤請求去掉這個請求頭,換成實盤 Key。

有沒有現成的 Python 庫?

歐易官方提供 Python SDK(PyPI 包名 python-okx),開源庫 ccxt 也支援歐易。不過先用本文的原生寫法理解簽名原理,排查問題時會輕鬆很多。

還沒有歐易賬戶?註冊時填寫邀請碼 ,可享新人福利與手續費返佣(以歐易活動頁為準)。
前往歐易註冊
參考資料

歐易的介面、費率和規則會調整,如與本文不一致,請以歐易官網最新資訊為準。