python-okx 从装环境到跑通交易:一份不再踩坑的完整排障手册
【免费下载链接】python-okx项目地址: https://gitcode.com/GitHub_Trending/py/python-okx
你是不是也用 python-okx 下单时报过 401,或者 WebSocket 刚订阅就掉线?本手册按开发场景把排障拆成 4 组:接入与鉴权、REST 数据读写、实时通道、生产兜底,对号入座直接跳。
| 你看到的现象 | 跳到哪 | 一句话根因 |
|---|---|---|
| 安装报依赖冲突 | 1.1 | Python 版本低于 3.9 |
| 下单报 401 或连不上 | 1.2 | flag 没切对,实盘测试网串了 |
| 接口返回 401 / 403 | 1.3 | 密钥权限或 IP 白名单问题 |
| 签名验证失败 10000 | 1.4 | 系统时间与服务器偏差过大 |
| place_order 报精度错误 | 2.1 | 价格小数位超过合约 tick |
| 历史订单拉不全 | 2.2 | 分页 after 没循环翻页 |
| WebSocket code=1006 断连 | 3.1 | 没发心跳或订阅过多 |
| 私有频道登录失败 | 3.2 | 测试网 WS 地址写错 |
| 进程因异常直接退出 | 4.1 | 没按三类异常分别捕获 |
| 请求返回 429 | 4.2 | 频率超限没加 sleep |
| K 线接口被反复请求 | 4.3 | 没做本地缓存 |
接入与鉴权:版本检查、测试网切换、错误码排查
Python 低于 3.9,安装冲突怎么查
现象:群里喊"pip install python-okx 怎么装都报依赖冲突"。
根因:库要求 Python ≥ 3.9,低于这个版本会与 httpx 等依赖产生版本冲突。
下面这条命令先确认版本,达标后再装最新版:
python --version # 需 ≥ 3.9 pip install python-okx --upgrade实盘测试网 flag 怎么切
现象:"测试网 key 下单一直 401,明明密钥是对的"。
根因:flag 控制 x-simulated-trading 请求头,'0' 是实盘、'1' 是测试网;两边的密钥不能混用。
# ❌ 忘了传 flag:库默认 flag='1'(测试网),实盘 key 会打到测试网 client = TradeAPI(api_key=key, api_secret_key=secret, passphrase=passphrase) # ✅ 测试网 key 配测试网 client = TradeAPI(api_key=key, api_secret_key=secret, passphrase=passphrase, flag='1') # ✅ 实盘:flag='0'⚠️ flag 默认值是 '1',不传就是测试网。实盘 key 忘了传 flag 报 401,这个坑我见过太多次了。
401 / 403 三步排查
现象:"私有接口全 401,公共接口好好的"。
根因:401 基本是密钥与 flag 环境不匹配,或建密钥时没勾"交易"权限;403 则是当前出口 IP 不在该密钥的白名单里。按"环境匹配 → 权限 → IP 白名单"三步走,密钥从环境变量取而不是硬编码:
import os # ✅ 三件套从环境变量读,确认同一账户、同一环境 api_key = os.getenv("OKX_API_KEY") secret_key = os.getenv("OKX_SECRET_KEY") passphrase = os.getenv("OKX_PASSPHRASE") flag = os.getenv("OKX_FLAG", "1") # ← 注意:实盘要显式设 "0"10000 签名验证失败,先同步系统时间
现象:"同一套 key,官方 demo 能过,我这边报 10000"。
根因:签名是 timestamp + 请求方法 + 请求路径 + 请求体的 HMAC-SHA256,本地时钟和服务器偏差超过约 30 秒,签名就验证失败。
sudo ntpdate ntp.aliyun.com # ← 注意:先同步系统时间再重试REST 调用:参数精度与分页循环
place_order 精度报错,用 Decimal 修
现象:"40000.123 这个价怎么就下单报错了?"
根因:每个交易对有最小价格精度和最小下单量,BTC-USDT 的 tick 到不了 0.001,服务器直接拒单。
from decimal import Decimal # ❌ 裸 float,精度超过 tick size trade.place_order(instId="BTC-USDT", tdMode="cash", side="buy", ordType="limit", px=40000.123, sz=0.001) # ✅ 用 Decimal,小数位对齐合约精度 trade.place_order(instId="BTC-USDT", tdMode="cash", side="buy", ordType="limit", px=Decimal("40000.12"), sz=Decimal("0.001"))⚠️ float 的 0.1 + 0.2 等于 0.30000000000000004,拿去做 px 就是参数错误常客。
分页漏单循环写法
现象:"拉历史订单怎么少了一半"。
根因:单次最多返回 limit 条(上限 100),不循环传 after 游标就只拿到第一页。
all_orders, after = [], None while True: resp = trade.get_orders_history(instType="SPOT", after=after, limit="100") all_orders.extend(resp["data"]) if len(resp["data"]) < 100: break after = resp["data"][-1]["ordId"] # ← 注意:用本页最后一条 ordId 翻页WebSocket 实时通道:1006 断连与心跳
1006 断连:30 秒心跳 + 5 秒重连
现象:"跑了半小时,连接就 code=1006 断了"。
根因:1006 是异常关闭,多数是网络抖动或空闲超时,少数是单连接订阅频道过多超流量上限。需要每 30 秒发一次 ping,并在断线后 5 秒自动重连。
ws = WsPrivateAsync(api_key, passphrase, secret_key, ws_url) await ws.connect() await ws.subscribe([{"channel": "account"}], on_msg) async def heartbeat(): while True: await asyncio.sleep(30) await ws.websocket.send("ping") # ← 注意:每 30 秒发一次 asyncio.create_task(heartbeat()) # 心跳单独起任务 # 外层套 while True + except 后 await asyncio.sleep(5) 即 5 秒重连⚠️ 私有频道和公共频道建议拆两条连接,一条连接订阅过多是 1006 头号原因。
测试网 WS 地址怎么写
现象:"私有频道 login 一直失败"。
根因:测试网和生产是两套 WebSocket 地址,测试网在 wspap 子域下,混用生产地址必然登录失败。
# ❌ 生产地址 + 测试网 key url = "wss://ws.okx.com:8443/ws/v5/private" # ✅ 测试网:wspap 子域,带 brokerId url = "wss://wspap.okx.com:8443/ws/v5/private?brokerId=9999"生产兜底:异常捕获、限频与缓存
三类异常分别捕获,别让进程挂
现象:"网络抖了一下,策略进程直接没了"。
根因:库抛三类异常——OkxAPIException(API 返回错误,带 code/message)、OkxRequestException(网络层)、OkxParamsException(参数校验),只捕第一种会漏掉后两类。
from okx.exceptions import (OkxAPIException, OkxRequestException, OkxParamsException) try: trade.place_order(...) except OkxParamsException as e: print(f"参数错误: {e.message}") except OkxAPIException as e: print(f"API 错误: {e.code} - {e.message}") except OkxRequestException as e: # ← 注意:网络错误才进重试队列 schedule_retry()429 限频:加 100 毫秒 sleep
现象:"批量下单,第二单开始 429"。
根因:每个接口有独立频控,循环里裸调必撞限。串行场景每 0.1 秒一次,把整体压在 10 次/秒以内。
import time def rate_limited(trade, inst_id): time.sleep(0.1) # ← 注意:保持 ≥100ms 间隔 return market.get_ticker(instId=inst_id)K 线本地缓存写法
现象:"K 线接口被轮询打爆"。
根因:K 线更新频率低,每次渲染都请求是浪费额度,加一层 lru_cache 即可。
from functools import lru_cache @lru_cache(maxsize=100) def get_cached_candles(instId, bar): return market.get_candles(instId=instId, bar=bar)本手册覆盖环境接入、鉴权、REST 调用、实时通道、生产兜底 4 个场景的常见故障。 上手可跑 example/get_started_en.ipynb,回归看 test/unit/,版本变更记录在 CHANGELOG.md。
【免费下载链接】python-okx项目地址: https://gitcode.com/GitHub_Trending/py/python-okx
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考