提交
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user