# 每周五 Bench Review 完整流程

> 每周五在服务器上跑一遍，把输出贴给 AI 代理分析。
> AI 代理按 AGENT.md 的 5 个维度给建议，人类拍板执行。

---

## 第 1 步：重新跑 30 天回测

> **做什么**：用最新的 cache 数据，对 backtest.json 里的所有钱包（live + bench）跑一次 30 天模拟跟单，产出 portfolio.json
>
> **相关文件**：`backtest.json`（输入：钱包列表）-> `portfolio.json`（输出：前瞻盈亏）

```bash
cd /opt/winning-wallet-finder/live && python3 portfolio.py --days 30
```

---

## 第 2 步：看每个钱包的前瞻盈亏排名

> **做什么**：读 portfolio.json 的 wallets 数组，按 30 天前瞻 realized 盈亏排序，标注哪个是 LIVE 哪个是 bench
>
> **相关文件**：`portfolio.json`（读）-> `copybot.paper.json`（对比哪些是 LIVE）
>
> **这是决策的核心数据**：前瞻 realized > 0 才考虑保留，连续 2 周负考虑降级

```bash
python3 -c "
import json
d = json.load(open('portfolio.json'))
live_names = {'Kruto2027','0xbadaf319','1kto1m','Vahan88','LSB1','EdwardIN','lma0o0o0o','Coteykens'}
ws = d.get('wallets', [])
print('=== 30天前瞻盈亏排名 ===')
print(f'{\"钱包\":20s} {\"笔数\":>4s} {\"胜\":>3s} {\"负\":>3s} {\"卖\":>3s} {\"已实现\":>10s} {\"状态\":>6s}')
print('-' * 60)
for w in sorted(ws, key=lambda x: x.get('realized',0), reverse=True):
    name = w.get('name','?')
    tag = 'LIVE' if name in live_names else 'bench'
    print(f'{name:20s} {w.get(\"bets\",0):4d} {w.get(\"won\",0):3d} {w.get(\"lost\",0):3d} {w.get(\"sold\",0):3d}  \${w.get(\"realized\",0):+9.2f}  {tag:>6s}')
print(f'\n总计: equity \${d[\"equity\"]:,.0f} | realized \${d[\"realized\"]:+,.0f} | {d[\"resolved_count\"]} resolved')
"
```

---

## 第 3 步：看候选池排名

> **做什么**：读 watch_sharps.json，按 copy_pnl 排序，看信念胜率和前瞻胜率
>
> **相关文件**：`watch_sharps.json`（daily.sh 自动产出）
>
> **注意**：copy_pnl 是 in-sample 的，会骗人（oliman2 copy_pnl #1 但前瞻亏）。只作参考，不作决策依据

```bash
cat watch_sharps.json | python3 -c "
import sys,json
data=json.load(sys.stdin)
data.sort(key=lambda w: w.get('copy_pnl',0), reverse=True)
print('=== watch_sharps 候选排名 ===')
for i,w in enumerate(data):
    name = w.get('name') or w.get('wallet','')[:10]
    win = w.get('conv_win')
    winstr = f'{win:.0f}%' if win is not None else '?'
    fwd = w.get('fwd_win',0)
    fwdstr = f'{fwd:.0f}%' if fwd else '?'
    print(f'#{i+1:2d} {name:20s} copy_pnl+{w.get(\"copy_pnl\",0):5d} conv_win={winstr} fwd_win={fwdstr}')
print(f'\n总共 {len(data)} 个候选')
"
```

---

## 第 4 步：看 floor 有没有漂移

> **做什么**：读 daily.log 里 sync_floors 的输出，看有没有门槛大幅漂移的警告
>
> **相关文件**：`daily.log`（读）-> `copybot.paper.json`（floor 被 sync_floors.py 写入）
>
> **判断**：`⚠ floor X->Y` 漂移 > 15% -> 建议钉 floor_pin 防止 paper/live 门槛不一致

```bash
grep "floor" daily.log | tail -10
```

---

## 第 5 步：看本周 bot 跟单记录

> **做什么**：读 live bot 最近 7 天的日志，看 FOLLOW（跟了什么）、skip（跳过了什么）、OPEN（实际下单了什么）
>
> **相关文件**：journalctl（systemd 日志）
>
> **用途**：看 bot 实际跟了哪些信号、有没有异常（大量 skip / ORDER FAILED / RTDS down）

```bash
journalctl -u copybot-live --since "7 days ago" --no-pager | grep -E "FOLLOW|OPEN|skip" | tail -30
```

---

## 第 6 步：看链上真实余额

> **做什么**：通过 SecureClient 查存款钱包的实际 pUSD 余额
>
> **相关文件**：`/etc/copybot/live.env`（读私钥）-> Polymarket 链上
>
> **用途**：确认真实资金状况，对比 bot 账本是否一致（CASH≠CHAIN）

```bash
export LIVE_PRIVATE_KEY=$(grep LIVE_PRIVATE_KEY /etc/copybot/live.env | cut -d= -f2-) && export HTTPS_PROXY=http://127.0.0.1:7890 && python3 -c "from polymarket import SecureClient; c=SecureClient.create(private_key='$LIVE_PRIVATE_KEY'); b=c.get_balance_allowance(asset_type='COLLATERAL'); print('链上 pUSD: %.2f' % (b.balance/1e6)); c.close()"
```

---

## 第 7 步：找出新候选（watch_sharps 里有但 backtest.json 里没有的）

> **做什么**：对比 watch_sharps.json 和 backtest.json，找出 daily.sh 新筛出来但还没在观察区的钱包
>
> **相关文件**：`watch_sharps.json`（读：全部候选）+ `backtest.json`（读：已在观察的）
>
> **用途**：发现新钱包，如果 copy_pnl 高 + 信念胜率好，加到 backtest.json 开始观察前瞻表现

```bash
python3 -c "
import json
sharps = json.load(open('watch_sharps.json'))
bt = json.load(open('backtest.json'))
bt_addrs = {w['wallet'].lower() for w in bt['wallets']}

new_candidates = [w for w in sharps if w.get('wallet','').lower() not in bt_addrs]
new_candidates.sort(key=lambda w: w.get('copy_pnl',0), reverse=True)

print('=== watch_sharps 里的新候选（不在 backtest.json 里）===')
print(f'watch_sharps 总共 {len(sharps)} 个，backtest.json 已有 {len(bt[\"wallets\"])} 个')
print(f'新候选: {len(new_candidates)} 个')
print()
print(f'{\"名字\":20s} {\"copy_pnl\":>10s} {\"信念胜率\":>8s} {\"前瞻胜率\":>8s}')
print('-' * 50)
for w in new_candidates[:15]:
    name = w.get('name') or w.get('wallet','')[:10]
    win = w.get('conv_win')
    winstr = f'{win:.0f}%' if win is not None else '?'
    fwd = w.get('fwd_win',0)
    fwdstr = f'{fwd:.0f}%' if fwd else '?'
    print(f'{name:20s} +{w.get(\"copy_pnl\",0):9d} {winstr:>8s} {fwdstr:>8s}')
"
```

---

## 一键跑全部 7 步

> 如果想一次性跑完所有步骤，复制下面整段：

```bash
cd /opt/winning-wallet-finder/live

echo "========== 第 1 步：跑回射 =========="
python3 portfolio.py --days 30

echo ""
echo "========== 第 2 步：前瞻盈亏排名 =========="
python3 -c "
import json
d = json.load(open('portfolio.json'))
live_names = {'Kruto2027','0xbadaf319','1kto1m','Vahan88','LSB1','EdwardIN','lma0o0o0o','Coteykens'}
ws = d.get('wallets', [])
print('=== 30天前瞻盈亏排名 ===')
print(f'{\"钱包\":20s} {\"笔数\":>4s} {\"胜\":>3s} {\"负\":>3s} {\"卖\":>3s} {\"已实现\":>10s} {\"状态\":>6s}')
print('-' * 60)
for w in sorted(ws, key=lambda x: x.get('realized',0), reverse=True):
    name = w.get('name','?')
    tag = 'LIVE' if name in live_names else 'bench'
    print(f'{name:20s} {w.get(\"bets\",0):4d} {w.get(\"won\",0):3d} {w.get(\"lost\",0):3d} {w.get(\"sold\",0):3d}  \${w.get(\"realized\",0):+9.2f}  {tag:>6s}')
print(f'\n总计: equity \${d[\"equity\"]:,.0f} | realized \${d[\"realized\"]:+,.0f} | {d[\"resolved_count\"]} resolved')
"

echo ""
echo "========== 第 3 步：候选池排名 =========="
cat watch_sharps.json | python3 -c "
import sys,json
data=json.load(sys.stdin)
data.sort(key=lambda w: w.get('copy_pnl',0), reverse=True)
print('=== watch_sharps 候选排名 ===')
for i,w in enumerate(data):
    name = w.get('name') or w.get('wallet','')[:10]
    win = w.get('conv_win')
    winstr = f'{win:.0f}%' if win is not None else '?'
    fwd = w.get('fwd_win',0)
    fwdstr = f'{fwd:.0f}%' if fwd else '?'
    print(f'#{i+1:2d} {name:20s} copy_pnl+{w.get(\"copy_pnl\",0):5d} conv_win={winstr} fwd_win={fwdstr}')
print(f'\n总共 {len(data)} 个候选')
"

echo ""
echo "========== 第 4 步：floor 漂移 =========="
grep "floor" daily.log | tail -10

echo ""
echo "========== 第 5 步：本周跟单记录 =========="
journalctl -u copybot-live --since "7 days ago" --no-pager | grep -E "FOLLOW|OPEN|skip" | tail -30

echo ""
echo "========== 第 6 步：链上余额 =========="
export LIVE_PRIVATE_KEY=$(grep LIVE_PRIVATE_KEY /etc/copybot/live.env | cut -d= -f2-) && export HTTPS_PROXY=http://127.0.0.1:7890 && python3 -c "from polymarket import SecureClient; c=SecureClient.create(private_key='$LIVE_PRIVATE_KEY'); b=c.get_balance_allowance(asset_type='COLLATERAL'); print('链上 pUSD: %.2f' % (b.balance/1e6)); c.close()"

echo ""
echo "========== 第 7 步：新候选 =========="
python3 -c "
import json
sharps = json.load(open('watch_sharps.json'))
bt = json.load(open('backtest.json'))
bt_addrs = {w['wallet'].lower() for w in bt['wallets']}
new_candidates = [w for w in sharps if w.get('wallet','').lower() not in bt_addrs]
new_candidates.sort(key=lambda w: w.get('copy_pnl',0), reverse=True)
print('=== watch_sharps 里的新候选（不在 backtest.json 里）===')
print(f'watch_sharps 总共 {len(sharps)} 个，backtest.json 已有 {len(bt[\"wallets\"])} 个')
print(f'新候选: {len(new_candidates)} 个')
print()
print(f'{\"名字\":20s} {\"copy_pnl\":>10s} {\"信念胜率\":>8s} {\"前瞻胜率\":>8s}')
print('-' * 50)
for w in new_candidates[:15]:
    name = w.get('name') or w.get('wallet','')[:10]
    win = w.get('conv_win')
    winstr = f'{win:.0f}%' if win is not None else '?'
    fwd = w.get('fwd_win',0)
    fwdstr = f'{fwd:.0f}%' if fwd else '?'
    print(f'{name:20s} +{w.get(\"copy_pnl\",0):9d} {winstr:>8s} {fwdstr:>8s}')
"

echo ""
echo "========== 全部完成，把以上输出贴给 AI 代理分析 =========="
```

---

## 跑完后

1. 把全部输出复制给 AI 代理
2. AI 代理按 AGENT.md 的 5 个维度分析，输出建议报告
3. 人类根据建议做决策
4. 人类在服务器执行变更（晋升/降级/钉 floor/加新候选）
5. 变更后更新 `setup_wallets.py` 记录
