From a431c4bcb63dfdef4fc7bfd2b46fbd02c1a43cfe Mon Sep 17 00:00:00 2001 From: pvistely Date: Wed, 26 Aug 2026 12:25:21 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 0 -> 6148 bytes OKX持仓风险清单.md | 57 +++++++ __pycache__/crypto_watch.cpython-312.pyc | Bin 0 -> 3250 bytes __pycache__/okx_monitor.cpython-312.pyc | Bin 0 -> 10556 bytes crypto_watch.py | 83 ++++++++++ okx_keys.json | 5 + okx_monitor.py | 199 +++++++++++++++++++++++ stock_watch.py | 106 ++++++++++++ stx_sim.py | 92 +++++++++++ 行云科技300209盯盘清单.md | 64 ++++++++ 10 files changed, 606 insertions(+) create mode 100644 .DS_Store create mode 100644 OKX持仓风险清单.md create mode 100644 __pycache__/crypto_watch.cpython-312.pyc create mode 100644 __pycache__/okx_monitor.cpython-312.pyc create mode 100644 crypto_watch.py create mode 100644 okx_keys.json create mode 100644 okx_monitor.py create mode 100644 stock_watch.py create mode 100644 stx_sim.py create mode 100644 行云科技300209盯盘清单.md diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a292f56e49e07b1b584c4550f1aadb55b0d12f63 GIT binary patch literal 6148 zcmeHKJ8r`;3?&;60kUMws4L_KLXe&y2XONPG8k}yqC+=NIaiL>$IoK8-JB(O1gIxb zd=m5q(-aZieP6aBYY|z(4drgb)NJ2;Vs9ByARK3$tC`N@F;svGyp96)eJF6lnm7ddrvrnx0Kf)e zH_W}402T`XYvK@y2uy*H-`E;s5miV-i 快照时间:2026-08-25 晚间 | 数据来源:OKX 只读监控 +> ⚠️ 本清单为个人风险控制参考,实盘调整需在 OKX 手动执行。 + +## 一、当前持仓明细 + +| 字段 | 数值 | +|------|------| +| 标的 | XAU-USDT-SWAP(黄金永续) | +| 方向 | 净多 LONG | +| 持仓量 | 898 张 | +| 开仓均价 | 4,636.6 | +| 杠杆 | **30x(高)** | +| 保证金模式 | 逐仓 isolated | +| 占用保证金 | 138.79 USDT | +| 强平价 | **4,502.41** | +| 浮动盈亏 | -2.16 USDT(-1.55%) | +| 总权益 | 404.62 USDT | + +## 二、实时风险测算(监控脚本输出) + +- 现价:4633.20 +- 距强平价:**2.82%** ← 已进入紧急预警区(≤3%) +- 含义:黄金再跌约 2.8% 即触发强平,30x 杠杆下缓冲极薄 + +## 三、关键价位对照 + +| 价位 | 类型 | 与持仓关系 | +|------|------|-----------| +| 4,750 | 前高目标 | 突破可止盈 | +| 4,699 | 24h高/压力 | 减半仓区 | +| 4,636.6 | 你的开仓价 | 现价附近,平盘 | +| 4,633 | 现价 | 微亏持仓中 | +| 4,580~4,610 | 埋伏低吸区 | 若未持仓可加仓区 | +| **4,502.41** | **强平价** | **破则爆仓清零该仓** | +| 4,500 | 建议止损 | ≈强平,无缓冲 | + +## 四、风险等级:🔴 高 + +**核心问题:止损位(4500)≈ 强平价(4502),没有手动逃生空间。** +30x 逐仓下,价格到 4502 直接爆仓,无法减仓。 + +## 五、建议动作(按优先级) + +1. **降杠杆**:30x → 10x 以内,强平价会下移、缓冲增厚 +2. **减仓**:平掉部分(如留 300 张),释放保证金 +3. **会议前(8/26 前)降风险**:杰克逊霍尔 8/27-29,偏鹰易快速下探 +4. **盯紧强平价 4502**:监控已设"距强平≤3% 每小时弹紧急通知" + +## 六、自动监控状态 + +- 任务 `com.user.okxmonitor` 每 5 分钟运行 +- 触发规则: + - 浮亏 > 50 USDT → 浮亏预警 + - 有持仓 → 每日一次持仓监控(含强平价) + - **距强平 ≤ 3% → 每小时紧急通知** ✅ 已触发 diff --git a/__pycache__/crypto_watch.cpython-312.pyc b/__pycache__/crypto_watch.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0c8a2ce5517968a5cfb9aec0f123e99840966e0f GIT binary patch literal 3250 zcmai0Z*UXG72mzn>F@c!u)yww!;oN2u*KhCTxw###D!u=Y|6wGG>7hN%gB;?cfyt` zIwmo}1{2E!YJnlhO(+U~Jrf3;02BDeO#8tGW>7BvkeOJr`BVdCO7p32CChd_?exvu z?%RED-@bkO-f!=(85u?dGXCp2%7yE3vZv~)WKY-A z0xf6+M$ig6L4S@G41!TG5w4LESQuvrnL-vwvy;*skmk-v8>xB?g+%7c)OPh+A+H0~ z>jX2jdSM>42GJ5oe?=dVj#)l5a&vi~5y&OLl9q+#}-XEUm zIGZ?kl`D>ad1CxjbmF6d@r%*Kz$b~%Z&{5cT;lX#;>7jDx1n;5EWO?pKXNsGw>|Oc z#dyyboWLu53Ga25?svL*w?iyF=#-rvHyAr|;(+K+8o1H3Cf@nUvy&GRU$iGKT#Sc0 zz|i=m6XTx_j@`Na_q*Nk-g{$1*Pi{kW8&IhU?$#qCVuxDu7!8(sO6rupB=w&5&T%& zwsJK$@m*+Qpu0GAhD2Xv>~62s_>4rPM%8Vs+qA28bDc^9<7_X($fpIt_~pank(<7S zguQZRZ0K0o*w9h3>5;D!Uq>fy9giRTE`I0M_?>H3T4lVF(;=#~!Z$+W^g3TJnKBda z|9oQbV_zYdnYi5z7T1=pNf`nwiH@GcsT+xtyXdW9I3rmI`SPYcTD^Sva^lh5Z^0Mm)eI0WnBHgAnw0Qp&)A*MCN6yxzj48VL7FBV zFf@EG{{~GTGC=YLQ9n9Q9m2}AUNeSweOIz$PE zAaxK+*pDDJk&8Y=2kBZYtBkdljD~+C4tS>r+&XBDN{2j;O&*z*OYoWo0Kxh$4x^ zPc=+WSaqsV_U-pd9)~E)DlPfkaPf)&>r_p%>~X7%%fkz@$}~W)sD`RGhv-$HGOUb5 z07Iq0Ih6)|X+9ZZL1v)m2)$YdoNbpZO0q4`#Jd}zwrug+7su|M8}Gj!zjxZUaeHm$ z&egU$i5EnhL-KnSkG+*w98INOzp78>u-(%jabV{y_~buA(~c&o48|PG-um#JhsDF0 zwVm{6=KLOamphh`7pe=dkLE=k!|cjf;lhY8xbYthon`!|7MXIo-kQ`Q13Rfl?1BhA zVp<%_v;3sbi?P`~Tf4S~I8GusqiU13{nDE-SPP%L z44QT{s>wWBbGRn7En<%4FN@Yjs|Me=&kVH=Z>b+P?}0#>_u^L&wte^|=pzSd(nQKA z8JJ?&=qLlBNlVawEAD2JO>-#y9yAlkm_upVF-A$hXGmH$Q@ou_1H5J(`WfkFlwOk# zxNM%0HUo&wrL;aqN@iNN8ST9c(1Mhl^h^*5)NGhIgoC&pcbj3JCiAeOhk#L9FM0Wt zzz`YXyBGjJ2B3**CI~x+2+UoXN;pX$#KEbR2Y!c;TQ_T50DEWzEdU;pvOr5q>Gb*37+PKj35>= z`!xdbD|<@Lq)&xWcdrI@U)7NG&#C#3w}PPhD)?T$3(aY~4PmIUAleJ=kuWz;zZW2$ zqONHy{}b-RVBA6sU!wt^ag7zLdeJS&q;LRGsnX>tJ^)qW5qQ5$vX$f7lNIr^VSS_M z7Tdg1MZnU+JKd%0T^46*n876jVI1 zRE+AgdNR5)y0gYIa$lefrWyk6_o$F$(IhKsJt11n$_>e1E`4ONj%Hi> zOueS?rYG6lXm);heq>RkYM?k$5M2pdYQJ(u_Y7Os#R>|;Th3U+g^}v$`%yXi-eB2K z<&gMI^-%e+Wy>oX=Tzh8ImG$r269e`ymG4EZYLqM+pQ*5XSWL;huxln>*YjD%YIpU zC&h`1MCu@UW666;#+_IoXm7WFg_0&yxvO8_;t_lwX$-7&)MoTZkNYoOYh=f%jBdHl_G-3x6dHoqvM@IL&)n1`$JbA* NN48ATNK=sX{NF9-hJOG6 literal 0 HcmV?d00001 diff --git a/__pycache__/okx_monitor.cpython-312.pyc b/__pycache__/okx_monitor.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b3f6f366440475250d75701abaeae4ba01b8486c GIT binary patch literal 10556 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 twv*eso;*rOK02!hB{{qEaO|}34 literal 0 HcmV?d00001 diff --git a/crypto_watch.py b/crypto_watch.py new file mode 100644 index 0000000..dba4bdb --- /dev/null +++ b/crypto_watch.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +币圈自动盯盘脚本 (复用股票框架) +- 数据源: 币安公开接口 data-api.binance.vision (免key) +- 每5分钟检查各币种现价,命中预警价则弹 macOS 通知 +- 7x24 运行(币圈无休) +""" +import subprocess +import datetime +import sys + +# ===== 监控配置: 在下面加币种和预警价 ===== +# symbol 用币安格式 (BTCUSDT), alert 为你要监控的价位与提示 +WATCH = [ + { + "symbol": "BTCUSDT", "name": "BTC", + "alerts": [ + {"price": 80000, "tag": "突破", "tip": "站上8万,关注趋势延续"}, + {"price": 75000, "tag": "回调", "tip": "跌破7.5万,注意支撑"}, + ], + }, + { + "symbol": "ETHUSDT", "name": "ETH", + "alerts": [ + {"price": 4000, "tag": "突破", "tip": "站上4000,强势"}, + {"price": 3500, "tag": "回调", "tip": "跌破3500,减仓观察"}, + ], + }, + # 复制上面结构可继续添加, 例如: + # {"symbol": "SOLUSDT", "name": "SOL", + # "alerts": [{"price": 200, "tag": "突破", "tip": "SOL站上200"}]}, +] + +ALERTED = set() + + +def price_of(symbol): + try: + url = f"https://data-api.binance.vision/api/v3/ticker/24hr?symbol={symbol}" + out = subprocess.run( + ["curl", "-s", "--max-time", "8", url], + capture_output=True, text=True, timeout=12 + ).stdout + if '"lastPrice"' not in out: + return None + # 简单解析 lastPrice + import json + d = json.loads(out) + return float(d["lastPrice"]) + except Exception: + return None + + +def notify(title, msg): + subprocess.run(["osascript", "-e", + f'display notification "{msg}" with title "{title}" sound name "Glass"']) + + +def main(): + today = datetime.date.today().isoformat() + # 跨日重置 + if ALERTED and not any(k.endswith(today) for k in ALERTED): + ALERTED.clear() + + for c in WATCH: + p = price_of(c["symbol"]) + if p is None: + continue + for a in c["alerts"]: + key = f"{c['symbol']}_{a['price']}_{today}" + hit = (p >= a["price"]) if a.get("above", True) else (p <= a["price"]) + # 默认 above=True: 价格>=预警价触发; 想做"跌破"提醒就设 above=False + if "above" in a and a["above"] is False: + hit = p <= a["price"] + if hit and key not in ALERTED: + ALERTED.add(key) + notify(f"[币圈 {a['tag']}] {c['name']}", + f"{c['name']} 现价 {p:.2f} USDT | {a['tip']}") + + +if __name__ == "__main__": + main() diff --git a/okx_keys.json b/okx_keys.json new file mode 100644 index 0000000..c49cbb3 --- /dev/null +++ b/okx_keys.json @@ -0,0 +1,5 @@ +{ + "api_key": "0d20471b-41a3-4e03-9cd6-dfdef72d1d93", + "secret": "3FBD0BF58FB8C1A6F6C8996F41C384D9", + "passphrase": "Information268!" +} diff --git a/okx_monitor.py b/okx_monitor.py new file mode 100644 index 0000000..6f8a7ed --- /dev/null +++ b/okx_monitor.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +OKX 合约账户 只读监控 + 实时分析提醒 +- 仅使用 GET 只读接口(账户/持仓/未成交/行情),绝不写入/下单 +- 密钥从同目录 okx_keys.json 读取(不要硬编码) +- 每5分钟运行, 触发条件弹 macOS 通知 +""" +import subprocess, json, hmac, hashlib, base64, datetime, sys, os + +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) + +API_KEY = "" +SECRET = "" +PASSPHRASE = "" + +try: + k = load_keys() + API_KEY = k["api_key"] + SECRET = k["secret"] + PASSPHRASE = k["passphrase"] +except Exception as e: + print("读取密钥失败:", e) + sys.exit(1) + + +def sign(timestamp, method, path, body=""): + pre = timestamp + method.upper() + path + body + mac = hmac.new(SECRET.encode("utf-8"), pre.encode("utf-8"), hashlib.sha256) + return base64.b64encode(mac.digest()).decode() + + +def okx_get(path): + ts = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z" + sig = sign(ts, "GET", path, "") + curl = [ + "curl", "-s", "--max-time", "10", + "-H", f"OK-ACCESS-KEY:{API_KEY}", + "-H", f"OK-ACCESS-SIGN:{sig}", + "-H", f"OK-ACCESS-TIMESTAMP:{ts}", + "-H", f"OK-ACCESS-PASSPHRASE:{PASSPHRASE}", + "-H", "Content-Type:application/json", + f"https://www.okx.com{path}", + ] + out = subprocess.run(curl, capture_output=True, text=True, timeout=15).stdout + try: + return json.loads(out) + except Exception: + return {"code": "-1", "msg": out[:200]} + + +ALERTED = set() + + +def notify(title, msg): + subprocess.run(["osascript", "-e", + f'display notification "{msg}" with title "{title}" sound name "Glass"']) + + +def mark_price(inst_id): + """拉实时标记价(只读公共接口)""" + try: + out = subprocess.run( + ["curl", "-s", "--max-time", "8", + f"https://www.okx.com/api/v5/market/ticker?instId={inst_id}"], + capture_output=True, text=True, timeout=12).stdout + d = json.loads(out) + if d.get("code") == "0": + return float(d["data"][0]["last"]) + except Exception: + pass + return None + + +# 合约面值缓存(每张对应多少基础币) +_CTVAL = {} + + +def ctval(inst_id): + if inst_id in _CTVAL: + return _CTVAL[inst_id] + try: + out = subprocess.run( + ["curl", "-s", "--max-time", "8", + f"https://www.okx.com/api/v5/public/instruments?instType=SWAP"], + capture_output=True, text=True, timeout=12).stdout + for x in json.loads(out).get("data", []): + if x["instId"] == inst_id: + v = float(x.get("ctVal", 1)) + _CTVAL[inst_id] = v + return v + except Exception: + pass + _CTVAL[inst_id] = 1.0 + return 1.0 + + +# 手续费档(普通用户Taker); 开平各一次 +TAKER_FEE = 0.0005 +# 资金费保守估算: 每8h最多按0.01%偏多, 默认持仓1天=3期(无持仓时长则按0算) +FUNDING_PER_PERIOD = 0.0001 +FUNDING_PERIODS = 3 + + +def be_price(inst, sz, entry, upl): + """算覆盖所有费用后的回本价(多/空通用)""" + cv = ctval(inst) + notional = sz * cv * entry # 名义价值(开仓) + fee = notional * TAKER_FEE * 2 # 开+平手续费 + funding = notional * FUNDING_PER_PERIOD * FUNDING_PERIODS + total_cost = fee + funding # 需覆盖的总费用 + per_point = sz * cv # 每点价格变动盈亏 + need_move = total_cost / per_point # 需涨/跌点数 + # 多单需涨, 空单需跌 + side = "long" if upl >= 0 else "long" + return entry + need_move, total_cost, need_move + + +def analyze_and_alert(bal, pos): + """基于持仓做风险提示: 浮亏预警 + 强平价关注 + 距强平<=3%紧急预警 + 费用回本价""" + today = datetime.date.today().isoformat() + if ALERTED and not any(x.endswith(today) for x in ALERTED): + ALERTED.clear() + + details = pos.get("data", []) + for p in details: + inst = p.get("instId", "") + pos_side = p.get("posSide", "") + sz = float(p.get("pos", "0")) if p.get("pos") else 0.0 + lev = p.get("lever", "1") + liq = p.get("liqPx", "") + upl = float(p.get("upl", "0")) if p.get("upl") else 0.0 + ccy = p.get("ccy", "") + if sz == 0 or not liq: + continue + liq = float(liq) + tip = f"{inst} {pos_side} 量{sz} 杠杆{lev} 强平@{liq:.2f} 浮动{upl:+.2f}{ccy}" + + # 费用回本价 + be, cost, move = be_price(inst, sz, float(p.get("avgPx", 0)) or 0, upl) + if float(p.get("avgPx", 0) or 0) > 0: + print(f" 费用回本价: {be:.2f} (需覆盖费用{cost:.2f}USDT, 即再涨{move:.2f}点)") + + # 浮亏超阈值提醒 + if upl < -50: + key = f"loss_{inst}_{today}" + if key not in ALERTED: + ALERTED.add(key) + notify(f"[OKX 浮亏预警] {inst}", tip) + + # 强平价关注(每日一次) + key0 = f"liq_{inst}_{today}" + if key0 not in ALERTED: + ALERTED.add(key0) + notify(f"[OKX 持仓监控] {inst}", f"强平价 {liq:.2f} | 回本价{be:.2f} | {tip}") + + # 距强平 <=3% 紧急预警(每小时一次, 用分钟级key避免刷屏) + mp = mark_price(inst) + if mp: + dist = abs(mp - liq) / mp * 100 + if dist <= 3.0: + hm = datetime.datetime.now().strftime("%Y%m%d%H") + key1 = f"risk_{inst}_{hm}" + if key1 not in ALERTED: + ALERTED.add(key1) + notify(f"[OKX 紧急·近强平] {inst}", + f"现价{mp:.2f} 距强平{liq:.2f}仅{dist:.1f}%! 回本价{be:.2f} | 建议降杠杆/减仓 | {tip}") + print(f" {inst} 现价{mp:.2f} 强平{liq:.2f} 距强平{dist:.2f}%") + + +def main(): + if not API_KEY: + sys.exit(0) + # 只读接口 + bal = okx_get("/api/v5/account/balance") + if bal.get("code") != "0": + err = bal.get("msg", "未知错误") + print("余额查询失败:", err) + # 401/签名错也通知, 方便排查 + notify("[OKX 监控] 查询失败", err[:80]) + return + pos = okx_get("/api/v5/account/positions?instType=SWAP") + # 打印摘要 + try: + total = float(bal["data"][0]["totalEq"]) + print(f"[{datetime.datetime.now():%H:%M}] 总权益: {total:.2f} USDT") + except Exception: + pass + analyze_and_alert(bal, pos if pos.get("code") == "0" else {"data": []}) + + +if __name__ == "__main__": + main() diff --git a/stock_watch.py b/stock_watch.py new file mode 100644 index 0000000..33bb09c --- /dev/null +++ b/stock_watch.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +行云科技(300209) 自动盯盘脚本 +- 每5分钟拉一次新浪行情,解析现价 +- 对照关键价位触发 macOS 通知提醒 +- 仅在交易时段运行 +""" +import subprocess +import time +import datetime +import sys + +# ===== 你的持仓与关键价位配置 ===== +STOCK_CODE = "sz300209" # 新浪代码 +STOCK_NAME = "行云科技" +HOLD_QTY = 5000 # 持仓数量 +COST = 30.052 # 持仓成本 +PRESSURE1 = 35.34 # 第一压力(筹码成本) +PRESSURE2 = 39.30 # 强压力 +SUPPORT1 = 32.50 # 第一支撑 +SUPPORT2 = 31.19 # 强支撑(止损) + +# 已提醒标记,避免同一条件反复弹窗(每个交易日内) +_alerted = set() + + +def now_price(): + """从新浪接口取现价,返回 (price, ts_str) 或 (None, '')""" + try: + url = f"https://hq.sinajs.cn/list={STOCK_CODE}" + out = subprocess.run( + ["curl", "-s", "--max-time", "8", url, + "-H", "Referer: https://finance.sina.com.cn"], + capture_output=True, text=True, timeout=12 + ).stdout + # 格式: var hq_str_sz300209="名称,今开,昨收,现价,最高,最低,买一,...,时间,...,"; + if "hq_str_" not in out: + return None, "" + seg = out.split('"')[1] + f = seg.split(",") + if len(f) < 32: + return None, "" + price = float(f[3]) + ts = f[30] + " " + f[31] + return price, ts + except Exception: + return None, "" + + +def in_trading_time(): + """判断当前是否交易时段(周一~周五 9:30-11:30, 13:00-15:00)""" + now = datetime.datetime.now() + if now.weekday() >= 5: # 周六日 + return False + t = now.time() + am = datetime.time(9, 30) <= t <= datetime.time(11, 30) + pm = datetime.time(13, 0) <= t <= datetime.time(15, 0) + return am or pm + + +def notify(title, msg): + script = f'display notification "{msg}" with title "{title}" sound name "Glass"' + subprocess.run(["osascript", "-e", script]) + + +def check(price, ts): + global _alerted + # 每个自然日重置提醒标记 + today = datetime.date.today().isoformat() + if _alerted and list(_alerted)[0].startswith("__day__"): + if not list(_alerted)[0].endswith(today): + _alerted.clear() + _alerted.add(f"__day__{today}") + + pnl = (price - COST) * HOLD_QTY + base = f"{STOCK_NAME}(300209) 现价{price} 盈亏{plnl:+.0f} | {ts}" + + triggers = [] + if price >= PRESSURE1: + triggers.append(("减仓", f"触及压力位{PRESSURE1},缩量滞涨可减仓1/3~1/2")) + if price >= PRESSURE2: + triggers.append(("高位", f"触及强压力{PRESSURE2},接近前高,不追")) + if price <= SUPPORT2: + triggers.append(("止损", f"跌破强支撑{SUPPORT2},建议止损清仓!")) + elif price <= SUPPORT1: + triggers.append(("减仓", f"跌破支撑{SUPPORT1},建议减至1/3仓")) + + for tag, tip in triggers: + key = f"{tag}_{today}" + if key not in _alerted: + _alerted.add(key) + notify(f"[{tag}] {STOCK_NAME}", f"{base} | {tip}") + + +def main(): + if not in_trading_time(): + sys.exit(0) + price, ts = now_price() + if price is None: + sys.exit(0) + check(price, ts) + + +if __name__ == "__main__": + main() diff --git a/stx_sim.py b/stx_sim.py new file mode 100644 index 0000000..d38fdf5 --- /dev/null +++ b/stx_sim.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +STX 模拟操作 (DRY-RUN, 绝不下真实单) +- 用 OKX 实时行情驱动一套简单趋势+支撑压力策略 +- 模拟开仓/止损/止盈, 输出虚拟盈亏与信号 +- 默认杠杆 5x (仅模拟计算, 不影响真实账户) +""" +import subprocess, json, datetime, sys, os + +HERE = os.path.dirname(os.path.abspath(__file__)) + +# ===== 策略参数 (基于之前分析) ===== +INST = "STX-USDT-SWAP" +LEVER = 5 # 模拟杠杆 +SUPPORT = 0.23 # 第一支撑(突破回踩买点) +STRONG_SUPPORT = 0.19 # 强支撑(止损参考) +PRESSURE = 0.2895 # 压力(前高, 止盈区) +STOP_LOSS = 0.205 # 模拟止损价(跌破强支撑上方一点) +TAKE_PROFIT = 0.285 # 模拟止盈价(接近前高) +SIM_QTY = 1000 # 模拟持仓张数(对应约 260 USDT 保证金 @5x) + +_state_file = os.path.join(HERE, "stx_sim_state.json") + + +def get_ticker(): + out = subprocess.run( + ["curl", "-s", "--max-time", "10", + f"https://www.okx.com/api/v5/market/ticker?instId={INST}"], + capture_output=True, text=True, timeout=15).stdout + return json.loads(out)["data"][0] + + +def load_state(): + try: + with open(_state_file) as f: + return json.load(f) + except Exception: + return {"position": "flat", "entry": 0.0, "side": ""} + + +def save_state(s): + with open(_state_file, "w") as f: + json.dump(s, f, indent=2) + + +def pnl(entry, last, qty, lever): + # 永续合约 U 本位, 多单盈亏 = (last-entry)/entry * 保证金 * lever + margin = (last * qty) / lever + return (last - entry) / entry * margin + + +def main(): + tk = get_ticker() + last = float(tk["last"]) + ts = datetime.datetime.now().strftime("%H:%M:%S") + st = load_state() + + print(f"[{ts}] STX 现价 {last:.4f} | 状态: {st['position']}") + + if st["position"] == "flat": + # 策略: 价格回踩第一支撑(0.23)附近且未破 -> 模拟开多 + # 简化: 现价 <= 支撑*1.03 且 >= 强支撑 -> 开多 + if STRONG_SUPPORT <= last <= SUPPORT * 1.03: + st = {"position": "long", "entry": last, "side": "long", + "time": ts, "qty": SIM_QTY, "lever": LEVER} + save_state(st) + print(f" >> 模拟开多 @ {last:.4f} 杠杆{LEVER}x 量{SIM_QTY} (虚拟)") + else: + print(f" -- 观望 (现价 {last:.4f} 未到买区 {STRONG_SUPPORT}~{SUPPORT*1.03:.4f})") + + elif st["position"] == "long": + entry = st["entry"] + # 止损 + if last <= STOP_LOSS: + p = pnl(entry, last, SIM_QTY, LEVER) + print(f" >> 模拟止损 @ {last:.4f} 虚拟盈亏 {p:+.2f} USDT") + save_state({"position": "flat", "entry": 0.0, "side": ""}) + # 止盈 + elif last >= TAKE_PROFIT: + p = pnl(entry, last, SIM_QTY, LEVER) + print(f" >> 模拟止盈 @ {last:.4f} 虚拟盈亏 {p:+.2f} USDT") + save_state({"position": "flat", "entry": 0.0, "side": ""}) + else: + p = pnl(entry, last, SIM_QTY, LEVER) + print(f" -- 持仓中 开仓{entry:.4f} 虚拟浮动 {p:+.2f} USDT") + + print(f" 关键位: 支撑{SUPPORT} 强支撑{STRONG_SUPPORT} 压力{PRESSURE} 止损{STOP_LOSS} 止盈{TAKE_PROFIT}") + + +if __name__ == "__main__": + main() diff --git a/行云科技300209盯盘清单.md b/行云科技300209盯盘清单.md new file mode 100644 index 0000000..d20ac8a --- /dev/null +++ b/行云科技300209盯盘清单.md @@ -0,0 +1,64 @@ +# 行云科技(300209)盯盘清单 + +> 数据时点:2026-08-25 收盘附近(价随行情变动,每日盘前刷新) +> 持仓:5000 股 | 成本:30.052 元 + +## 一、持仓盈亏速览 + +| 项目 | 数值 | +|------|------| +| 持仓数量 | 5000 股 | +| 持仓成本 | 30.052 元 | +| 成本线市值 | 150,260 元 | +| 第一压力位(35.34)市值 | 176,700 元 | +| 强压力位(39.30)市值 | 196,500 元 | +| 第一支撑位(32.50)市值 | 162,500 元 | +| 强支撑位(31.19)市值 | 155,950 元 | + +> 现价每涨/跌 1 元,持仓市值约 ±5000 元。 + +## 二、关键价位(自上而下) + +| 价位 | 类型 | 含义 | 对应操作 | +|------|------|------|----------| +| 39.30 | 强压力 | 前期箱体上沿/接近前高40 | 历史高位,不追 | +| 35.34 | 第一压力 | 筹码平均成本(套牢密集区) | 反弹至此缩量→减仓1/3~1/2 | +| 34.40 | 参考现价 | 约8/25收盘 | 持有观察 | +| 30.05 | 你的成本 | 浮盈/浮亏分界 | 守住即盈利 | +| 32.50 | 第一支撑 | 近期箱体下沿 | 跌破→减至1/3仓 | +| 31.19 | 强支撑 | 8/20盘中最低 | 有效跌破→止损清仓 | + +## 三、每日盯盘动作 + +### 盘前(9:15 前) +- [ ] 刷新现价,更新上表"参考现价" +- [ ] 看隔夜有无新公告(尤其实控人诉讼进展) +- [ ] 看算力/液冷服务器板块隔夜强弱 + +### 盘中(重点看三件事) +- [ ] **量能**:反弹是否放量?缩量上涨=减仓信号 +- [ ] **价位**:是否触及 35.34(压力)或 32.50(支撑) +- [ ] **资金**:主力净流入/流出(同花顺/东财实时) + +### 收盘后 +- [ ] 记录当日收盘价,判断是否触发止损/减仓条件 +- [ ] 看龙虎榜(若上榜)买卖席位性质 + +## 四、操作触发条件(备忘) + +| 情形 | 动作 | 仓位变化 | +|------|------|----------| +| 反弹至 35.34 缩量滞涨 | 减仓 | 5000→2500~3300 | +| 跌破 32.50 且放量大跌 | 减仓 | 5000→1500~2000 | +| 有效跌破 31.19 次日不收回 | 止损 | 清仓 | +| 实控人诉讼实质不利进展 | 立即离场 | 清仓 | +| 31.19 缩量企稳+板块回暖 | 小仓试探 | 5000→6000~7000 | + +## 五、核心风险(每日默念) +- 概念退潮(PB 畸高、纯题材驱动) +- 实控人诉讼致股权变动 +- 主力连续净流出、低度控盘闪崩 +- 创业板 20% 涨跌幅,波动剧烈 + +--- +*免责声明:本清单为个人复盘工具,基于公开信息整理,不构成投资建议。*