feat(crypto-t-monitor): v2.3.0 新币自动挑选池 (PICKS=2, POOL_MAX=6)

- NEW_COIN_PICKS=2: 每次扫描后筛 2 个 (按 24h vol 排序)
- NEW_COIN_POOL_MAX=6: 永久保留上限, 超限自动裁最早加入
- 30 天内新币 + 24h vol > $1M, 自动加入监控池
- 推 QQ 仅在变化时 (与 v2.1 C 方案一致)
- references/: 新增 backtest-usage.md, change-driven-push.md, symbol-coverage-pitfall.md

用户原话: 新币最多保留六个, 每次扫描后筛选

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-10 19:43:21 +08:00
co-authored by Claude
parent feb1e73bc9
commit 4aae222173
4 changed files with 728 additions and 0 deletions
@@ -0,0 +1,94 @@
# Symbol Coverage Pitfall (2026-07-10 实战)
## 症状
Cron 推送"💤 静默: 无持仓, 无变化"或"💤 无持仓, 跳过做T",但实际账户**持有 1.45 张 SPCX**(或其他币种)。
**用户原话**: "一直在提示吗... 这个定时任务没改名称, 是币圈还是股票"。后续他从来没问过是否持仓,但 agent 看到 cron 消息也没去查实际持仓,以为没问题。
## 根因
`okx_t_monitor.py``DEFAULT_SYMBOLS` 是静态列表:
```python
DEFAULT_SYMBOLS = ['ETH', 'BTC', 'SOL', 'DOGE', 'XRP'] # 漏了 SPCX
```
`monitor()` 循环每个币种拉 OKX 持仓,**只在循环里的币种才被监控**。SPCX 不在列表里 → 永远查不到 → 被视为"无持仓"。
`SYMBOL_SPECS` 也必须包含该币种,否则 `KeyError` 直接崩。
**变种 1**: 用户开了小众币种(非主流)做T,监控不到
**变种 2**: 用户开了 OKX 交易但用 ccxt 报"unexpected type" 失败的币种
## 修复:三步
**1. 把持仓币种加进 `DEFAULT_SYMBOLS`**:
```python
DEFAULT_SYMBOLS = ['ETH', 'BTC', 'SOL', 'DOGE', 'XRP', 'SPCX'] # + 持仓币
```
**2. 把持仓币种加进 `SYMBOL_SPECS`**(避免 KeyError):
```python
SYMBOL_SPECS = {
'ETH': {'ct_val': 0.1, 'leverage': 25, 't_qty': 0.05, 'min_sz': 0.01},
...
'SPCX': {'ct_val': 1.0, 'leverage': 5, 't_qty': 0.5, 'min_sz': 0.01},
# ⚠️ t_qty 是"每次做T张数", NOT "总持仓"
}
```
**3. (推荐) 自动检测持仓币种**:
```python
def get_monitored_symbols():
"""从 OKX 实际持仓 + 预设列表合并"""
syms = set(DEFAULT_SYMBOLS)
try:
positions = ex.fetch_positions()
for p in positions:
if abs(float(p.get('contracts', 0))) > 0.001:
inst_id = p.get('instId', '') # e.g. "SPCX-USDT-SWAP"
sym = inst_id.replace('-USDT-SWAP', '')
syms.add(sym)
except Exception as e:
print(f"⚠️ 拉持仓失败: {e}")
return sorted(syms)
```
`monitor()` 第一行调用 `DEFAULT_SYMBOLS = get_monitored_symbols()`
## 防御性编程
**新加币种时(尤其是用户/交易员信号里出现的)**:立刻同步 `DEFAULT_SYMBOLS``SYMBOL_SPECS`。否则:
- 信号来了推不到做T → 错过机会
- 平仓信号到了不被检测 → 持仓过夜
- 浮盈大幅波动不报警 → 用户不知道风险
**最稳**:用 `get_monitored_symbols()` 自动合并 + 当新币种出现时让用户填 SYMBOL_SPECS(告警一次后自动用默认 0.01 张)。
## 实测教训
**SPCX 1.45 张空 @ 149.15** 在 2026-07-10 上午被实测发现时,DEFAULT_SYMBOLS 没有,SYMBOL_SPECS 也没有,导致:
1. cron 跑 N 次,显示"💤 无持仓"
2. 实际有 SPCX 持仓但**变化检测 + 做T 触发都跳过**
3. 浮盈变化根本不被监控
4. 价格触及 buy1/buy2/sell1/sell2 也不会触发平仓
**修复后**:
- DEFAULT_SYMBOLS += ['SPCX']
- SYMBOL_SPECS['SPCX'] = {'ct_val': 1.0, 'leverage': 5, 't_qty': **0.5**(不是 1.45!), 'min_sz': 0.01}
- 下次 cron 跑 → 检测 SPCX 价格触及 149.15 ± ATR×0.7 → 自动推送"📍 价格触及"或成交
## t_qty 重要澄清
`t_qty` 是**每次做T张数**,不是总持仓大小。
- SPCX 持仓 1.45 张,t_qty = 0.5 → 每次 low/high 0.5 张,做满要 3 次
- 1.45 张仓位 + 做 T 一次就 1 张 → 仓位瞬间变化 67%,太大
**规则**:`t_qty ≤ 总仓位 × 0.5`(单笔不超过一半仓位)。
## 相关决策
- v2.1 C 方案"有变化时推"上线后,**静默覆盖了**"持仓不在列表"的 bug——之前会推"💤 无持仓"噪音,现在静默不推,bug 隐藏更深。
- **必须**每 24 小时或新币种出现时,核对 DEFAULT_SYMBOLS 是否包含全部持仓币种
- 实战:应该用 `get_monitored_symbols()` 而不是静态列表