Files
Hermes-Skills/longbridge-cli/scripts/t_monitor.py
T
mikeandClaude af6aa8d7b8 feat(longbridge): 602315 mainland CN geo-block bypass + stock_t通用脚本
- SKILL.md: 加 602315 bypass 章节(三件套 LONGBRIDGE_REGION + proxychains + Clash HK)
- longbridge-python-sdk/SKILL.md: Python SDK 路径同样需要 bypass
- references/longbridge-602315-bypass.md: 完整方案+验证步骤
- references/longbridge-cn-vs-com-endpoint.md: cn vs com 域名区别
- references/clash-node-switching.md: Clash 切香港节点操作
- references/stock-t-trading-workflow.md: 通用持仓脚本用法
- intraday-trading/SKILL.md: 同步 602315 限制说明
- scripts/{daily_t_analysis,t_monitor}.py: 之前漏提交,补上

验证: 2026-07-09 下单 RGTI 15股@15.50 订单ID 1259547163696824320 成功
背景: longport SDK 通过 is_cn() 自动探测 geotest.lbkrs.com 选 cn/com endpoint
     net_mode下 cn 域(阿里云深圳)被拒,com 域(AWS香港)需绕
     唯一可行: LONGBRIDGE_REGION=ap 强制走 com + proxychains + Clash 香港出口

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-09 00:45:25 +08:00

117 lines
5.1 KiB
Python

#!/usr/bin/env python3
"""
持仓做T价格监控 - 支撑位低吸、阻力位高抛
监控所有持仓(OKX+长桥),价格接近关键位时提醒
无提醒时静默输出(cron no_agent模式不推送)
"""
import os, sys, json, math, subprocess, re
from datetime import datetime
# Load creds
okx_creds = {}
with open(os.path.expanduser('~/.bashrc')) as f:
for line in f:
m = re.match(r'export\s+(OKX_\w+)=(.*)', line.strip())
if m:
okx_creds[m.group(1)] = m.group(2).strip().strip('"').strip("'")
line = line.strip()
if line.startswith('export LONGPORT_') or line.startswith('export LONGBRIDGE_'):
parts = line.replace('export ', '').split('=', 1)
if len(parts) == 2:
os.environ[parts[0]] = parts[1]
def okx_get(endpoint, params=""):
import hmac, base64, hashlib
ts = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.') + f"{datetime.utcnow().microsecond // 1000:03d}Z"
path = endpoint + ('?' + params if params else '')
msg = ts + 'GET' + path
sig = base64.b64encode(hmac.new(okx_creds['OKX_SECRET'].encode(), msg.encode(), hashlib.sha256).digest()).decode()
cmd = ['curl', '-s', '--proxy', 'http://127.0.0.1:7890',
'-H', f'OK-ACCESS-KEY: {okx_creds["OKX_API_KEY"]}', '-H', f'OK-ACCESS-SIGN: {sig}',
'-H', f'OK-ACCESS-TIMESTAMP: {ts}', '-H', f'OK-ACCESS-PASSPHRASE: {okx_creds["OKX_PASSPHRASE"]}',
'-H', 'Content-Type: application/json', f'https://www.okx.com{path}']
r = subprocess.run(cmd, capture_output=True, text=True, timeout=15)
return json.loads(r.stdout)
def monitor():
alerts = []
# OKX positions
try:
pos = okx_get('/api/v5/account/positions', 'instType=SWAP')
for p in pos.get('data', []):
if float(p.get('pos', 0)) == 0:
continue
sym = p['instId'].replace('-USDT-SWAP', '')
try:
ticker = okx_get('/api/v5/market/ticker', f'instId={sym}-USDT-SWAP')
price = float(ticker['data'][0]['last'])
candles = okx_get('/api/v5/market/candles', f'instId={sym}-USDT-SWAP&bar=4H&limit=20')
data = candles.get('data', [])
if len(data) >= 10:
closes = [float(d[4]) for d in data]
highs = [float(d[2]) for d in data]
lows = [float(d[3]) for d in data]
atr_sum = sum(max(highs[-i]-lows[-i], abs(highs[-i]-closes[-i-1]), abs(lows[-i]-closes[-i-1])) for i in range(1, min(15, len(data))))
atr = atr_sum / min(14, len(data)-1)
support = min(lows[-5:])
resistance = max(highs[-5:])
sma20 = sum(closes) / len(closes)
buy_zone = min(support, sma20) + atr * 0.2
sell_zone = max(resistance, sma20) - atr * 0.2
dist_buy = abs(price - buy_zone) / price * 100
dist_sell = abs(price - sell_zone) / price * 100
if dist_buy < 1.5:
alerts.append(f"🟢 {sym} 接近低吸位! 现价{price:.2f} → 低吸{buy_zone:.2f} (差{dist_buy:.1f}%)")
elif dist_sell < 1.5:
alerts.append(f"🔴 {sym} 接近高抛位! 现价{price:.2f} → 高抛{sell_zone:.2f} (差{dist_sell:.1f}%)")
elif price < support:
alerts.append(f"⚠️ {sym} 跌破支撑! 现价{price:.2f} < 支撑{support:.2f}")
elif price > resistance:
alerts.append(f"🚀 {sym} 突破阻力! 现价{price:.2f} > 阻力{resistance:.2f}")
except:
pass
except:
pass
# LongBridge positions
try:
from longport import openapi
cfg = openapi.Config.from_env()
trade_ctx = openapi.TradeContext(config=cfg)
quote_ctx = openapi.QuoteContext(config=cfg)
resp = trade_ctx.stock_positions()
lb_syms = []
lb_pos = {}
for ch in resp.channels:
for p in ch.positions:
if int(p.quantity) > 0:
lb_syms.append(p.symbol)
lb_pos[p.symbol] = {'cost': float(p.cost_price), 'qty': int(p.quantity)}
if lb_syms:
quotes = quote_ctx.quote(lb_syms)
for q in quotes:
price = float(q.last_done)
cost = lb_pos[q.symbol]['cost']
buy_zone = cost * 0.95
sell_zone = cost * 1.05
dist_buy = abs(price - buy_zone) / price * 100
dist_sell = abs(price - sell_zone) / price * 100
if dist_buy < 2:
alerts.append(f"🟢 {q.symbol} 接近低吸位! 现价{price:.2f} → 低吸{buy_zone:.2f}")
elif dist_sell < 2:
alerts.append(f"🔴 {q.symbol} 接近高抛位! 现价{price:.2f} → 高抛{sell_zone:.2f}")
except:
pass
if alerts:
print("📊 做T监控提醒\n")
print("\n".join(alerts))
print(f"\n{datetime.now().strftime('%H:%M')}")
# 无输出=静默
if __name__ == '__main__':
monitor()