#!/usr/bin/env python3
"""重挂OCO - net模式修复版: 平多止盈止损 side=sell, 不带posSide"""
import sys, time, hmac, hashlib, base64, json
import requests
from datetime import datetime, timezone

BASE = "https://www.okx.com"
INST = "BTC-USDT-SWAP"

def load_env(path='/root/.hermes/.env'):
    env = {}
    with open(path) as f:
        for line in f:
            line = line.strip()
            if line and '=' in line and not line.startswith('#'):
                k, v = line.split('=', 1)
                env[k.strip()] = v.strip().strip('"').strip("'")
    return env

env = load_env()
API_KEY = env['OKX_API_KEY']
SECRET = env['OKX_SECRET_KEY']
PASS = env['OKX_PASSPHRASE']

def okx(method, path, params=None, body=''):
    ts = datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
    qs = ''
    if params:
        qs = '?' + '&'.join(f"{k}={v}" for k, v in params.items())
    full = path + qs
    msg = ts + method + full + body
    sig = base64.b64encode(hmac.new(SECRET.encode(), msg.encode(), hashlib.sha256).digest()).decode()
    headers = {'OK-ACCESS-KEY': API_KEY, 'OK-ACCESS-SIGN': sig,
               'OK-ACCESS-TIMESTAMP': ts, 'OK-ACCESS-PASSPHRASE': PASS,
               'Content-Type': 'application/json'}
    r = requests.request(method, BASE + full, headers=headers, data=body if body else None, timeout=15)
    return r.json()

def get_position():
    r = okx('GET', '/api/v5/account/positions', params={'instId': INST})
    if r.get('code') != '0':
        return None
    for p in r.get('data', []):
        if p.get('instId') == INST and float(p.get('pos', 0)) != 0:
            return p
    return None

# 尝试1: 不带posSide
def attach_oco_no_posside(sz, tp, sl):
    body = {
        "instId": INST,
        "tdMode": "isolated",
        "sz": str(sz),
        "tpTriggerPx": str(tp),
        "tpOrdPx": "-1",
        "slTriggerPx": str(sl),
        "slOrdPx": "-1",
        "ordType": "conditional",
        "side": "sell",
    }
    r = okx('POST', '/api/v5/trade/order-algo', body=json.dumps(body))
    print("OCO(no posSide):", json.dumps(r, ensure_ascii=False))
    if r.get('code') == '0':
        print(f"✅ OCO挂载成功 algoId={r['data'][0].get('algoId')}")
        return True
    print(f"❌ 失败: {r.get('msg')}")
    return False

if __name__ == '__main__':
    p = get_position()
    if not p:
        print("NO_POSITION - 无法挂OCO")
        sys.exit(1)
    print("当前持仓:", json.dumps(p, ensure_ascii=False)[:300])
    pos = float(p['pos'])
    sz = abs(pos)
    print(f"持仓量: {sz} 张, 方向: {'多' if pos > 0 else '空'}")
    if pos < 0:
        print("⚠️ 当前是空头持仓，本脚本只处理多头OCO")
        sys.exit(1)
    tp, sl = 63350, 63060
    ok = attach_oco_no_posside(sz, tp, sl)
    if not ok:
        # 尝试2: posSide=net
        body = {
            "instId": INST, "tdMode": "isolated", "posSide": "net",
            "sz": str(sz), "tpTriggerPx": str(tp), "tpOrdPx": "-1",
            "slTriggerPx": str(sl), "slOrdPx": "-1",
            "ordType": "conditional", "side": "sell",
        }
        r = okx('POST', '/api/v5/trade/order-algo', body=json.dumps(body))
        print("OCO(posSide=net):", json.dumps(r, ensure_ascii=False))
        if r.get('code') == '0':
            print(f"✅ OCO挂载成功 algoId={r['data'][0].get('algoId')}")
            ok = True
        else:
            print(f"❌ 失败: {r.get('msg')}")
    sys.exit(0 if ok else 2)
