Files
Trade/xau_watch_order.py
2026-08-26 15:07:04 +08:00

166 lines
7.0 KiB
Python

#!/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<last else '上方(追高)'})")
print(f" - 相对24h低: +{dist_to_low:.2f}% 距24h高: -{dist_to_high:.2f}%")
print(f" - 相对枢轴P: {'下方(偏弱)' if px<pivot else '上方(偏强)'} 相对SMA20: {'下方' if px<sma20 else '上方'}")
print(f" - 是否在24h区间: {'是(区间内)' if in_24h_range else '否'}")
print(f" - 挂单价下方买盘支撑量: {fmt(buy_liq)} 张 上方卖盘压力量: {fmt(ask_above)} 张")
print("-" * 70)
print("【止损/止盈空间】")
print(f" 止损 {fmt(sl)}: 距买入价 {dist_to_sl:.2f}% (30x下= {(dist_to_sl*lev):.0f}%保证金风险)")
print(f" 止盈 {fmt(tp)}: 距买入价 +{dist_to_tp:.2f}% (需涨到 {fmt(tp)})")
print(f" 盈亏比 (TP/SL): {abs(dist_to_tp/dist_to_sl):.2f} : 1")
print("=" * 70)
# 综合评分与结论
score = 0
notes = []
if px < last and px >= s1:
score += 2; notes.append("挂单价在枢轴支撑S1上方、现价下方, 属回调接多合理区")
elif px < s1:
score += 1; notes.append("挂单价已跌破S1支撑, 偏激进(可能一路下行扫损)")
else:
score -= 1; notes.append("挂单价在现价上方=追高, 当前区间震荡不建议追")
if dist_to_sl >= 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()