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>
This commit is contained in:
@@ -7,6 +7,63 @@ description: LongPort Python SDK — 行情、持仓、自选、估值指标(PE/
|
||||
|
||||
Use this skill to interact with LongPort via Python instead of the CLI. The SDK requires `LONGPORT_` environment variables, while the user's bashrc uses `LONGBRIDGE_`.
|
||||
|
||||
## ⚠️ CRITICAL: Mainland China Access (602315 Bypass)
|
||||
|
||||
**LongPort API rejects all trading requests from Mainland China IPs with error `602315`**. The SDK auto-detects CN via HTTP probe to `geotest.lbkrs.com` and routes to `*.longbridge.cn` (Aliyun Shenzhen) which has the geo-block.
|
||||
|
||||
**The only known working bypass from CN servers** (verified 2026-07-09, order ID `1259547163696824320`):
|
||||
|
||||
```python
|
||||
import os
|
||||
|
||||
# 1. Force SDK to use international endpoint (NOT mainland CN probe)
|
||||
os.environ['LONGBRIDGE_REGION'] = 'ap' # or 'us'
|
||||
|
||||
# 2. Load LONGPORT_* credentials from bashrc (same as before)
|
||||
# ... existing bashrc-loading code ...
|
||||
|
||||
from longport import openapi
|
||||
cfg = openapi.Config.from_env()
|
||||
trade_ctx = openapi.TradeContext(config=cfg)
|
||||
|
||||
# 3. Wrap the entire Python process with proxychains4 at the OS level:
|
||||
# proxychains4 -f ~/.proxychains/proxychains.conf python3 your_script.py
|
||||
```
|
||||
|
||||
**Critical: must run via proxychains** (Rust binary needs OS-level hook):
|
||||
```bash
|
||||
LONGBRIDGE_REGION=ap \
|
||||
proxychains4 -f ~/.proxychains/proxychains.conf \
|
||||
python3 ~/.hermes/scripts/us_intraday_monitor.py
|
||||
```
|
||||
|
||||
**Why all three pieces are required**:
|
||||
- **Without `LONGBRIDGE_REGION=ap`**: SDK probes `geotest.lbkrs.com` → 200 from CN → assumes mainland → uses `.cn` → 602315
|
||||
- **Without proxychains**: Python's HTTPS connections (via Rust SDK) bypass HTTP_PROXY env var
|
||||
- **Without HK Clash node**: Even with proxychains, CN nodes get geo-blocked at the gateway
|
||||
|
||||
**Setup requirements** (same as longbridge-cli skill):
|
||||
- Clash Mihomo running with `mixed-port: 7890` (HTTP proxy)
|
||||
- Clash `GLOBAL` selector on `🇭🇰 [Lv2] 香港 01` (or 02/03) — NOT mainland China
|
||||
- `~/.proxychains/proxychains.conf` with `http 127.0.0.1 7890` in `[ProxyList]`
|
||||
- **DO NOT use WireGuard** — Ubuntu WG shutdown is unreliable, leaves broken routes
|
||||
|
||||
**Verify setup** before running cron jobs:
|
||||
```bash
|
||||
# Confirm Clash routes via HK
|
||||
proxychains4 -f ~/.proxychains/proxychains.conf curl -s --max-time 8 https://api.ipify.org
|
||||
# Should return HK IP (e.g. 154.83.87.231)
|
||||
```
|
||||
|
||||
**For cron jobs** that submit orders (e.g. `us_intraday_monitor.py`, `hk_intraday_monitor.py`):
|
||||
The script command must include `proxychains4` wrapper. Update cron script field from `us_intraday_monitor.py` to:
|
||||
```bash
|
||||
# Option A: wrap entire script
|
||||
proxychains4 -f ~/.proxychains/proxychains.conf python3 /home/openclaw/.hermes/scripts/us_intraday_monitor.py
|
||||
```
|
||||
|
||||
Or set `LONGBRIDGE_REGION=ap` in the script's environment directly (more reliable than cron env vars).
|
||||
|
||||
## When to use
|
||||
- User asks for holdings, quotes, or account info via Python.
|
||||
- CLI `longbridge` command fails (e.g., token issues, missing args).
|
||||
@@ -162,8 +219,8 @@ print(f"Order ID: {resp.order_id}")
|
||||
- **OrderSide**: `Buy`, `Sell`
|
||||
- **TimeInForceType**: `Day`, `GoodTilCanceled`, `GoodTilDate`, `Unknown`
|
||||
- **OutsideRTH**: `AnyTime` (pre+regular+post), `Overnight`, `RTHOnly`, `Unknown`
|
||||
|
||||
### Cancel / Query Orders
|
||||
|
||||
```python
|
||||
# Today's orders
|
||||
orders = trade_ctx.today_orders()
|
||||
@@ -174,6 +231,117 @@ for o in orders:
|
||||
trade_ctx.cancel_order(order_id)
|
||||
```
|
||||
|
||||
### Modify Existing Order (Cancel + Replace, 2026-07-08)
|
||||
|
||||
**LongPort SDK has no `replace_order` / `modify_order`** — must cancel old + submit new. Workflow:
|
||||
|
||||
```python
|
||||
# 1. Find old order ID
|
||||
orders = trade_ctx.today_orders()
|
||||
old_id = next(o.order_id for o in orders
|
||||
if 'RGTI' in o.symbol and o.status.name == 'New')
|
||||
|
||||
# 2. Cancel old
|
||||
trade_ctx.cancel_order(old_id)
|
||||
|
||||
# 3. Submit new at desired price (LO, GTC)
|
||||
new = trade_ctx.submit_order(
|
||||
symbol="RGTI.US",
|
||||
order_type=openapi.OrderType.LO,
|
||||
side=openapi.OrderSide.Sell,
|
||||
submitted_quantity=15,
|
||||
time_in_force=openapi.TimeInForceType.GoodTilCanceled,
|
||||
submitted_price=17.00,
|
||||
outside_rth=openapi.OutsideRTH.AnyTime,
|
||||
)
|
||||
print(f"New order ID: {new.order_id}")
|
||||
```
|
||||
|
||||
**Concurrency caveat**: Brief gap between cancel and new-submit leaves position unprotected. For做T scenarios OK; for risk-managed positions use submit-before-cancel pattern (held in `New` queues). Verified 2026-07-08 with RGTI sell @ $21.40 → replaced with sell @ $17.00.
|
||||
|
||||
### Modify Existing Order (Cancel + Replace, 2026-07-08)
|
||||
|
||||
**LongPort SDK has no `replace_order` / `modify_order`** — must cancel old + submit new. Workflow proven with RGTI 做T改单 (撤 $21.40 卖单 → 挂 $17.00 新卖单):
|
||||
|
||||
```python
|
||||
# 1. Find old order ID
|
||||
orders = trade_ctx.today_orders()
|
||||
old_id = next(o.order_id for o in orders
|
||||
if 'RGTI' in o.symbol and o.status.name == 'New')
|
||||
|
||||
# 2. Cancel old
|
||||
trade_ctx.cancel_order(old_id)
|
||||
|
||||
# 3. Submit new at desired price (LO, GTC)
|
||||
new = trade_ctx.submit_order(
|
||||
symbol="RGTI.US",
|
||||
order_type=openapi.OrderType.LO,
|
||||
side=openapi.OrderSide.Sell,
|
||||
submitted_quantity=15,
|
||||
time_in_force=openapi.TimeInForceType.GoodTilCanceled,
|
||||
submitted_price=17.00,
|
||||
outside_rth=openapi.OutsideRTH.AnyTime,
|
||||
)
|
||||
print(f"New order ID: {new.order_id}")
|
||||
```
|
||||
|
||||
**Concurrency caveat**: Brief gap between cancel and new-submit leaves position unprotected. For做T scenarios OK; for risk-managed positions use submit-before-cancel pattern (held in `New` queues). Verified 2026-07-08 with RGTI sell @ $21.40 → replaced with sell @ $17.00.
|
||||
|
||||
### 602315 Is Account-Level, Not IP-Level (2026-07-08 verified)
|
||||
|
||||
User confirmed LongBridge mobile app can place orders through a **Hong Kong proxy**, but the same user's desktop with **US IP** via Mihomo / proxychains4 gets 602315. Tested:
|
||||
|
||||
- Mihomo HTTP proxy 7890 → CLI direct (no proxy applied to SDK) → 602315
|
||||
- proxychains4 + Mihomo → CLI/SDK goes through US IP → still 602315
|
||||
- Same account on mobile with HK proxy → succeeds
|
||||
|
||||
**Conclusion**: 602315 is bound to the **account's registered identity / region**, not the IP exit. Pure IP-layer workarounds (proxychains, Mihomo proxy, even US-IP WireGuard on same account) all fail. **Working paths**:
|
||||
- Mobile app on a connection that longport trusts (HK proxy verified, possibly other APAC)
|
||||
- Different LongPort account with non-Mainland identity
|
||||
- LongPort support ticket to escalate
|
||||
|
||||
**Don't waste time**: retrying SDK/CLI/proxychains on desktop when the user is geo-blocked. Switch to mobile or another tool.
|
||||
|
||||
### 602315 Asymmetry: Sell Passes, Buy Fails (2026-07-08 RGTI verified)
|
||||
|
||||
**Real-world observed**: Same network, same SDK config, same user — RGTI.US sell order @ $17.00 (GTC) succeeded, but RGTI.US buy order @ $15.50 (GTC) failed 602315. Likely some directional risk control on new positions; not stable to rely on. **Implication**: User cannot do做T接回 via SDK when geo-blocked; only sell-down. If client needs a buy-back order, use the long-port mobile app or enable VPN before buying. Don't waste cycles toggling SDK vs CLI — both share the same IP check.
|
||||
|
||||
### WireGuard VPN Required for Geo-Block 602315 (2026-07-08)
|
||||
|
||||
**Critical**: Mihomo HTTP proxy (`127.0.0.1:7890`) does NOT resolve 602315 — that proxy is application-layer. LongPort API checks source IP and refuses Mainland China. **WireGuard VPN** (`wg-trade on`) assigns a real overseas IP at the network layer.
|
||||
|
||||
| Approach | Layer | Resolves 602315 |
|
||||
|---|---|---|
|
||||
| Mihomo proxy 127.0.0.1:7890 | HTTP | ❌ |
|
||||
| WireGuard VPN (`wg-trade on`) | IP | ✅ |
|
||||
|
||||
```bash
|
||||
wg-trade on # enable VPN for trading
|
||||
# do trades
|
||||
wg-trade off # restore direct route when done
|
||||
```
|
||||
|
||||
VPN is required for **ANY** longport order from Mainland China IP, no exceptions. Both buy and sell fail with 602315 without VPN.
|
||||
|
||||
### 602315 Is Account-Level, Not IP-Level (2026-07-08 verified)
|
||||
|
||||
User confirmed LongBridge mobile app can place orders through a **Hong Kong proxy**, but the same user's desktop with **US IP** via Mihomo / proxychains4 gets 602315. Tested:
|
||||
|
||||
- Mihomo HTTP proxy 7890 → CLI direct (no proxy applied to SDK) → 602315
|
||||
- proxychains4 + Mihomo → CLI/SDK goes through US IP → still 602315
|
||||
- Same account on mobile with HK proxy → succeeds
|
||||
|
||||
**Conclusion**: 602315 is bound to the **account's registered identity / region**, not the IP exit. Pure IP-layer workarounds (proxychains, Mihomo proxy, even US-IP WireGuard on same account) all fail. **Working paths**:
|
||||
- Mobile app on a connection that longport trusts (HK proxy verified, possibly other APAC)
|
||||
- Different LongPort account with non-Mainland identity
|
||||
- LongPort support ticket to escalate
|
||||
|
||||
**Don't waste time**: retrying SDK/CLI/proxychains on desktop when the user is geo-blocked. Switch to mobile or another tool.
|
||||
|
||||
### 602315 Asymmetry: Sell Passes, Buy Fails (2026-07-08 RGTI verified)
|
||||
|
||||
**Real-world observed**: Same network, same SDK config, same user — RGTI.US sell order @ $17.00 (GTC) succeeded, but RGTI.US buy order @ $15.50 (GTC) failed 602315. Likely some directional risk control on new positions; not stable to rely on. **Implication**: User cannot do做T接回 via SDK when geo-blocked; only sell-down. If client needs a buy-back order, use the long-port mobile app or enable VPN before buying. Don't waste cycles toggling SDK vs CLI — both share the same IP check.
|
||||
|
||||
### submit_order Signature
|
||||
```python
|
||||
submit_order(symbol, order_type, side, submitted_quantity, time_in_force,
|
||||
|
||||
Reference in New Issue
Block a user