Files
Hermes-Skills/okx-auto-position/references/v4.5.45-lock-status-push-and-auto-unlock.md
T

174 lines
5.6 KiB
Markdown

# v4.5.45 (2026-08-06) 锁状态推送 + 自动解锁 + 手动解锁 CLI
## 背景
用户连续纠正:
- "锁了要你要消息推给我啊,不然我每次去问吗" → 锁了必须推 QQ
- "现在都平仓了,肯定解锁啊" → 平仓必须自动解锁
- "还有几个锁?每次推送时要显示所有锁的状态" → 每次推送附所有锁
- "这就是了" → 用户期待"我转发信号 → 正常跟单",不要每次问
## 3 个新行为
### 1. 锁了必须推 QQ(原行为是沉默)
**旧行为** `process_signal.py`:
```python
allowed, lock_msg = check_signal_lock(symbol, trader, side_en)
if not allowed:
return f"🔒 {lock_msg}" # ❌ 只回 return, 不推 QQ
```
**新行为** (2026-08-06):
```python
allowed, lock_msg = check_signal_lock(symbol, trader, side_en)
if not allowed:
msg = f"""🔒 **跟单被锁** 🔒
📊 币种: {symbol}
📈 当前信号: {trader} {side} {leverage}x
🚫 锁信息: {lock_msg}
💡 提示: 同币种只能锁一个 trader. 如要切跟, 用 `/unlock {symbol}` 解锁或告诉我换 trader.
"""
push_to_qq(msg)
return f"🔒 {lock_msg} | 已推 QQ"
```
**为什么**: 用户原话"锁了要你要消息推给我啊,不然以为是Bug"。
### 2. 平仓自动解锁
**旧行为**: close 信号 → 平仓 → 锁**留着**(下次同币种信号又拒)
**新行为** (2026-08-06):
```python
if signal_type == 'close':
...
close_result = close_position_raw(symbol_usdt, signal_side_en)
...
# 2026-08-06: 平仓后自动释放锁
from signal_tracker import release_lock
released, lock_msg = release_lock(symbol_usdt, trader, auto=True)
if released:
msg += f"\n\n🔓 锁已释放: {lock_msg}"
push_to_qq(msg)
return f"✅ 平仓处理: {close_result['action']} | {symbol_usdt} {signal_side_en} | {lock_msg}"
```
**为什么**: 用户原话"现在都平仓了,肯定解锁啊"。
**lock_expiry 在 signal_tracker.py**: 默认 72h,但平仓不触发自动 unlock — **现在修了**。
### 3. 每次推送附所有锁状态
**新增 helper** `_locks_status_text()`:
```python
def _locks_status_text():
"""所有锁状态 - 附加在每个推送尾部"""
try:
locks = list_locks()
except Exception:
return ""
if not locks:
return ""
lines = ["\n\n🔒 **当前所有锁**:"]
for l in locks:
symbol = l['symbol']
trader = l['trader']
side = l['side']
locked_at = l['locked_at']
from datetime import datetime
try:
ts = datetime.fromisoformat(str(locked_at).replace('Z', ''))
hours = (datetime.now() - ts).total_seconds() / 3600
age = f"{hours:.1f}h"
except Exception:
age = "?"
lines.append(f" • {symbol} → **{trader}** {side} (锁 {age})")
return "\n".join(lines)
```
**为什么**: 用户原话"还有几个锁?每次推送时要显示所有锁的状态,不然怎么记得呢"。
**未来集成点**: 加到 `push_to_qq(msg)` 之后(写在每个推送尾部):
```python
msg += _locks_status_text()
push_to_qq(msg)
```
**当前状态**: helper 已写但**未集成到主流程**。下次修复时把 helper 嵌入到所有 push_to_qq() 之后。
### 4. 手动解锁 CLI
**新增 CLI** `process_signal.py unlock`:
```bash
# 列出所有锁
python3 process_signal.py unlock
# 解锁指定币种
python3 process_signal.py unlock BTC
# 解锁指定 trader 的锁(通常 auto=True)
python3 process_signal.py unlock BTC 熬鹰资本
```
**实现**:
```python
def main():
if _sys.argv[1] == 'unlock':
from signal_tracker import release_lock, list_locks
if len(_sys.argv) < 3:
locks = list_locks()
print(locks or "无锁")
return
symbol = _sys.argv[2]
trader = _sys.argv[3] if len(_sys.argv) > 3 else None
released, msg = release_lock(symbol, trader, auto=True)
push_to_qq(f"🔓 手动解锁: {msg}")
```
**为什么**: 给用户**手动解锁**的能力,不依赖平仓信号自动 unlock。
## 验证 (2026-08-06)
```bash
# 1. unlock 列表
$ python3 process_signal.py unlock
[
{'symbol': 'BTC', 'trader': '熬鹰资本', 'side': 'long', 'locked_at': '...'},
{'symbol': 'ETH', 'trader': '麻吉大哥', 'side': 'long', 'locked_at': '...'},
...
]
# 2. 解锁 BTC
$ python3 process_signal.py unlock BTC
🔓 解锁 BTC (前锁: 熬鹰资本 long)
```
## 完整时间线 (2026-08-06)
| 事件 | 时间(北京) | 动作 |
|------|------|------|
| 用户转发 BTC 做空信号 | 之前 | #45 入库,被熬鹰资本锁拒 |
| 用户质问"做空信号没跟单" | 23:00 | 查锁:BTC 被熬鹰资本 long 锁 |
| 用户说"锁了要推我" | 23:00 | 改 push_to_qq 锁拒绝路径 |
| 用户说"平仓了肯定解锁" | 23:01 | 改 close 路径 auto-unlock |
| 用户说"每次推送看所有锁" | 23:02 | 写 _locks_status_text() |
| 用户说"刚才 BTC 再处理一次" | 23:05 | 手动 `unlock BTC` |
| 用户转发测试 BTC short | 23:08 | 跑通,1.21 张,但实际未下单(测试单) |
## 仍未做的
1. **集成 `_locks_status_text()` 到所有 push_to_qq** — 当前只在 lock 拒绝路径用了
2. **close 自动 unlock 推到所有 push** — 当前只在 close 路径跑了一次
3. **unlock 应该有更智能的"自动检测平仓"** (检测 OKX 真实持仓为 0 时 unlock)
## 关联
- `signal_tracker.py` — `check_signal_lock`, `release_lock`, `list_locks`
- `v4.5.41-signal-queue-done-but-no-order-execute.md` — 下游执行
- `v4.5.42-insufficient-funds-explicit-notify.md` — 余额不足显式推送
- `forwarder-rule-enable-killer.md` — 上游链断排查
- `agent-workflow-feedback-rules.md` — 用户纠正的工作流硬规则