92 lines
4.1 KiB
Markdown
92 lines
4.1 KiB
Markdown
# v4.5.8 SKHY 暴涨 stopout session (2026-07-08)
|
|
|
|
## 背景
|
|
|
|
用户在 2026-07-08 收到多条熬鹰 SKHY (SK Hynix) 信号,跟单路径出现两个新坑:
|
|
|
|
1. **`📉 减仓` 信号不停损 bug** — 熬鹰 SKHY 从 168 → 187 暴涨,你持 SKHY short 0.81张@2x 浮亏扩大到 -$15.65 (占账户权益 16%),但 `📉 减仓` 信号走 advisor 推加减仓建议路径,**完全没触发止损**
|
|
2. **advisor SSL 失败频发** — 同一时段 BTC/SKHY/SPCX 多条信号都遇到 `urllib3.exceptions.SSLEOFError`,agent 报告"无 execute"但 raw REST 仍可用
|
|
|
|
## 时间线
|
|
|
|
```
|
|
16:30 熬鹰 SKHY short 新开仓 7479张 @168.06, advisor 推 0.81张@2x 已跟, avgPx=168.61, 浮亏 -$0.08
|
|
16:50 SKHY 涨到 175+, 浮亏 -$5+
|
|
17:00 SKHY 涨到 180+, 浮亏 -$9+
|
|
17:10 熬鹰 SKHY 减仓信号(5649张,@2x @168.06 → @187.89),agent 推"性价比低, +0.14张",**没触发止损**
|
|
17:11 熬鹰 SKHY 平仓信号, system 报 `⏭️ 重复信号跳过` (因上条刚走 dedup 路径)
|
|
17:20 用户问 "这个没推平仓信号" — 提醒 agent 减仓信号应该带止损检查
|
|
17:25 SKHY 涨到 188+, 浮亏 -$15.65 (16% 账户权益)
|
|
17:30 用户问 "要是我没发现,就一直不推了吗?重试机制呢"
|
|
```
|
|
|
|
## 用户原话
|
|
|
|
> "这个没推平仓信号"
|
|
> "要是我没发现,就一直不推了吗?重试机制呢"
|
|
> "你分析这些没有用,不需要你分析,该分析的都在skill里了"
|
|
> "我是指这个信息,是你分析的吗,只需要把跟单结果中涉及数据相关的推给QQ,这里不需要推"
|
|
|
|
## 学到的教训
|
|
|
|
1. **`📉 减仓` + 大幅浮亏 = 必须紧急止损** — 不能等 advisor 算加减仓建议
|
|
2. **dedup 修复后又踩新坑** — `⏭️ 重复信号跳过` 仍可能命中平仓信号,需要验证修复覆盖所有路径
|
|
3. **advisor SSL 失败 ≠ execute 失败** — agent 应该自动 retry + raw REST fallback
|
|
4. **用户最讨厌 agent 主观分析** — 回复侧只报核心状态,数据全推QQ
|
|
|
|
## 已修复 (v4.5.4 dedup + v4.5.8 紧急止损)
|
|
|
|
- v4.5.4: `signal_type == 'close'` 走独立通道,只看 raw_text hash 唯一性
|
|
- v4.5.8: `signal_type == 'reduce'` + `abs(upl) / totalEq > 0.15` 自动升级为 close + 市价全平
|
|
|
|
## 待修 (下次session优先)
|
|
|
|
- advisor SSL 失败时**自动 retry + raw REST fallback** 还没写进 process_signal.py,只在 SKILL.md 写了规则
|
|
- 用户原话"重试机制呢"提醒:agent 必须有 retry 而不只是报告失败
|
|
|
|
## 紧急止损阈值
|
|
|
|
```
|
|
abs(upl) / totalEq > 0.15 → 触发紧急止损
|
|
abs(upl) > $10 → 触发紧急止损 (小账户兜底)
|
|
```
|
|
|
|
例如:
|
|
- totalEq = $100, upl = -$15 → 触发
|
|
- totalEq = $50, upl = -$7.5 → 触发
|
|
- totalEq = $50, upl = -$5 → 不触发 (8.6%, 接近但未到15%)
|
|
|
|
## raw REST 紧急止损脚本模板
|
|
|
|
```python
|
|
import json, time, hmac, hashlib, base64, requests
|
|
|
|
def okx_post(path, body, t=15):
|
|
creds = open('/home/openclaw/.bashrc').read()
|
|
k = s = pw = None
|
|
for l in creds.split('\n'):
|
|
if l.startswith('export OKX_API_KEY='): k = l.split('=',1)[1].strip().strip('"').strip("'")
|
|
elif l.startswith('export OKX_SECRET='): s = l.split('=',1)[1].strip().strip('"').strip("'")
|
|
elif l.startswith('export OKX_PASSPHRASE='): pw = l.split('=',1)[1].strip().strip('"').strip("'")
|
|
body_str = json.dumps(body)
|
|
ts = time.strftime('%Y-%m-%dT%H:%M:%S.000Z', time.gmtime())
|
|
msg = ts + 'POST' + path + body_str
|
|
sig = base64.b64encode(hmac.new(s.encode(), msg.encode(), hashlib.sha256).digest()).decode()
|
|
h = {'OK-ACCESS-KEY': k, 'OK-ACCESS-SIGN': sig, 'OK-ACCESS-TIMESTAMP': ts,
|
|
'OK-ACCESS-PASSPHRASE': pw, 'Content-Type': 'application/json'}
|
|
px = {'http':'http://127.0.0.1:7890','https':'http://127.0.0.1:7890'}
|
|
return requests.post(f'https://www.okx.com{path}', data=body_str,
|
|
headers=h, proxies=px, timeout=t).json()
|
|
|
|
# 紧急止损:平 SKHY short
|
|
result = okx_post('/api/v5/trade/order', {
|
|
'instId': 'SKHY-USDT-SWAP',
|
|
'tdMode': 'cross',
|
|
'side': 'buy', # 平空 → buy
|
|
'posSide': 'net',
|
|
'ordType': 'market',
|
|
'sz': '0.81', # 实际持仓张数, 从 raw REST 查
|
|
'reduceOnly': True
|
|
})
|
|
print(result)
|
|
``` |