# 项目使用手册（USAGE.md）

> Polymarket 跟单系统 — 找会赢的钱包 → 纸盘回测 → 实盘跟单
>
> 写于 2026-07-17。配合 `README.md`、`live/README.md`、`live/仪表盘说明.md`、`HANDOFF.md`、`实盘配置.md` 一起看。

---

## 0. 三句话理解项目

1. **找钱包**：从 Polymarket 全网数据里，按 5 道统计门（z-score、FDR、样本外一致性等）筛出 ~3% 真有 edge 的钱包，落到 `live/watch_skilled.json`；再用"信念门槛（每钱包自己下注前 20% 才叫信念单）"筛出 12 个可复制的，落到 `live/watch_sharps.json`。
2. **回测**：拿这些钱包的历史已结算单，按 4% 资金 + 真实手续费 + 0.5% 滑点重放一遍，写出 $1000 的纸盘账户进出，落到 `live/portfolio.json`（纸盘与实盘共用同一个回放引擎，确保一致）。
3. **跟单**：跟单 bot（`copybot.py`）24/7 监听这些钱包的新交易，paper 模式只记账，live 模式（`--live` + `LIVE_CONFIRM`）才真下单。

整个系统分三层：**离线找钱包 + 纸盘验证 → 跟单 bot 跑 paper → 跟单 bot 切 live**。

---

## 1. 仓库结构

```
winning-wallet-finder/
├── README.md                   ← 项目总览（论文背景、findings）
├── HANDOFF.md                  ← 接手文档（关键决策与已知坑）
├── FINDINGS.md                 ← 研究发现汇总
├── 实盘配置.md                 ← 实盘钱包/私钥配置（已写过）
├── ETHERSCAN_MIGRATION.md      ← Etherscan 数据迁移说明
├── requirements.txt            ← 依赖（核心用 Python 3 stdlib）
│
├── smart_money.py              ← Polymarket data-api 客户端（共用）
├── insider.py                  ← 内部人/聪明钱检测
├── copybot.py                  ← ★ 跟单 bot（paper/live 两用）
├── copytrade.py                ← 实盘下单引擎（py-clob-client 封装）
├── redeem.py                   ← 兑现中奖单
├── preflight_live.py           ← live 前的只读凭证检查
├── polymarket_connectivity_test.py  ← API 连通性测试
│
├── config.example.json         ← 通用配置示例（无密钥）
├── config.live.example.json    ← ★ 实盘配置模板（无密钥）
├── copybot_state.json          ← bot 状态（持续累积）
├── copybot_fills.jsonl         ← bot 成交记录（每行一笔）
├── fly.Dockerfile              ← 云端部署镜像
├── fly.toml / fly.live.toml    ← Fly.io 部署配置
│
├── live/                       ← ★ 离线分析与纸盘回测
│   ├── README.md               ← live/ 子模块说明
│   ├── 仪表盘说明.md            ← dashboard.html 字段说明
│   ├── wallet筛选完整流程.md    ← 钱包筛选细节
│   │
│   ├── enumerate.py            ← 候选池发现（top traders）
│   ├── collect.py              ← 把候选钱包历史拉进 cache.duckdb
│   ├── cache.py                ← DuckDB 缓存层（所有离线分析的"事实来源"）
│   ├── skill.py                ← 5 道门打分 → watch_skilled.json
│   ├── conviction_scan.py      ← 信念钱包扫描
│   ├── validate_timing.py      ← 复制可行性 + 费后 Copy P&L → watch_sharps.json
│   ├── sync_floors.py          ← 把每钱包 p80 信念门槛同步进 copybot 配置
│   ├── payouts.py              ← 链上 payout 校验（防幸存者偏差）
│   ├── trust.py                ← 信任度评估（哪些 cache 行可信）
│   ├── slug_cache.py           ← market → event 关联缓存
│   │
│   ├── portfolio.py            ← ★ $1k 纸盘回测引擎
│   ├── portfolio.json          ← portfolio.py 产物（仪表盘读这个）
│   ├── backtest.json           ← ★ 纸盘配置（天数、钱包列表、class_pct）
│   ├── copybot.paper.json      ← ★ paper 模式 bot 配置（bot 直接读）
│   ├── copybot_live.json       ← paper bot 实时输出的 feed（仪表盘读）
│   ├── copybot_live_real.json  ← live bot 的 feed
│   ├── watch_skilled.json      ← skill.py 产物
│   ├── watch_sharps.json       ← validate_timing.py 产物（仪表盘主表）
│   ├── conviction_wallets.json ← conviction_scan.py 产物
│   │
│   ├── dashboard.py            ← 生成 dashboard.html
│   ├── dashboard.html          ← ★ 自包含 HTML 仪表盘（双击打开）
│   ├── daily.sh                ← ★ 一键每日流水线（见 §7）
│   ├── discord_daily.py        ← Discord 每日摘要推送
│   │
│   └── tests/, archive/        ← 测试与归档研究代码
│
├── host/                       ← 云端/部署辅助（Fly、桥接、钱包 bootstrap）
├── wide/                       ← 历史归档的 subgraph 扫描（frozen）
├── tests/                      ← 单元测试
└── PolymarketDocumentation-main/  ← 官方文档（参考用）
```

---

## 2. 数据流（一张图）

```
   Polymarket data-api ──► enumerate.py ──► candidates.json
                              │
                              ▼
                       collect.py + cache.py ──► cache.duckdb  (本地事实来源)
                              │
                ┌─────────────┼─────────────┐
                ▼             ▼             ▼
           skill.py   conviction_scan.py  payouts.py/trust.py
                │             │
                ▼             ▼
        watch_skilled.json  watch_sharps.json ──┐
                                │               │
                                ▼               │
                          sync_floors.py        │
                                │               │
                                ▼               ▼
                       copybot.paper.json   dashboard.html
                                │               ▲
                                ▼               │
                         copybot.py (paper) ────┘
                                │
                                ▼
                        copybot_live.json ──► dashboard / GitHub Pages

       （cloud run）                            （每日定时）
       copybot.py --live ──► CLOB API ──► 真实成交
```

---

## 3. 常用命令速查

### 3.1 一次性：建库

```bash
pip install duckdb py-clob-client web3    # 实盘需要后两个
cd live
python enumerate.py 180                    # 发现候选（过去 180 天）
python collect.py                          # 拉取所有候选钱包历史（首次慢，可断点续传）
python skill.py                            # 5 道门打分 → watch_skilled.json
python conviction_scan.py                  # 信念钱包扫描
python validate_timing.py                  # 复制可行性 → watch_sharps.json
python sync_floors.py                      # 把每钱包 p80 门槛写进 copybot 配置
python dashboard.py                        # 生成 dashboard.html
python portfolio.py --days 30              # 跑 30 天纸盘回测 → portfolio.json
```

### 3.2 日常：每日流水线

```bash
cd live
./daily.sh                                 # 一键：发现 → 刷新 → 打分 → 仪表盘 → 提交推送 → Discord 摘要
```

按顺序跑：discover → freshen → re-score → sharps → floors → portfolio → dashboard → publish。

### 3.3 跑纸盘 bot（24/7）

```bash
python copybot.py --config copybot.paper.json --poll 60
```

- `--poll 60`：每 60 秒轮询一次（无 Alchemy webhook 时用这个）
- 默认用 WebSocket 订阅 RTDS（实时数据流），延迟最低
- `copybot_state.json` 自动持久化，重启可恢复

### 3.4 切实盘（**真钱**）

```bash
export LIVE_PRIVATE_KEY=0x...
export LIVE_FUNDER_ADDRESS=0x...
export LIVE_SIGNATURE_TYPE=1            # 邮箱登录 = 1
export LIVE_CONFIRM="I understand real money is at risk"

python copybot.py --config config.live.json --live --poll 60
```

详见 `实盘配置.md`。

### 3.5 其它常用命令

| 用途 | 命令 | 说明 |
| --- | --- | --- |
| 测试 API 连通性 | `python polymarket_connectivity_test.py` | 7 个端点一次测完 |
| 实盘前凭证检查 | `python preflight_live.py` | 只读，不会下单 |
| 单钱包 dry-run | `python copybot.py --test-wallet 0xabc...` | 走一遍流程但不持久化 |
| 强制刷特定钱包 | `python -c "import cache; cache.invalidate(['0xabc...'])"` | 跳过 14 天缓存 |
| 手动跑纸盘 | `python portfolio.py --wallets 0xabc,0xdef:whale --days 30 --out /tmp/p.json` | 临时换钱包跑 |
| 只跑一次回测 | `python copybot.py --poll-once --config copybot.paper.json` | 给 cron 用 |
| 把 paper feed 跟 model 比对 | 跑完 `portfolio.py` 后看 `history/calibration.csv` | 校准核心指标 |
| 重算某钱包门槛 | `python sync_floors.py` | 把 p80 写回 copybot 配置 |

---

## 4. 关键配置文件

### 4.1 `live/backtest.json`（纸盘回测用）

```json
{
  "days": 30,                    // 回看窗口长度（滚动）
  "class_pct": {                 // 每类钱包的下注比例（占总资金）
    "volume": 0.04,              // 普通钱包：每笔 4% 当前权益
    "whale": 0.12                // whale：12%
  },
  "wallets": [                   // 要回测的钱包列表
    {
      "wallet": "0x...",
      "name": "Kruto2027",
      "class": "volume",         // 或 "whale"
      "floor": 80.0              // 信念门槛（可选；缺省从历史 p80 算）
    }
  ]
}
```

跑：`python portfolio.py --days 7` 覆盖 days，或 `--wallets 0xabc,0xdef:whale` 临时换列表。

### 4.2 `live/copybot.paper.json`（纸盘 bot 配置）

```json
{
  "mode": "paper",
  "bankroll_usd": 1000.0,        // 起始资金
  "bankroll_pct": 0.04,          // 每笔占当前权益的比例
  "wallets": [...],              // 跟哪些钱包
  "follow": {
    "buy_only": true,            // 只跟买，不跟卖（卖通常意味着平仓）
    "min_their_usd": 25.0,       // 信号钱包下注 ≥ $25 才跟
    "min_entry": 0.0,
    "max_entry": 0.95,           // 不买 > ¢95 的热门（赔率薄）
    "class_pct": { "volume": 0.04, "whale": 0.12 }
  },
  "risk": {
    "min_order_usd": 5.0,        // Polymarket 单笔最小 $5
    "max_per_event": 0           // 同事件并发数（0 = 不限）
  },
  "price_guard_abs": 0.05        // 价格偏离保护（信号价 vs 我看到的）
}
```

### 4.3 `config.live.example.json`（实盘模板）

```json
{
  "mode": "live",
  "bankroll_usd": 22.28,         // ★ 必须等于你实盘钱包的真实余额（启动时和链上比对）
  "bankroll_pct": 0.04,
  "price_guard_abs": 0.05,
  "taker_fee_rate": 0.03,        // Polymarket V2 taker fee (2026-03-30 起)
  "discord_webhook": "",
  "follow": { ... },
  "risk": { ... },
  "live": {
    "private_key": "",           // ← 留空，靠 env 注入
    "funder_address": "",        // ← 留空，靠 env 注入
    "signature_type": 1,         // ← 邮箱登录固定 = 1
    "order_type": "FAK",         // Fill-And-Kill：能成交多少成交多少
    "auto_redeem": false,        // 兑现交给 redeem.py
    "rpc_url": ""
  },
  "wallets": [...],              // 实盘跟的钱包（必须跟 paper 一致）
  "feed_path": "live/copybot_live_real.json",
  "fill_log": "copybot_fills.live.jsonl",
  "shadow_log": "rtds_shadow.live.jsonl"
}
```

> **强烈建议**：不要碰 `live.private_key`/`live.funder_address`，用环境变量注入（`LIVE_PRIVATE_KEY` 等），见 §3.4 与 `copybot.py:2303-2308`。

### 4.4 `live/watch_skilled.json`、`live/watch_sharps.json`

- 这两个是 **`skill.py` / `validate_timing.py` 的输出**，**不要手改**
- `daily.sh` 会每天重算并 commit/push
- 仪表盘（`dashboard.html`）直接读这两个文件

### 4.5 `config.example.json`（通用配置）

只放了 Discord webhook + Alchemy key + 一个 `watch` 列表，是 `config.live.example.json` 的简化版——**实盘请用后者**，别用这个。

---

## 5. 核心变量怎么改

### 5.1 改跟单金额

| 变量 | 在哪个文件 | 含义 | 推荐范围 |
| --- | --- | --- | --- |
| `bankroll_usd` | `copybot.paper.json` 或 `config.live.json` | 起始资金（实盘要等于链上余额） | 看你预算 |
| `bankroll_pct` | 同上 | 每笔占**当前权益**的比例（凯利式复利） | 2–8% |
| `class_pct.volume` / `.whale` | `backtest.json` + `copybot.paper.json` 的 `follow.class_pct` | 按钱包类型区分下注比例 | volume 2–6%, whale 8–15% |
| `min_order_usd` | `copybot.paper.json` 的 `risk.min_order_usd` | Polymarket 单笔最小 | ≥ $5 |
| `max_per_event` | `copybot.paper.json` 的 `risk.max_per_event` | 同事件最多几笔并发 | 1–3（避免一输全输） |
| `max_entry` | `copybot.paper.json` 的 `follow.max_entry` | 不买价格高于 ¢? 的票 | 0.85–0.95 |

**改纸盘 → 实盘要做的一致性检查**（`daily.sh` 里已经写好自动警告）：

```bash
python -c "import json; print(json.load(open('copybot.paper.json'))['follow']['class_pct'])"
python -c "import json; print(json.load(open('backtest.json'))['class_pct'])"
# 两个必须完全一致，否则纸盘和实盘会用不同金额
```

### 5.2 改跟哪些钱包

方法 A（**推荐**：用 paper 配置）
1. 编辑 `live/copybot.paper.json` 的 `wallets` 数组
2. 同时编辑 `live/backtest.json` 的 `wallets`（纸盘回测跟同一个集）
3. 重启 bot

方法 B（**调试用**：CLI 临时覆盖）
```bash
python portfolio.py --wallets 0xabc,0xdef:whale,0x123:volume --days 7
python copybot.py --test-wallet 0xabc...    # 只跑这一个
```

每钱包字段：
- `wallet`：Polygon 地址（小写）
- `name`：仪表盘上显示的标签
- `class`：`volume`（只跟信念单）或 `whale`（跟所有单）
- `floor`：**信念门槛**（美元）。钱包下一笔 ≥ 这个金额才跟进；缺省时 `sync_floors.py` 自动从历史 p80 算
- `floor_pin`：`floor` 是否钉死（`sync_floors.py` 不覆盖钉死的值）

**建议流程**：先用 `dashboard.html` 挑出几个高 z / 高 OOS z 的 → 加进 `copybot.paper.json` → 跑一周 paper → 看 `portfolio.json` 的 equity 曲线 → 表现好的保留进 `config.live.json`。

### 5.3 改回测窗口

```bash
python portfolio.py --days 7        # 7 天滚动窗口
python portfolio.py --days 30       # 默认
python portfolio.py --days 0        # 全历史（极慢，慎用）
```

`backtest.json` 里的 `"days"` 是默认值；CLI 参数优先。

### 5.4 改信念门槛

```bash
python sync_floors.py                # 自动算每钱包 p80，写回 copybot.paper.json
python copybot.py --conviction-from-sharps live/watch_sharps.json  # 用 sharps 表的 avg_bet
```

或者手改某钱包的 `floor` 字段（建议同时设 `floor_pin: true` 防止被自动覆盖）。

---

## 6. 完整流程（从零跑通）

### 6.1 第一次跑（建库）

```bash
# 0. 环境
pip install duckdb                 # 本地分析最低依赖
# 实盘才需要：pip install py-clob-client==0.34.6 web3==7.16.0

# 1. 找候选钱包（一次，约 2–5 分钟）
cd live
python enumerate.py 180            # 取过去 180 天最活跃的市场 → top traders → candidates.json

# 2. 拉所有候选钱包的历史（首次 30+ 分钟，断点续传）
python collect.py

# 3. 打分（秒级，全在本地 cache）
python skill.py                    # → watch_skilled.json（71 个左右）
python conviction_scan.py          # → conviction_wallets.json
python validate_timing.py          # → watch_sharps.json（12 个左右）

# 4. 同步门槛 + 生成仪表盘
python sync_floors.py              # → copybot.paper.json 的 floor 字段
python dashboard.py                # → dashboard.html
python portfolio.py --days 30      # → portfolio.json

# 5. 看结果
start dashboard.html               # Windows；Mac 用 `open dashboard.html`
cat portfolio.json | python -m json.tool | head -50
```

### 6.2 每日维护

```bash
cd live
./daily.sh                         # 一键全自动：发现 → 刷新 → 打分 → 仪表盘 → commit → push → Discord
```

`daily.sh` 内部做的事（按顺序）：

1. `enumerate.py 14`：最近 14 天新市场的 top traders，合并进 `candidates.json`
2. `cache.invalidate(...)` + `collect.py`：watchlist 钱包强制重拉，新钱包补齐
3. `skill.py`：5 道门打分（秒级）
4. `conviction_scan.py` + `validate_timing.py`：信念 + 复制可行性
5. `sync_floors.py`：把每钱包 p80 写回 bot 配置
6. `portfolio.py`：纸盘回测
7. 校准行：把 paper bot 当前 equity 跟 model 比对，写入 `history/calibration.csv`
8. `dashboard.py` + 快照到 `history/`
9. `git commit && git push`：把 JSON 推到 GitHub
10. `discord_daily.py`：推送每日摘要到 Discord

部署建议：cron 或 launchd 每天 10:00 跑一次。

### 6.3 跑纸盘 bot

```bash
cd live
python copybot.py --config copybot.paper.json --poll 60
```

观察：
- `copybot_live.json`：bot 实时写的 feed（仪表盘读这个）
- `copybot_state.json`：bot 内部状态（持仓、现金、追踪进度）
- `copybot_fills.jsonl`：每笔成交（追加写）

随时看：双击 `dashboard.html`，里面"Live"那一栏就是 bot 当前的书。

### 6.4 切到实盘

按 `实盘配置.md` 走完整流程：

1. 拿到私钥（邮箱登录走 https://reveal.magic.link/polymarket）
2. 拿到 funder address（polymarket.com/settings）
3. 设环境变量（`LIVE_PRIVATE_KEY` 等）
4. `cp config.live.example.json config.live.json`，改 `bankroll_usd` 为真实余额
5. **先 dry-run**：不传 `--live`，只设 `LIVE_PRIVATE_KEY` 让 bot 跑 dry-run 验证下单链路
6. **正式开火**：`python copybot.py --config config.live.json --live --poll 60`
7. 建议先小金额跑几天（`bankroll_usd: 20`），验证无误再加大

---

## 7. 核心算法一图流

### 7.1 找钱包（5 道门）

```
所有钱包 → 1) n ≥ 15 已结算
         → 2) z = (赢 − Σp) / √Σp(1−p) > 阈值
         → 3) BH-FDR @ 5% （控制假阳性）
         → 4) 时间切两半：z_oos > 0 （OOS 验证）
         → 5) 总笔数 ≤ 2500 （剔除做市机器人）
         = watch_skilled.json（71 个）
```

详见 `live/skill.py`。

### 7.2 找可复制的（信念 + Copy P&L）

```
watch_skilled → 取每钱包自己下注的前 20%（p80 信念门槛）
             → 实时模拟：跟这些单，扣 0.5% 滑点 + 3% taker fee
             → 只留：copy_pnl > 0 且 active in 30d
             = watch_sharps.json（12 个）
```

**Copy P&L 是唯一可信的筛选指标**——胜率（win%）对"只卖赚钱"的 scalper 会骗你。详见 `live/validate_timing.py`。

### 7.2.1 什么是"信念"（Conviction）

**信念 = 信号钱包"认真下注"的大单**。不是每笔交易都跟，只跟信号钱包自己下注最大的那 20%。

#### 怎么计算

每个钱包的历史交易按**下注金额**排序，取 **p80**（第 80 百分位）作为门槛：

```
假设 Vahan88 过去 90 天有 100 笔交易，按金额排序：

$5, $8, $10, $12, ... $200, $245, $300, $500
                                    ↑
                              p80 = $245（第 80 笔）

下注 < $245 的交易 = 小单（80%）-> 不跟
下注 ≥ $245 的交易 = 信念单（20%）-> 跟
```

这就是为什么 Vahan88 的 floor 是 $245 -- 只有它下注 ≥ $245 时 bot 才跟。

#### 为什么这么设计

项目作者发现：**大单的胜率远高于小单**。

```
Vahan88 全部交易胜率：可能只有 50-60%
Vahan88 信念单（top 20%）胜率：86.2%
```

钱包下小单时可能是试水、对冲、刷量；下大单时才是"我有信心这个方向"--这就是"信念"。

#### floor（门槛）怎么来的

`sync_floors.py`（daily.sh 每天跑）做的事：

1. 从 cache.duckdb 读每个钱包过去 90 天的交易
2. 按下注金额排序，算 p80（第 80 百分位）
3. 写入 `copybot.paper.json` / `config.live.json` 的 `floor` 字段
4. 每天自动更新（因为钱包的交易模式会变）

示例（当前 8 个钱包的 floor）：

| 钱包 | floor | 含义 |
|------|-------|------|
| Kruto2027 | $80 | 经常下 $80+ 的单 |
| 0xbadaf319 | $42 | 小额玩家，$42 就算信念 |
| 1kto1m | $332 | 大额玩家，$332+ 才算信念 |
| Vahan88 | $245 | 中等 |
| LSB1 | $315 | 大额 |

> 门槛低的钱包（如 0xbadaf319 的 $42）不是"质量差"，而是这个钱包平时下注金额就小，$42 对它来说已经是大单了。门槛高的钱包（如 1kto1m 的 $332）平时下注大，$332 才算它的"信念"。

#### 信念胜率（conv_win）

dashboard 里的"信念胜率"是这个钱包**信念单的历史胜率**：

```
Vahan88 信念胜率 86% = 过去信念单里 86% 赢了
BikesAreTheBikes 信念胜率 21% = 只有 21% 赢了（所以不建议跟）
```

选钱包时**信念胜率比 copy_pnl 更重要**--pnl 高可能是一两笔大单运气好，信念胜率高才是稳定赚钱的能力。

#### 新加钱包的 floor

手动加新钱包时 floor 先设 `$25`（最低门槛），第二天 daily.sh 的 `sync_floors.py` 会自动算出真实 p80 门槛覆盖掉。


### 7.3 纸盘回测

```
信号（watch_sharps 或 backtest.json 里的 wallets）
  ↓
每个 in-window 的信念单：
  - stake = bankroll_pct × 当前权益（或 floor 取大）
  - entry_p = signal_p × 1.005（+0.5% 滑点）
  - fee = stake × 0.03 × (1−p)
  - settle: 跟到 resolution 或跟信号平仓
  - capital 在 res_t 时释放（不是 endDate，cache 存了真实结算时间）
  - DD < 20% 时 stake 减半
  - EVENT_CAP > 0 时同事件限笔数
  ↓
portfolio.json（dashboard 直接读）
```

详见 `live/portfolio.py`。

---

## 8. 仪表盘怎么读

打开 `live/dashboard.html`，**顶部 5 个卡片**给出池子总览（z 中位数、OOS z 中位数、各类型数量），**表格**列出每个通过 5 道门的钱包。

挑钱包的硬指标（按重要性）：

1. **OOS z > 0**（必须）：前半后半都赢
2. **z ≥ 5**（强烈推荐）：显著超过市场
3. **alpha 0.2–0.4 高**：在长镜头冷门区有 edge（不是骑热门）
4. **type = Value**（推荐）：真正可复制的 alpha 区
5. **总笔数 ≥ 30**：样本足够

避坑：
- **高 z 但 OOS z 负** = 运气
- **高胜率但 avg entry > 0.85** = Favorite-rider，赔率薄、深度差，复利赚不到
- **总笔数 < 15** = 样本不足

详细字段含义见 `live/仪表盘说明.md`。

---

## 9. 故障排查

| 症状 | 原因 / 解决 |
| --- | --- |
| 跑 `portfolio.py` 报 `OverflowError: mktime argument out of range` | Polymarket 某些市场的 `endDate` 是 0001-01-01 这种 sentinel，超出 mktime 范围。已修过：`live/portfolio.py:336` 同时捕 `ValueError` 和 `OverflowError`。 |
| `urllib` 直连超时 | 国内被墙。本机设 `$env:HTTPS_PROXY = "http://127.0.0.1:7890"`；云服务器直连没问题（已测）。 |
| `daily.sh` 跑完但 portfolio.json 不更新 | 多半是 `collect.py` 还在拉（首次很慢）。等下一次或手动跑。 |
| dashboard.html 不显示某些钱包 | `skill.py` 的 5 道门把它们刷掉了。改 `skill.py` 顶部的阈值（min_resolved、z 阈值等）。 |
| `sync_floors.py` 把我的 `floor` 改了 | 是因为没设 `floor_pin: true`。钉死的字段不会被覆盖。 |
| `preflight_live.py` 报 INVALID_SIGNATURE | 私钥错了。邮箱登录走 https://reveal.magic.link/polymarket 重导。 |
| `preflight_live.py` 报 Invalid Funder Address | funder_address 错了。打开 polymarket.com/settings 看你的 Polygon profile address。 |
| paper bot 跑了但 `copybot_live.json` 没更新 | 检查磁盘权限；或 bot 启动时报错（看 stderr）。 |

---

## 10. 进阶

### 10.1 跑更宽的回测

`wide/` 里有冻结的 subgraph 扫描器，能挖 2024 之前的历史。如果你换了一批钱包想看更久：

```bash
cd wide
python ingest.py --subgraph ...
python score.py --min-bets 30
```

（参考 `wide/README.md`，这是历史归档，新研究都在 `live/`）

### 10.2 改入场价上限

`live/portfolio.py` 顶部：
```python
MAX_ENTRY = float(os.environ.get("MAX_ENTRY", 0.95))
```
或 CLI：
```bash
MAX_ENTRY=0.85 python portfolio.py --days 30
```

`copybot.paper.json` 的 `follow.max_entry` 同理。两者保持一致。

### 10.3 加新钱包

```bash
# 1. 把钱包加进 candidates
python -c "import json,os; c=set(json.load(open('candidates.json'))); c.add('0xNEW...'); json.dump(sorted(c), open('candidates.json','w'))"

# 2. 拉它的历史
python -c "import cache; cache.invalidate(['0xNEW...'])"
python collect.py
# 或单拉：
python -c "import cache; cache.get_bets('0xNEW...')"

# 3. 重新打分
python skill.py
python validate_timing.py

# 4. 看仪表盘，决定要不要加进 follow set
python dashboard.py
```

---

## 11. 一句话总结

- **找**：用 `live/skill.py` 找 71 个有 edge 的，`live/validate_timing.py` 留 12 个可复制的
- **测**：用 `live/portfolio.py` 跑纸盘回测，结果看 `live/portfolio.json` 和 `live/dashboard.html`
- **跑**：用 `python copybot.py --config live/copybot.paper.json --poll 60` 跑 paper
- **上**：`cp config.live.example.json config.live.json` + 设 env + 加 `--live`

每天 `./daily.sh` 一次维护。