From d7fa60a4ee98e878c6f18ddff5b3b755d9cbf623 Mon Sep 17 00:00:00 2001 From: mike Date: Fri, 25 Sep 2026 01:26:31 +0800 Subject: [PATCH] =?UTF-8?q?okx-auto-position:=20templates=20=E7=9B=AE?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/manual_order_template.py | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 okx-auto-position/templates/manual_order_template.py diff --git a/okx-auto-position/templates/manual_order_template.py b/okx-auto-position/templates/manual_order_template.py new file mode 100644 index 0000000..7a2caa8 --- /dev/null +++ b/okx-auto-position/templates/manual_order_template.py @@ -0,0 +1,103 @@ +""" +手动 raw REST OKX 下单模板 (用于 advisor execute 失败/proxy 抽风时手动救火) + +用法: +1. 复制本文件到 /tmp/order_.py +2. 修改 body 字段 (instId/side/sz/ordType/tdMode/posSide/reduceOnly) +3. python3 /tmp/order_.py + +注意事项: +- 用 127.0.0.1:7890 proxy (国内 VPS 必走, GFW 屏蔽) +- 凭证从 ~/.bashrc 读 (export OKX_API_KEY/SECRET/PASSPHRASE) +- 永不复用 cost_performance / advisor 的 ccxt 路径 (proxy 抽风时 SSL 不稳) +- 只在 process_signal 走 raw REST 失败时手动救火, 不要做"测试" +- 下单成功后必须手记 position_history (audit trail, 防 ghost close) +- 调杠杆失败 (OKX 59108 = 账户余额不足) 不要无限重试 + +已知踩坑币种 (advisor execute 隐性失败): SPCX / 1000PEPE / MU / XAU / BTC / SKHYNIX +""" +import json, time, hmac, hashlib, base64, requests + + +def okx_post(p, body, t=15): + creds = open('/home/openclaw/.bashrc').read() + k = s = pw = None + for line in creds.splitlines(): + if line.startswith('export OKX_API_KEY='): + k = line.split('=', 1)[1].strip().strip('"').strip("'") + elif line.startswith('export OKX_SECRET='): + s = line.split('=', 1)[1].strip().strip('"').strip("'") + elif line.startswith('export OKX_PASSPHRASE='): + pw = line.split('=', 1)[1].strip().strip('"').strip("'") + body_str = json.dumps(body) + ts = time.strftime('%Y-%m-%dT%H:%M:%S.000Z', time.gmtime()) + msg = ts + 'POST' + p + body_str + sig = base64.b64encode(hmac.new(s.encode(), msg.encode(), hashlib.sha256).digest()).decode() + h = { + 'OK-ACCESS-KEY': k, + 'OK-ACCESS-SIGN': sig, + 'OK-ACCESS-TIMESTAMP': ts, + 'OK-ACCESS-PASSPHRASE': pw, + 'Content-Type': 'application/json' + } + px = {'http': 'http://127.0.0.1:7890', 'https': 'http://127.0.0.1:7890'} + return requests.post(f'https://www.okx.com{p}', data=body_str, headers=h, proxies=px, timeout=t).json() + + +# ===== 常用下单模板 ===== + +def open_long(inst_id, sz): + """开多 (跟单信号方向=做多)""" + body = {'instId': inst_id, 'tdMode': 'cross', 'side': 'buy', 'posSide': 'net', 'ordType': 'market', 'sz': str(sz)} + return okx_post('/api/v5/trade/order', body) + + +def open_short(inst_id, sz): + """开空""" + body = {'instId': inst_id, 'tdMode': 'cross', 'side': 'sell', 'posSide': 'net', 'ordType': 'market', 'sz': str(sz)} + return okx_post('/api/v5/trade/order', body) + + +def close_long(inst_id, sz): + """平多 (买入平仓)""" + body = {'instId': inst_id, 'tdMode': 'cross', 'side': 'sell', 'posSide': 'net', 'ordType': 'market', 'sz': str(sz), 'reduceOnly': True} + return okx_post('/api/v5/trade/order', body) + + +def close_short(inst_id, sz): + """平空 (买入平仓)""" + body = {'instId': inst_id, 'tdMode': 'cross', 'side': 'buy', 'posSide': 'net', 'ordType': 'market', 'sz': str(sz), 'reduceOnly': True} + return okx_post('/api/v5/trade/order', body) + + +def adjust_leverage(inst_id, lev): + """调杠杆 (路径不同: /api/v5/account/set-leverage)""" + body = {'instId': inst_id, 'lever': str(lev), 'mgnMode': 'cross', 'posSide': 'net'} + return okx_post('/api/v5/account/set-leverage', body) + + +# ===== 实战示例 ===== + +if __name__ == '__main__': + import sys + + # 用法: python3 /tmp/order_xxx.py + # action: open_long / open_short / close_long / close_short / adjust_leverage + if len(sys.argv) >= 4: + action, inst_id, sz = sys.argv[1], sys.argv[2], sys.argv[3] + if action == 'open_long': + print(json.dumps(open_long(inst_id, sz), ensure_ascii=False, indent=2)) + elif action == 'open_short': + print(json.dumps(open_short(inst_id, sz), ensure_ascii=False, indent=2)) + elif action == 'close_long': + print(json.dumps(close_long(inst_id, sz), ensure_ascii=False, indent=2)) + elif action == 'close_short': + print(json.dumps(close_short(inst_id, sz), ensure_ascii=False, indent=2)) + elif action == 'adjust_leverage': + print(json.dumps(adjust_leverage(inst_id, sz), ensure_ascii=False, indent=2)) + else: + print(f"Unknown action: {action}") + else: + print("用法: python3 /tmp/order_xxx.py ") + print("action: open_long / open_short / close_long / close_short / adjust_leverage") + print("示例: python3 /tmp/order_btc.py close_long BTC-USDT-SWAP 1.43") \ No newline at end of file