diff --git a/每周五Review命令.md b/每周五Review命令.md new file mode 100644 index 00000000..faa6d352 --- /dev/null +++ b/每周五Review命令.md @@ -0,0 +1,244 @@ +# 每周五 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` 记录