#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ XAU-USDT-SWAP 挂单盯盘: 实时判断当前挂单价是否合理 - 拉取挂单 + 行情 + K线 + 订单簿 - 计算技术支撑/压力 (SMA/枢轴/24h高低/VWAP) - 评估: 挂单价相对现价/支撑/压力的位置, 止损止盈空间, 触发概率 - 只读, 不改动任何订单 用法: python -X utf8 xau_watch_order.py --dns-ip 198.18.0.0 """ import json, hmac, hashlib, base64, datetime, sys, os, argparse, subprocess HERE = os.path.dirname(os.path.abspath(__file__)) KEYS_FILE = os.path.join(HERE, "okx_keys.json") def load_keys(): with open(KEYS_FILE, "r", encoding="utf-8") as f: return json.load(f) def sign(secret, ts, method, path, body=""): pre = ts + method.upper() + path + body return base64.b64encode(hmac.new(secret.encode(), pre.encode(), hashlib.sha256).digest()).decode() def okx_get(path, keys, dns_ip): ts = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z" sig = sign(keys["secret"], ts, "GET", path, "") domain = "www.okx.com" cmd = ["curl", "-s", "--max-time", "15", "--resolve", f"{domain}:443:{dns_ip}"] cmd += ["-H", f"OK-ACCESS-KEY:{keys['api_key']}", "-H", f"OK-ACCESS-SIGN:{sig}", "-H", f"OK-ACCESS-TIMESTAMP:{ts}", "-H", f"OK-ACCESS-PASSPHRASE:{keys['passphrase']}", "-H", "Content-Type:application/json", "-H", "User-Agent:curl/8.5.0", f"https://{domain}{path}"] try: return json.loads(subprocess.run(cmd, capture_output=True, text=True, timeout=20).stdout) except Exception as e: return {"code": "-1", "msg": str(e)} def fmt(n, d=2): try: return f"{float(n):,.{d}f}" except Exception: return str(n) def main(): ap = argparse.ArgumentParser() ap.add_argument("--dns-ip", default="198.18.0.0") args = ap.parse_args() keys = load_keys() D = args.dns_ip # 1. 挂单 o = okx_get("/api/v5/trade/orders-pending?instType=SWAP", keys, D) orders = [x for x in o.get("data", []) if x.get("instId") == "XAU-USDT-SWAP" and x.get("state") == "live"] if not orders: print("当前无 XAU 活跃挂单") return ord0 = orders[0] px = float(ord0["px"]); sz = float(ord0["sz"]); lev = float(ord0["lever"]) tp = float(ord0["attachAlgoOrds"][0]["tpOrdPx"]); sl = float(ord0["attachAlgoOrds"][0]["slTriggerPx"]) # 2. 行情 t = okx_get("/api/v5/market/ticker?instId=XAU-USDT-SWAP", keys, D)["data"][0] last = float(t["last"]); high24 = float(t["high24h"]); low24 = float(t["low24h"]) open24 = float(t["open24h"]); sod = float(t["sodUtc8"]) # 3. K线 c = okx_get("/api/v5/market/candles?instId=XAU-USDT-SWAP&bar=1H&limit=60", keys, D)["data"] cls = [float(x[4]) for x in c]; lows = [float(x[3]) for x in c]; highs = [float(x[2]) for x in c] sma20 = sum(cls[:20]) / 20; sma50 = sum(cls[:50]) / 50 lo12 = min(lows[:12]); hi12 = max(highs[:12]) pivot = (high24 + low24 + last) / 3 s1 = 2 * pivot - high24; r1 = 2 * pivot - low24 # 4. 订单簿 b = okx_get("/api/v5/market/books?instId=XAU-USDT-SWAP&sz=400", keys, D)["data"][0] bids = b["bids"]; asks = b["asks"] def cum_bid(px_ref): s = 0.0 for p, sz_, *_ in bids: if float(p) >= px_ref: s += float(sz_) return s def cum_ask(px_ref): s = 0.0 for p, sz_, *_ in asks: if float(p) <= px_ref: s += float(sz_) return s buy_liq = cum_bid(px) # 挂单价下方买盘支撑量(可吸单) ask_above = cum_ask(px) # 挂单价上方卖盘压力量 # 判断逻辑 below_mid = pivot - sma20 # 多空分界偏离 px_vs_last = (px - last) / last * 100 dist_to_sl = (px - sl) / px * 100 dist_to_tp = (tp - px) / px * 100 dist_to_low = (px - low24) / low24 * 100 dist_to_high = (high24 - px) / px * 100 in_24h_range = low24 <= px <= high24 now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") print("=" * 70) print(f"XAU-USDT-SWAP 挂单盯盘 {now}") print("=" * 70) print(f"挂单: 买入 {int(sz)} 张 @ {fmt(px)} 杠杆 {int(lev)}x 状态 live") print(f" 名义价值 ~ {fmt(sz*0.001*px)} USDT 止损 {fmt(sl)} 止盈 {fmt(tp)}") print("-" * 70) print(f"现价 last : {fmt(last)}") print(f"24h 区间 : {fmt(low24)} ~ {fmt(high24)} (振幅 {fmt((high24-low24)/low24*100)}%)") print(f"今日开盘UTC8: {fmt(sod)} 24h开盘 {fmt(open24)}") print(f"SMA20 {fmt(sma20)} SMA50 {fmt(sma50)} | 枢轴P {fmt(pivot)} S1(支撑) {fmt(s1)} R1(压力) {fmt(r1)}") print(f"近12h 区间 : {fmt(lo12)} ~ {fmt(hi12)}") print("-" * 70) print("【挂单价 4635 位置评估】") print(f" - 相对现价: {px_vs_last:+.2f}% (现 {fmt(last)}, 挂单在 {'下方(等回调)' if px= 1.5: score += 2; notes.append(f"止损空间 {dist_to_sl:.2f}% 充足") elif dist_to_sl >= 1.0: score += 1; notes.append(f"止损空间 {dist_to_sl:.2f}% 偏紧") else: score -= 2; notes.append(f"止损空间仅 {dist_to_sl:.2f}%, 30x下极易被扫(小于正常波动)") if abs(dist_to_tp / dist_to_sl) >= 1.5: score += 1; notes.append("盈亏比合理(>=1.5)") else: score -= 1; notes.append("盈亏比偏低(<1.5), 期望不占优") if buy_liq >= sz * 0.5: score += 1; notes.append("挂单价下方买盘充足, 成交后不易立刻被砸") else: score -= 1; notes.append("挂单价下方买盘支撑偏弱") verdict = "✅ 合适" if score >= 4 else ("⚠️ 一般, 需优化" if score >= 1 else "❌ 不合适") print(f"综合评分: {score}/8 → {verdict}") for n in notes: print(f" · {n}") print("=" * 70) if __name__ == "__main__": main()