Files
Hermes-Skills/okx-auto-position/references/okx-api-pitfalls.md
T
mike 657dc41c46 Initial commit: Trading skills collection
- OKX交易自动化 (okx-auto-position, okx-crypto, okx-exchange)
- 交易信号处理 (signal-confirmation-templates, trading-signal-aggregator)
- 量化因子挖掘 (quant-factor-mining)
- 长桥集成 (longbridge-cli, longbridge-python-sdk)
- 六合彩分析 (lottery-hk)
- 股息投资 (dividend-investing, dividend-scanner)
- 日内交易 (intraday-trading)
- 同花顺 (tonghuashun)
2026-07-05 02:39:41 -04:00

176 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OKX API 关键Pitfalls
## 1. posMode=net_mode vs long_short_mode
**问题**:账户可能是 `net_mode`(净头寸)而非 `long_short_mode`(多空分离)。
**检查方法**
```python
GET /api/v5/account/config
# 响应中 "posMode": "net_mode" 或 "long_short_mode"
```
**影响**
- `net_mode`**禁止传 `posSide` 参数**,否则报错 `sCode=51000 "Parameter posSide error"`
- `long_short_mode`**必须传 `posSide`** (long/short)
**下单示例(net_mode**
```python
{
"instId": "ETH-USDT-SWAP",
"tdMode": "cross",
"side": "buy", # buy=开多/平空, sell=开空/平多
"ordType": "market",
"sz": "1" # 不传posSide
}
```
**设置杠杆(net_mode**
```python
{
"instId": "ETH-USDT-SWAP",
"lever": "25",
"mgnMode": "cross" # 不传posSide
}
```
**切换模式**(需要主账户权限):
```python
POST /api/v5/account/set-position-mode
{"posMode": "long_short_mode"} # 或 "net_mode"
```
---
## 2. OCO订单合并(加仓场景)
**问题**:加仓后,旧OCO只覆盖旧仓位,新OCO只覆盖新仓位,导致多个OCO并存。
**错误示例**
- 持仓5张,OCO(sell 5, SL=1660, TP=1746)
- 加仓1张 → 持仓6张
- 新建OCO(sell 1, SL=1666.8, TP=1775.1)
- 结果:2个OCO并存,旧OCO触发只平5张,剩1张单独走
**正确流程**
1. 查现有OCO`GET /api/v5/trade/orders-algo-pending?ordType=oco`
2. 找到同instId的旧OCO algoId
3. 删除旧OCO`POST /api/v5/trade/cancel-algo``[{instId, algoId}]`
4. 创建新OCO覆盖全部持仓
**验证**
```bash
# 查pending OCO
curl -X GET "https://www.okx.com/api/v5/trade/orders-algo-pending?ordType=oco" \
-H "OK-ACCESS-KEY: $KEY" ...
# 应该只有一个OCO per instId
```
---
## 3. 补推信号必须先查持仓
**场景**:模型断线后补推积压信号。
**错误做法**:直接用历史信号数据推送推荐(如"4,290 ETH加仓到4,455")。
**正确做法**
1. 先查当前持仓:`GET /api/v5/account/positions`
2. 再查当前algo orders`GET /api/v5/trade/orders-algo-pending?ordType=oco`
3. 用**当前持仓数据**而非历史信号数据生成推荐
**案例**
- 历史信号说"4,290 ETH"
- 实际持仓已是5张(可能中间已有多次变动)
- 用历史数据推"加仓到4,455"是错误的
---
## 4. 遍历查询algo orders
**问题**`ordType` 参数不能组合查询,需逐个类型查。
```python
for algo_type in ["oco", "conditional", "trigger", "move_order_stop"]:
result = okx_get(f"/api/v5/trade/orders-algo-pending?ordType={algo_type}")
# 处理 result["data"]
```
**注意**:某些类型可能返回错误(如账户未开通该功能),需忽略错误继续。
---
## 5. 密码中含特殊字符
**问题**`OKX_PASSPHRASE``$` 等特殊字符时,bash 会尝试变量展开。
**错误**`export OKX_PASSPHRASE=mikeOkxID$1``$1` 展开为空
**正确**
```bash
export OKX_PASSPHRASE='mikeOkxID$1' # 单引号
```
**或从文件读取**
```python
with open("~/.bashrc", "r") as f:
for line in f:
if "OKX_PASSPHRASE" in line:
passphrase = line.split("=", 1)[1].strip().strip('"').strip("'")
```
---
## 6. 凭证变量名:OKX_SECRET(不是OKX_SECRET_KEY
bashrc里实际变量名是 `OKX_SECRET`,不是 `OKX_SECRET_KEY`
**脚本内部**`load_credentials()``OKX_\w+` 正则匹配,自动兼容,不受影响。
**手动ccxt初始化**agent写临时Python时):
```python
# ❌ 错误 — 会 KeyError
creds['OKX_SECRET_KEY']
# ✅ 正确
creds['OKX_SECRET']
# ✅ 兼容写法
secret = creds.get('OKX_SECRET', '') or creds.get('OKX_SECRET_KEY', '')
```
**三个变量**`OKX_API_KEY``OKX_SECRET``OKX_PASSPHRASE`
---
## 7. --execute 必须同时带 --rec-json
脚本代码 `if args.execute and args.rec_json:` 要求两个参数同时存在。
**错误**:只传 `--execute` 不传 `--rec-json` → 静默跳过执行,fall through到推荐流程
**正确两步流程**
```bash
# 第1步:获取推荐JSON
python3 okx_position_advisor.py --symbol HYPE --side long --leverage 10 --json > /tmp/rec.json
# 第2步:执行下单(必须同时带 --execute 和 --rec-json
python3 okx_position_advisor.py --symbol HYPE --side long --leverage 10 --execute --json --rec-json "$(cat /tmp/rec.json)"
```
---
## 8. 余额为零时ZeroDivisionError
**问题**`recommend_position()` 函数在计算 `margin_pct = total_margin / acct_info['usdt_free'] * 100` 时,如果 `usdt_free=0`(用户满仓),会抛出 `ZeroDivisionError`
**修复**:在调用 `recommend_position()` 前检查余额:
```python
if acct_info['usdt_free'] < 0.01:
print("⚠️ 余额不足(可用0 USDT),无法开仓")
sys.exit(0)
```
**format_signal.py 已加 try/except 处理此场景。**