v4.5.38: 实时数据查询硬规则(回复前必查)+ check_account.py封装

This commit is contained in:
2026-07-17 22:14:19 +08:00
parent 629ac197de
commit 533c342305
55 changed files with 5437 additions and 599 deletions
@@ -0,0 +1,158 @@
# execute 后判定成败的完整 self-check (2026-07-08)
## 触发场景
**用户原话(本次 session)**: "要是我没发现,就一直不推了吗? 重试机制呢"
**问题链路**: 熬鹰 ETH short 减仓信号 → 紧跟"已平仓提醒"信号 → process_signal dedup 误跳过 → agent 没自动平 → ETH 涨到 1795 → 用户 ETH short 浮亏扩大到 -$6.58 → 用户质问"自动平仓的retry在哪?"
## 三大failure mode必须能识别
### 1. execute 静默失败(advisor stdout 看起来 OK,实际没下单)
**症状**:
- advisor --execute 返回完整 JSON(contracts/margin/tp_price 等字段齐全)
- 但 raw REST 查持仓:**没新增任何仓**
- `frozenBal` 也没变化
**已知受害币种**(2026-07-08 实测):
- SPCX-USDT-SWAP (新开仓 long/short 都失败)
- MU-USDT-SWAP (新开仓静默失败,加仓成功)
- SKHYNIX-USDT-SWAP (新开仓失败,加仓成功)
**agent 必须做的 self-check**(在推QQ之前):
```bash
# 1. 立刻 raw REST 查持仓
curl -s -X GET "https://www.okx.com/api/v5/account/positions?instId={SYMBOL}-USDT-SWAP" \
-H "OK-ACCESS-KEY: ..." -H "OK-ACCESS-SIGN: ..." \
-H "OK-ACCESS-TIMESTAMP: ..." -H "OK-ACCESS-PASSPHRASE: ..." | jq .
# 2. 看 abs(pos) 是否对应 contracts × leverage
# 3. 看 frozenBal 变化值 = contracts × markPx / leverage
# 4. 若两者都不匹配 → 静默失败 → 立即 raw REST 手动重下
```
### 2. execute 返回 order_id 但实际 Rejected
**症状**: stdout 有 `order_id` 字段,但实际 status=Rejected。
**agent 必须做的 self-check**:
```bash
# OKX 私有 API 反查订单状态
curl -s -X GET "https://www.okx.com/api/v5/trade/order?instId={SYMBOL}-USDT-SWAP&ordId={ID}" \
-H "OK-ACCESS-KEY: ..." ... | jq '.data[0].state'
# state 值: filled / live / canceled / Rejected
```
**禁止**: 看到 stdout 有 order_id 就推"✅ 下单成功" —— 必须反查 state。
### 3. 平仓信号被 dedup 跳过(本次 session 实测)
**症状**: process_signal 返回 `⏭️ 重复信号跳过`,但实际持仓仍存在,平仓信号没触发市价平仓。
**agent 必须做的 self-check**(强化 v4.5.12 章节):
```bash
# 当 process_signal 返回 ⏭️ 重复信号跳过时:
# 1. raw REST 查同币种持仓
# 2. 若有持仓 + 信号是平仓类型 + 持仓方向与信号同方向 → 立即手动 raw REST 平仓
# 3. 不等下次信号,不等用户质问
```
**关键判断逻辑**(process_signal.py 应该自动化,但 agent 也得会手动):
```
process_signal 返回值: ⏭️ 重复信号跳过
↓ raw REST 查持仓
持仓: pos = -2.89 (short)
信号类型: 平仓(close)
信号方向: short
方向一致? ✅ 同方向 → 立即 raw REST 市价全平 reduceOnly=true
方向不一致? ⛔ 反向 → 不动,推"⏭️ 反向持仓不跟平"
无持仓? ⏭️ → 不动,推"⏭️ 无持仓可平"
```
## 三层验证 checklist (agent 每次 execute 后必跑)
### 第 1 层:raw REST 反查持仓(< 1秒)
```python
import json,time,hmac,hashlib,base64,requests
# 用 v4.5.2 提供的 okx_get 函数模板
result = okx_get('/api/v5/account/positions', {'instId': f'{symbol}-USDT-SWAP'})
for p in result.get('data', []):
pos = abs(float(p.get('pos', 0) or 0))
if pos > 0.001:
print(f"✅ 实际持仓: {symbol} {p['posSide']} {pos}张 @ {p['avgPx']}")
break
else:
print(f"⚠️ {symbol} 无持仓 - execute 可能静默失败")
```
### 第 2 层:raw REST 反查余额变化(< 1秒)
```python
result = okx_get('/api/v5/account/balance')
for d in result.get('data', [{}])[0].get('details', []):
if d['ccy'] == 'USDT':
frozen = float(d.get('frozenBal', 0))
avail = float(d.get('availBal', 0))
print(f"USDT: avail={avail:.2f} frozen={frozen:.2f}")
# 期望: frozen ≥ contracts × markPx / leverage
# 若 frozen < 期望 → 静默失败
```
### 第 3 层:订单 status 反查(若 advisor stdout 有 order_id)(< 1秒)
```python
result = okx_get('/api/v5/trade/order', {'instId': f'{symbol}-USDT-SWAP', 'ordId': order_id})
if result.get('data'):
state = result['data'][0].get('state')
if state == 'filled':
print(f"✅ 订单已成交: {order_id}")
elif state == 'live':
print(f"⏳ 订单挂单中: {order_id}")
elif state == 'Canceled':
print(f"🚫 订单已撤: {order_id}")
elif state == 'Rejected':
print(f"❌ 订单被拒: {order_id} - 查 OKX App 原因")
```
## 实战决策表
| 第 1 层 | 第 2 层 | 第 3 层 | 综合判定 | agent 动作 |
|---|---|---|---|---|
| 有持仓 | frozen ≥ 期望 | filled | ✅ 成功 | 推"已跟单 X 张" |
| 有持仓 | frozen ≥ 期望 | live | ⏳ 挂单中 | 推"⏳ 挂单中 @ price" |
| 无持仓 | frozen < 期望 | 无 order_id | ❌ 静默失败 | raw REST 手动重下 |
| 无持仓 | frozen < 期望 | Rejected | ❌ 拒单 | raw REST 重下 + 调小 size |
| 无持仓 | frozen < 期望 | Canceled | 🚫 撤单 | raw REST 重下 |
| 有持仓但反向 | - | - | ⛔ dedup 反向 | 不动,推"⏭️ 反向持仓不跟" |
| 平仓信号 + 有同向持仓 | - | - | ✅ 应平仓 | raw REST 市价全平 |
## 用户质问 → 强制改进
每次用户质问"为什么没自动处理"时,都应触发本 checklist 复盘:
1. 是哪个 failure mode 触发了?
2. 当时为什么没识别?
3. 把识别规则加进 skill 或 process_signal.py
**已经触发的质问(2026-07-08)**:
- "你分析这些没有用" → v4.5.2 章节
- "回复侧不要数据" → v4.5.3 章节
- "要是我没发现,就一直不推了吗? 重试机制呢" → **本 reference**
- "执行成功但agent说没成" → v4.5.0 + 本 reference 第 1 层
## 修复优先级
未来如果重写 process_signal.py,这 3 层验证应该作为 post-execute 钩子**内置**到脚本里,不是依赖 agent 手动跑:
```python
# 建议的 process_signal.py 流程
def process_signal(text):
... # 解析 + advisor + execute
# post-execute hook (新增)
if signal_type == 'open' or signal_type == 'add':
time.sleep(1)
verify_execution(symbol, expected_contracts, expected_margin)
```
## 一句话总结
**不要相信 stdout。要相信 raw REST 反查持仓 + 余额变化。**