Files
Hermes-Skills/okx-auto-position/references/spcx-silent-fail-repro.md
T

4.5 KiB

SPCX-USDT-SWAP Silent-Execute-Failure Repro

Captured: 2026-07-13 Skill version: okx-auto-position v4.5.4 Severity: High (advisor reports success, but no order fills)

Symptom

okx_position_advisor.py --symbol SPCX --side {short,long} --leverage 5 --execute --json returns a full success-shaped JSON with contracts, margin, tp_price, sl_price, cost_check.auto_execute=true etc. However:

  1. GET /api/v5/account/positions?instId=SPCX-USDT-SWAP returns empty list
  2. GET /api/v5/account/balance details[ccy=USDT].frozenBal unchanged
  3. No order_id anywhere in advisor stdout
  4. process_signal pushes " 已推送 | SPCX short 5x | 1.45张 | 性价比高" — but position is actually 0

Reproduction (3 cases confirmed)

Case 3 (2026-07-13): MU short 新开仓静默失败

  • Signal: 熬鹰 MU short 334.95张 @10x @937.67, -0.15% PnL
  • Advisor: 0.51张 @10x, margin=$48.78
  • execute: JSON returned normally
  • Verify (5s after): positions=MU-USDT-SWAP not in list, frozenBal=0
  • Status: silent failure (3rd coin confirmed)

Key finding: MU 加仓可成功但新开仓失败

  • 紧跟 MU 新开仓静默失败之后,MU 加仓信号触发 execute 成功: 0.52张 @10x, avgPx 940.40, 真实持仓确认
  • 推测: ccxt 对 "首次建仓" vs "加仓" 走不同下单路径,首次建仓时可能在 ctVal/minSz 处理上漏掉
  • MU 实战规则: 新开仓(existing_pos=0) → 必须 raw REST 手动下单; 加仓(existing_pos>0) → 可信 advisor

Case 1: SPCX short

  • Signal: 熬鹰 SPCX short 17350张 @5x @148.59, +1.52% PnL
  • Advisor: 1.45张, margin=$43.15, tp=$133.86, sl=$153.85, liq=$175.57
  • execute: JSON returned normally
  • Verify (3s after): positions=SPCX-USDT-SWAP not in list, frozenBal=0
  • Status: silent failure

Case 2: SPCX long

  • Signal: 熬鹰 SPCX long 4514张 @2x @139.21, +0.28% PnL
  • Advisor: 3.5张, margin=$48.78
  • execute: JSON returned normally
  • Verify (5s after): positions=SPCX-USDT-SWAP not in list, frozenBal=0
  • Status: silent failure (second time same coin, same symptom)

Root cause (hypothesized)

OKX's SPCX-USDT-SWAP contract likely has unusual min-size/step-size/lot-size rules that ccxt's create_market_sell_order doesn't auto-handle. The advisor's execute path silently catches the error and returns the recommendation JSON anyway (without an order_id field).

Detection snippet

import json,time,hmac,hashlib,base64,requests

def okx_get(p, params=None, t=15):
    # ... standard raw REST GET with OKX_ACCESS_SIGN ...
    return requests.get(...).json()

# 1. Run execute
import subprocess
r = subprocess.run(['python3', 'okx_position_advisor.py', '--symbol', 'SPCX',
                    '--side', 'short', '--leverage', '5', '--execute', '--json'],
                   capture_output=True, text=True, timeout=60)
exec_json = json.loads(r.stdout)

# 2. Verify within 3 seconds
time.sleep(3)
pos = okx_get('/api/v5/account/positions', {'instId': 'SPCX-USDT-SWAP'})
positions = [p for p in pos.get('data', []) if float(p.get('pos', 0) or 0) != 0]

bal = okx_get('/api/v5/account/balance')
frozen = next((float(d['frozenBal']) for d in bal['data'][0]['details'] if d['ccy'] == 'USDT'), 0)

if not positions and frozen == 0:
    # SILENT FAILURE
    # Manual raw REST retry
    body = {
        'instId': 'SPCX-USDT-SWAP',
        'tdMode': 'cross',
        'side': 'sell' if 'short' in exec_json.get('side', '') else 'buy',
        'posSide': 'net',
        'ordType': 'market',
        'sz': str(exec_json['contracts']),
    }
    result = okx_post('/api/v5/trade/order', body)
    print(json.dumps(result, indent=2))

Manual fallback (when detected)

body = {
    'instId': 'SPCX-USDT-SWAP',
    'tdMode': 'cross',
    'side': 'sell',  # short
    'posSide': 'net',
    'ordType': 'market',
    'sz': '1.45',  # from advisor contracts
    # reduceOnly=False (initial open)
}
# POST /api/v5/trade/order

When to extend this list

Add a new entry whenever a coin shows the same silent-fail pattern:

  • Other small-cap contracts: SKHY, SNDK, MU USDC-margined variants
  • After 2+ confirmed silent failures, treat coin as "manual-only" and skip advisor's --execute path entirely
  • Instead: raw REST direct placement, skip advisor recommendation block
  • "v4.5.0 新坑 process_signal/advisor --execute 不返回 order_id" — covers detection
  • "v4.5.2 CCXT vs Raw REST 可靠性差距" — covers ccxt SSL/timeouts but NOT this silent-fail case
  • "v4.5.4 SPCX-USDT-SWAP 自动下单静默失败" — main entry in SKILL.md