python-okx 是 OKX v5 REST 与 WebSocket API 的 Python 客户端,适合用 Python 打通行情获取、下单撤单和持仓管理链路。下面围绕模拟盘下单、模块分工、双均线信号和常见报错,整理一条可落地的实现路径。
一、模拟盘密钥与签名边界
在 OKX 控制台为模拟盘单独创建一组密钥,不要与实盘密钥混用。私有请求需要 api_key、secret、passphrase 三要素;签名由库内部完成:okxclient.py 在每次私有请求前,将时间戳、请求方法、请求路径与请求体拼接,使用 HMAC-SHA256 加 secret 生成摘要,再写入 OK-ACCESS-SIGN 等请求头。业务代码只需传入密钥,不需要手工处理签名细节。行情类公共接口则完全不需要密钥。
二、安装依赖并发出第一笔模拟盘订单
安装依赖后,初始化 TradeAPI 并调用 place_order。flag='1' 表示模拟盘,flag='0' 表示实盘,建议先用模拟盘验证流程。place_order 的参数与 OKX v5 下单接口一一对应,必传项包括交易标的、保证金模式、买卖方向、订单类型与数量。
- import okx.Trade as Trade
- trade_api = Trade.TradeAPI(
- api_key='your-api-key',
- api_secret_key='your-api-secret',
- passphrase='your-passphrase',
- flag='1', # 1 = 模拟盘, 0 = 实盘
- )
- result = trade_api.place_order(
- instId='BTC-USDT',
- tdMode='cash',
- side='buy',
- ordType='market',
- sz='1',
- )
- print(result)
复制代码
返回值是一个列表包裹的结果结构,顶层 code 为 '0' 表示请求成功,data[0] 中携带 ordId 与 sCode、sMsg。判断是否真正成交时,应同时检查顶层 code 和 data[0] 中的 sCode、sMsg,而不是只看 HTTP 层面有没有抛异常。
三、四个核心模块的分工
TradeAPI 对应 Trade.py,负责下单、撤单、改单、批量下单,以及订单与成交明细查询。AccountAPI 对应 Account.py,负责账户余额、持仓、杠杆设置、账单与保证金查询。MarketAPI 对应 MarketData.py,负责最新成交价、订单簿深度、K 线与历史行情。WebSocketFactory.py 下的 WebSocket 模块负责公共频道行情推送与私有频道订单、持仓状态更新。
REST 接口按请求—响应同步取数,适合低频轮询;行情订阅或需要实时感知订单状态的场景,改用 WebSocket 模块,由交易所主动推送,可省去高频轮询带来的限流风险。
四、instId 命名与订单类型选择
instId 要按品种写清楚:BTC-USDT 是现货交易对,BTC-USDT-SWAP 是永续合约,BTC-USDT-240329 是交割合约,尾部为交割日期。tdMode 在现货模式用 cash,合约则用 cross 或 isolated。
ordType 的差异也要注意:market 表示立即按最优价成交,适合快速建仓平仓,无需传 px;limit 表示按指定价格挂单,必须同时传 px;post_only 表示只做 maker 挂单,若会立即吃单则直接被拒。
sz 的单位因品种而异:现货以基础币数量计,合约以张数计。下单前建议先通过 PublicData 模块查询对应品种的最小下单量与数量精度,避免因单位或精度问题被拒单。
五、从双均线信号到下单
以双均线交叉为例,流程是取 K 线、计算均线、生成信号、调用下单接口。先用 MarketAPI 拉取 K 线,算出快慢两条均线,金叉发买入信号、死叉发卖出信号,信号再交给 place_order 执行。
get_candlesticks 的 bar 参数控制周期,例如 1H、1D;返回数组每行按时间戳、开、高、低、收、成交量排列,收盘价在第 4 位,且默认按时间倒序返回。
- import okx.MarketData as MarketData
- market_api = MarketData.MarketAPI(flag='1')
- def ma_signal(instId, fast=5, slow=20):
- resp = market_api.get_candlesticks(instId=instId, bar='1H', limit=str(slow + 10))
- if resp['code'] != '0':
- return None
- closes = [float(row[4]) for row in resp['data']]
- fast_ma = sum(closes[-fast:]) / fast
- slow_ma = sum(closes[-slow:]) / slow
- return 'buy' if fast_ma > slow_ma else 'sell'
复制代码
拿到 buy 或 sell 信号后,直接调用前文初始化好的 trade_api.place_order 完成执行。策略落地时还有三条底线值得提前写进代码:单笔下单金额控制在总资金的小比例以内;开仓时通过 attachAlgoOrds 附带条件单作为止损;策略主循环设置最小间隔,K 线等公共接口连续请求之间也加入短暂延迟,避免触发频率限制。
六、容易踩的三个坑
签名或时间戳报错:常见现象是返回签名错误或时间戳非法,多因本地时钟与服务器偏差过大。对策是先把系统时钟同步到 NTP 时间源,再继续排查其他原因。
模拟盘与实盘密钥混用:模拟盘创建的密钥只对 flag='1' 有效,拿去实盘调用会直接鉴权失败。对策是两套密钥物理隔离,并在配置里显式标注用途。
数量单位与精度误用:现货 sz 按币数、合约按张数,且不同品种的最小下单量与精度不同,填错会导致拒单或仓位偏差。对策是下单前先拉取该品种的合约详情做校验。
七、后续可探索的方向
okx/websocket/ 下的 WsPublicAsync 与 WsPrivateAsync 提供了行情与订单状态的异步订阅,适合作为轮询方案的升级路径;仓库 example/ 目录中还有两份 Jupyter notebook,分别演示入门流程与合约交易,可以作为对照材料。若策略趋于复杂,再把 K 线数据落盘存储、接入回测框架,会比直接在实盘上调参稳妥得多。 |