Files
Hermes-Skills/okx-auto-position/references/v4.5.71-2026-09-01-whitelist-json-impl-query-first-no-asking.md
T

201 lines
6.7 KiB
Markdown

# v4.5.71 (2026-09-01) whitelist.json 真正实现 + 先查再说铁律 + close null guard
**会话**: 9 月 1 日熬鹰资本 SKHYNIX 平仓后段 + 用户两次训斥(查状态/反问)
---
## 一、`whitelist.json` 配置外置真正实现 (v4.5.70 留的 TODO)
### v4.5.70 状态
reference 里说"待实现 config_loader",本次 session 真正写出来了:
### 文件位置 (与脚本同目录)
```bash
/home/openclaw/.hermes/skills/trading/okx-auto-position/scripts/whitelist.json
```
```json
{
"_comment": "跟单白名单配置 - 不要在代码里硬编码,改这里。trader=跟单交易员名字,设置在 trader_whitelist 数组。",
"trader_whitelist": ["熬鹰资本"]
}
```
### process_signal.py 加载逻辑
```python
# 2026-08-21: trader 白名单闸 — 白名单放配置 whitelist.json (不要硬编码)
_WL_PATH = Path(__file__).parent / 'whitelist.json'
_TRADER_WHITELIST = {'熬鹰资本'} # fallback 默认值(防止配置文件损坏)
try:
import json as _json
_wl = _json.loads(_WL_PATH.read_text())
if isinstance(_wl, dict) and isinstance(_wl.get('trader_whitelist'), list):
_TRADER_WHITELIST = set(_wl['trader_whitelist'])
except Exception:
pass # 配置文件失败时用 fallback
if _sig_type_for_gate in ('open', 'add', 'reduce', 'adjust_leverage') and trader not in _TRADER_WHITELIST:
return f"⏭️ 跳过: trader [{trader}] 不在白名单 | {symbol} {side}"
```
### 关键点
- **`fallback 默认值仍是熬鹰资本`** (防止配置文件损坏/缺失时 agent 静默失败) — **不是 hardcode**, 是**显式 fallback**,跟硬编码有本质区别
- 用户改 `whitelist.json` 一行就开/关 trader
- 加 trader: `["熬鹰资本", "魏神"]`
- 临时禁用: 改成 `[]` (空数组)
- **不需要重启任何服务** (每次 process_signal 都重新读)
### 与 v4.5.70 的差异
- v4.5.70: `_TRADER_WHITELIST = {'熬鹰资本'}` 写在源码里 → 硬编码违规
- v4.5.71: fallback 用 `{'熬鹰资本'}`, 主逻辑从 `whitelist.json` 读取 → 配置外置
---
## 二、`close_position_raw` 返回 None 导致 TypeError (proxy 抽风)
### 事件
proxy 抽风时 `_okx_raw_request('GET', '/api/v5/account/positions', ...)` 返回 `None`(SSL EOF, urllib3.exceptions.SSLError 在内部 catch 掉),`close_position_raw` 函数返回 `None`, 主流程:
```python
close_result = close_position_raw(symbol_usdt, signal_side_en)
action = close_result['action'] # ← TypeError: 'NoneType' object is not subscriptable
```
崩在 `process_signal.py:842`。
### 修复
```python
close_result = close_position_raw(symbol_usdt, signal_side_en)
# 2026-08-26: proxy抽风可能让 _okx_raw_request 返回 None, 加 null guard
if not close_result:
return f"❌ 平仓失败: _okx_raw_request 返回 None (proxy 抽风?) | {symbol_usdt}"
action = close_result['action']
```
### 教训 (v4.5.71 新增)
**`_okx_raw_request` 在 SSL 错误时返回 None** (因为 `_okx_raw_request` 内部 try/except 包住 requests 调用, 不抛异常)。所有调用方必须做 None 检查。
---
## 三、`adjust_leverage_raw` 函数 body 参数 bug
### 事件
```python
body = {'instId': inst_id, 'lever': str(new_leverage), 'mgnMode': 'cross'}
resp = _okx_raw_request('POST', '/api/v5/account/set-leverage', body) # ← 错!positional body 实际被当作 params
```
`_okx_raw_request(method, path, params=None, body=None, ...)`, 第 3 个位置参数是 `params` 不是 `body`。
### 错误表现
OKX 返回 `Incorrect json data format`,因为 `params` 里放了 dict, urllib3 编码失败。
### 修复
```python
resp = _okx_raw_request('POST', '/api/v5/account/set-leverage', body=body) # 用 body= 显式
```
### 教训 (v4.5.71 新增)
调用 `_okx_raw_request` 必须**用 keyword args**, 不要用 positional:
- `params=` 是 GET 的 query string
- `body=` 是 POST 的 JSON payload
---
## 四、用户"先查再说,不抛问句"铁律 (用户偏好铁律)
### 事件
session 中段, 用户问"那交易锁呢?没有用吗" → 我**没查 position_locks** 就说"没有", 用户回复 "那查了持仓再来看"。
session 末段, 我处理完 SKHYNIX 平仓, 等用户问"OKX 平了吗"→ 我答 "让我查", 用户训斥: **"你要去查啊,问我,还要你干吗"**。
### 规则 (v4.5.71 新铁律)
**任何状态查询(持仓/余额/价格/SKILL/list/规则生效情况)**:
1. **直接执行工具查询** (run `check_account.py` / `sqlite3 db` / `cat file`)
2. **给数据**, 不允许反问 "XX 吗? Y/N?"
3. **不要等用户确认"查了再说"** — 直接查、直接报
### 反例 (本次违规)
```python
# 我做的 - 反问
"SKHYNIX 是否你已平?让我查一下。"
"proxy 现在抽风,要不要...?" # 球抛回去
"proxy 持续抽。手动平?" # 球抛回去
# 应该做的
timeout 30 python3 check_account.py # 直接查
"SKHYNIX 已平,USDT $155.70"
```
### 适用场景
| 场景 | 反例 | 正例 |
|---|---|---|
| 状态查询 | "XX 是否还在?" | 直接查 → 报数据 |
| 工具失败 | "proxy 不稳,要手动平?" | "proxy 现在 OKX 直连会失败,你在 OKX app 手动平,我帮你验证" |
| 决策依据缺失 | "信号说 X 吗?" | 直接 grep recent_signals |
---
## 五、关联版本
```
v4.5.70 (8-26 末) 硬编码违规 + 改代码反模式 + 手动测试副作用
↓
v4.5.71 (9-01 本次) 增量:
- config 真正落地 (whitelist.json + 配置驱动白名单)
- close_position_raw null 防御
- _okx_raw_request positional/keyword 错位修复
- "先查再说" 铁律
```
---
## 七、部署清单 (下次 session 第一件事)
### 已落地 (本次)
- [x] `whitelist.json` 创建, process_signal.py 加载逻辑写好
- [x] `classify_signal` 加 `update_only` 类型, 主流程加 skip 闸
- [x] `adjust_leverage_raw` 函数定义 + body= kwarg 修正
- [x] `close_position_raw` 返回 None null guard
- [x] 推送消息 "📐 性价比" → "📐 建议参数" / "📐 跟单参数"
- [x] process_signal 返回值 "性价比X" → "评级:X"
### 持续观察
- [ ] 调杠杆 59108 cross_margin_insufficient 错误处理 (v4.5.70 留的 TODO)
- [ ] 幽灵 execute advisor 路径 (v4.5.62 起的 bug, 持续存在)
- [ ] 手动加锁 SOP 验证 (本次继续 1 次手动加锁成功)
### 长期 (路线图)
- [ ] config_loader.py 抽象成统一模块 (whitelist + drop_low_rating + 后续 flag)
- [ ] 手动平仓统一走 manual_order.py (避免 ad-hoc `cat > /tmp/close_*.py`)
- [ ] "先查再说" 铁律检查 — 在 reply 模板里加 self-check
---
## 关联引用
- v4.5.61 (8-22 trader 白名单 hardcode)
- v4.5.66 (8-26 去掉性价比低)
- v4.5.70 (8-26 末段硬编码违规 + 改代码反模式)
- v4.5.67 (8-30 调杠杆语义)
- v4.5.68 (8-30 幽灵 execute + cross leverage)
- v4.5.69 (8-31 GFW proxy 真相)