# longport_http.py 公共模块 (2026-07-21 新建, 2026-07-23 更新 get_candlesticks) ## 背景 长桥 Python SDK (`openapi.QuoteContext` / `openapi.TradeContext`) 走 **WSS (WebSocket)**,而国内 VPS + Clash 代理下 WSS 经常超时 (`error sending request for url (https://openapi.longport.com/v1/socket/token): client error (Connect)`)。多次观察到: - 长桥 quote 公共 API (HTTP) 走 mihomo 代理**能通** - 长桥 SDK WSS 走 mihomo 代理**必败** - 长桥 CLI 走 mihomo 代理**能通** (HTTP 协议) **结论**:**长桥 SDK 不可用,长桥 CLI 完全够用**。 ## 公共模块: `~/.hermes/scripts/longport_http.py` 路径: `~/.hermes/scripts/longport_http.py` ### 提供函数 | 函数 | 替代 | 说明 | |------|------|------| | `get_quote(symbol)` | `ctx.quote([symbol])` | 拿 1 只票实时报价, fallback candlesticks day | | `get_quotes(symbols)` | `ctx.quote(batch)` | 批量,失败的 symbol 不会出现在结果里 | | `get_candlesticks(symbol, period="day", count=30)` | `ctx.candlesticks(...)` | K 线,返回 `[{"timestamp","open","high","low","close","volume"},...]` | | `get_positions()` | `trade_ctx.stock_positions()` | 查持仓 | | `submit_order(...)` | `trade_ctx.submit_order(...)` | 下单 (limit) | ### get_candlesticks 详解 (2026-07-23 新增) ```python klines = get_candlesticks('600519.SH', 'day', 5) # 返回: [{"timestamp": "2026-07-23T00:00", "open": 1299.8, "high": 1299.97, # "low": 1285.43, "close": 1294.95, "volume": 14448.0}, ...] klines = get_candlesticks('NVDA.US', '5m', 30) # period: 'day' | '5m' | '15m' | '1h' | '1m' 等 ``` A 股价格单位是**元**,不需要除以 100。 ### 内部实现 ```python def _run(*args) -> str: cmd = [PROXYCHAINS, "-f", PROXYCHAINS_CONF, LONGBRIDGE_BIN, "--profile", PROFILE, *args] r = subprocess.run(cmd, capture_output=True, text=True, timeout=TIMEOUT) return r.stdout if r.returncode == 0 else "" ``` **所有调用走 `proxychains4` + `longbridge` CLI**,避开 WSS。 ### A 股 / 长 symbol 截断问题 `longbridge quote 600519.SH` 表格列宽限制,symbol 显示成 `600519…`,价格也截断成 `1308.0…`。 **fallback**:`get_quote` 失败时调 `candlesticks day --count 1` 取日线收盘价(完整数字, 不是实时但可用)。 ```python if out: symbol_trunc = symbol[:7] + "…" for cand in [symbol, symbol_trunc]: m = re.search(r"│\s*" + re.escape(cand) + ... , out) if m: price_str = m.group(1) if "…" in price_str or len(price_str) < 4: break # 截断, 走 candlesticks fallback ... # fallback cs_out = _run("candlesticks", symbol, "day", "--count", "1") ``` ### 性能 (实测 2026-07-21) | 标的数 | 平均耗时 | 5 次连续成功率 | |--------|----------|----------------| | 3 (DCA US) | 4-5s | 5/5 ✅ | | 10 (dividend 港+美+A) | 21-26s | 3/3 ✅ | | 1 (cron 每 15min) | 4s | 5/5 ✅ | ## 已迁移的脚本 - `~/.hermes/skills/trading/dividend-investing/scripts/dividend_alert.py` ✅ (2026-07-24 迁移到 skill 仓库) - `~/.hermes/scripts/dca_monitor.py` ✅ - `~/.hermes/skills/trading/strategy-management/scripts/calc_cn_levels.py` ✅ (2026-07-23 新建) ## 待迁移 (Phase 2) | 脚本 | 当前 | 推广后 | |------|------|--------| | `~/.hermes/scripts/stock_t.py` | 直接调 ccxt | `from longport_http import get_quote, get_positions` | | `~/.hermes/scripts/daily_t_analysis.py` (cron `cb187ab5f9fc`) | 走 SDK | 改 longport_http | | `~/.hermes/scripts/dca_scanner.py` | 走 SDK | 改 longport_http | ## 实战铁律 (2026-07-21) - **`LONGPORT_*` env vars 在 cron 不生效** — 必须走 proxychains + longbridge CLI 走 mihomo - **`get_quote` 返回 None 不抛异常** — 让调用方自己判断 - **失败不重试** — 一次拿不到, 下一分钟 cron 会再跑 - **不要 fallback 到 SDK** — SDK 永远不通, 走了更糟 ## 关联 reference - `longbridge-cli/SKILL.md` - 长桥 CLI 主文档 - `strategy-management/SKILL.md` - A 股/港股/美股点位计算脚本(含 get_candlesticks 用法)