Files
Hermes-Skills/okx-auto-position/references/v4.5.42-insufficient-funds-explicit-notify.md

94 lines
4.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# v4.5.42 (2026-08-05) 余额不足显式推送通知 + exit code != 0
## ⚠️ 用户原话 (2026-08-05 触发本次修复)
> "这种余额不够的要通知啊,不然以为是Bug"
**场景**: 8/4 20:32 SNDK 加仓信号 (4 条 done), 用户 8/5 11:20 问"跟了吗", 答"已推(193.32→197.17张); 你无SNDK持仓; USDT $95.52", 用户反馈 "这个没有跟单成功吧"。
**问题**: `process_signal.py` 余额不足时只推 QQ 普通消息 + `outcome='pushed_add_insufficient'`, 但 `signal_queue.db` 仍标 `status='done'`, 用户看到 done 以为是真跟单。
## 🛠️ 已部署修复 (2026-08-05 commit `f00b696`)
### 1. 余额不足显式标识 (`process_signal.py` line 802-829)
```python
elif signal_type == 'add':
exec_result = execute_order(symbol, side, leverage, rec)
if exec_result and 'error' not in exec_result and rec.get('contracts', 0) > 0:
# 真下单成功 → 推执行结果 + outcome='auto_executed_add'
...
else:
# 余额不足/执行失败 → 显式前缀 + USDT 余额显示
exec_err = (exec_result or {}).get('error', 'unknown')
is_insufficient = '余额不足' in str(exec_err) or 'insufficient' in str(exec_err).lower()
usdt_free = _get_usdt_free() # 实时查 OKX
if is_insufficient:
msg = f"⚠️ **跟单失败: 余额不足** ⚠️\n\n{msg}\n\n💡 你 USDT ${usdt_free:.2f} 不足以开 1 张 {symbol} 3x 杠杆 (约需 ~$46k)\n"
outcome = 'pushed_add_insufficient'
else:
msg = f"⚠️ **跟单失败: 执行错误** ⚠️\n\n{msg}\n\n❌ 错误: {exec_err}\n"
outcome = 'auto_executed_failed'
...
```
### 2. exit code 2 让 signal_queue 标 failed (`process_signal.py` main())
```python
result = process_signal(text)
print(result)
if '跟单失败' in str(result):
sys.exit(2) # signal_queue.retry 看到 rc != 0 → mark_failed
```
### 3. _get_usdt_free() helper (`process_signal.py` 604-619)
```python
def _get_usdt_free():
"""实时查 OKX USDT free (失败返回 0)."""
try:
from okx_position_advisor import load_credentials, create_exchange
creds = load_credentials()
ex = create_exchange(creds)
bal = ex.fetch_balance()
usdt_info = bal.get('USDT', {}) if isinstance(bal, dict) else {}
free = usdt_info.get('free', 0) if isinstance(usdt_info, dict) else 0
return float(free or 0)
except Exception as e:
print(f"[warn] _get_usdt_free err: {e}", file=__import__('sys').stderr)
return 0.0
```
## 🎯 修复效果 (预期)
| 场景 | 之前 | 现在 |
|------|------|------|
| 余额足够, 真下单 | QQ 推"已跟单 X 张 @ Yx" + status=done | 不变 |
| 余额不足, advisor contracts=0 | QQ 推普通信号消息 + status=done ⚠️ | QQ 推 **"⚠️ 跟单失败: 余额不足 ⚠️ + USDT X 不足以开 1 张"** + status=failed |
| advisor execute 报错 | QQ 推普通信号消息 + status=done ⚠️ | QQ 推 **"⚠️ 跟单失败: 执行错误 ⚠️ + 错误信息"** + status=failed |
| 反向锁跳过 | 推"🔒 跳过" + status=done | 不变 (这不是执行失败) |
## 📊 实战数据 (2026-08-05 11:00 当前 OKX USDT)
| 信号 | 大佬仓位 | 所需保证金 | USDT $107 能跟吗 |
|------|----------|------------|------------------|
| SNDK 做空 197.17 张 @ 1390 × 3x | $46k+ | ❌ 不够 (但 advisor 会自动调张到 0.056 张, 占 99.7% 余额) |
| BTC 做多 1000 张 @ $64k × 10x | $6.4k | ❌ 不够 (advisor 调张到 1.25 张) |
| BTC 0.01 张 @ $64k × 10x | $640 | ❌ 不够 |
**关键洞察**: advisor 不是直接 0 张,而是按可用余额自动调小到 1 张或更少 → **跟单了但只下了 0.x 张,用户以为"真跟了 0 张失败"**, 实际"跟了但用了 99.7% 余额"。
## 🚨 关键提醒 (下次 session)
1. **用户偏好**: 余额不足**必须显式通知**, 不能"看起来跟了实际没跟"
2. **信号推送文案**: 用 `⚠️ **跟单失败: 余额不足** ⚠️` 前缀, 不要混在普通推送里
3. **status 闭环**: process_signal rc != 0 → signal_queue 标 failed → cron retry 还能再试
4. **USDT < $50k 时**, 几乎所有熬鹰大单 (SNDK/BTC 100+ 张) 都跟不了, 用户应主动入金
## 🔗 关联文件
- `scripts/process_signal.py` line 604-619 (_get_usdt_free helper)
- `scripts/process_signal.py` line 802-829 (余额不足分支)
- `scripts/process_signal.py` main() (exit code 2)
- `scripts/signal_queue.py` (mark_failed 已支持)
- 实战案例: `references/v4.5.41-signal-queue-done-but-no-order-execute.md` (问题描述)