Files
winning-wallet-finder/live/钱包筛选完整流程.md
T
gavindiaz b916633528 fix: portfolio.py OverflowError on out-of-range endDate; add Chinese docs; utf-8 dashboard write
- live/portfolio.py:336 — catch OverflowError alongside ValueError in _end_ts
  (mktime on out-of-range dates raises OverflowError on Windows; previously
  crashed the whole window_bets() on certain operator-resolved markets)
- live/dashboard.py — open(out,'w',encoding='utf-8') so dashboard.html
  renders Chinese titles correctly on Windows
- .gitignore — ignore session-local artifacts (PolymarketDocumentation-main/,
  wwf_state.json, live/portfolio.json, etc.)
- Add Chinese-language docs: USAGE.md (项目使用手册), live/仪表盘说明.md,
  live/钱包筛选完整流程.md, 实盘配置.md
2026-07-17 17:37:06 +08:00

24 KiB
Raw Blame History

钱包筛选 / 回测 / 实时跟踪 — 完整流程说明

本文档基于 live/ 下各 Python 脚本(enumerate.py、collect.py、cache.py、skill.py、conviction_scan.py、validate_timing.py、portfolio.py、sync_floors.py、daily.sh)和 copybot.py 的真实代码逻辑,描述"从 Polymarket 全体交易者 → 71 个 z-score 合格钱包 → copybot 跟踪的钱包集合"是如何一步步产生的。


一、"71 个钱包"是什么?从哪来的?

1.1 它们是 watch_skilled.json 的内容

dashboard.py 第 28 行:

w = json.load(open(os.path.join(HERE, "watch_skilled.json")))

watch_skilled.jsonskill.py 的输出(skill.py 第 147 行),记录了通过 5 门统计漏斗 的候选钱包列表。当前你看到的 71 个,就是这个文件的条数。

1.2 71 个 ≠ copybot 跟踪的钱包

copybotpaper 模式)读的是 live/copybot.paper.json(也就是你 bot 实际用的 follow 配置),它只跟踪 5 个 钱包。这 5 个是从 watch_skilled.jsonvalidate_timing.pywatch_sharps.jsonsync_floors.py 这 4 层里最终挑出的"fee-aware 复制复现后仍盈利"的子集。

所以关系是:

candidates.json (~1-3 万候选)
        ↓ skill.py 的 5 门
watch_skilled.json (~71 个 z 合格)
        ↓ conviction_scan.py(信念画像)
conviction_wallets.json (~20-40 个)
        ↓ validate_timing.pyfee-aware 复制复现)
watch_sharps.json (~10-20 个可复制)
        ↓ sync_floors.py(写 p80 门槛到 bot 配置)
copybot.paper.json / backtest.json (copybot 跟踪的 5-10 个)

1.3 它们是什么时候筛选出来的?

watch_skilled.json 里的 71 个钱包 不是固定时间 的快照。看 daily.sh

# step 2 — 强制刷新 watchlist
python3 -c "import json,os,cache
wl=[]
for f in ('watch_skilled.json','watch_sharps.json'):
    if os.path.exists(f):
        wl += [w['wallet'] for w in json.load(open(f))]
if wl:
    cache.invalidate(wl)"  # ← 强制让当前 watchlist 的钱包下一次 get_bets 时重新拉数据
python3 collect.py

# step 3 — 重新评分(从缓存瞬间完成)
python3 skill.py

所以 watch_skilled.json 每跑一次 daily.sh 就会被覆盖一次。里面的每条数据都是 基于该钱包过去 180 天窗口内已结算的所有 bets 实时计算的 z-score。

这意味着你现在看到的 71 个钱包,就是最近一次运行 skill.py 时,用当时的 bets 缓存数据算出来的结果。


二、完整的"7 层"筛选流程

下面每一步都有明确的代码位置。


第 1 层:枚举候选池(enumerate.py → candidates.json

问题Polymarket 上有数万个活跃钱包,我们不可能全拉。

做法enumerate.py 第 113-156 行 main 函数):

  1. 找到最近 N 天内已结算且流动性高的市场

    • WINDOW_DAYS = 180(默认),可通过命令行参数覆盖(daily.sh 传 14
    • https://gamma-api.polymarket.com/markets 拉取
    • MIN_VOLUME = 20000$20,000 以上才算)
    • 每 100 个一页,并发 4 波,最多扫描 MAX_SCAN=25000 个市场,保留 MAX_MARKETS=1200 个
  2. 对每个市场取 Top 30 名义金额交易者

    • 调用 insider.market_traders(conditionId, top=30)enumerate.py 第 123 行)
    • 去重,统计每个钱包"出现在多少个不同市场"(markets_seen 计数)
  3. 累积到 candidates.json

    • 每次运行不是覆盖,而是与旧的 candidates.json 合并(第 138-151 行)
    • 新钱包追加;已存在的钱包取更大的 markets_seen
    • 最终按 markets_seen 降序写入 candidates.json

输出candidates.json(当前约 1-3 万个钱包,取决于累积运行次数)

为什么按 markets_seen 排序:在 many 个不同市场都下注的钱包更可能是认真研究的,不是只碰了一个市场就走运的。


第 2 层:收集钱包的历史 betscollect.py → cache.duckdb

问题:enumerate 只给出了候选钱包名单,没有他们的下注历史。每算一次 z-score 都要从 Polymarket 拉一次 API,非常慢(单钱包 5-30 秒)。

做法collect.py 第 31-55 行 + cache.py 全文件):

  1. candidates.json,按 markets_seen 倒序
  2. 区分 "全新钱包"(从未拉过)和 "过期钱包"(最后一次拉取已经超过 14 天)
    • MAX_AGE_DAYS = 14 在 cache.py 第 44 行
  3. 每轮只拉新的 + 最近过期的 STALE_CAP = 2500 个(第 28 行)
    • 这个 cap 很重要:没有它,当整个候选池第一次同时跨过 14 天阈值时,一次 daily 会变成 40 小时的重拉
  4. cache.get_bets(wallet) 拉取并写入 DuckDB(第 179 行 INSERT

缓存机制cache.py 核心逻辑,第 135-183 行):

  • DuckDB 表 schemabets(wallet, cond, asset, won, p, res_t, size, src, ts, resolved)
  • 对每个钱包,如果 pulled_at 距今 < 14 天(MAX_AGE_DAYS),直接读缓存返回,不碰 API
  • 否则调用 insider.resolved_bets(wallet, ...) 拉取 180 天窗口的已结算 bets
  • 写入时是 upsert 而非 overwrite:旧的历史数据会累积(永久归档)
  • get_bets 读回时会对 p 值 clamp 到 [0.001, 0.999](第 18 行注释 + 130 行)
  • 如果 API 拉取失败,不会把空结果写进 pulled 表,下次会重试(第 149 行 return []

输出cache.duckdbSQLite-like,当前约 1-3 万钱包 × 数十到数百条 bets)


第 3 层:可信数据过滤(trust.py,被 conviction_scan/validate_timing/portfolio 间接调用)

问题cache 里的某些 res_t 字段不是链上结算时间,而是钱包自己的"卖出时间"(当市场还未结算时,钱包已经卖了)。做市商钱包的 won 被标记为卖出方向价格 -> 结果看起来胜率极高("99% 赢"),这是虚高。

做法trust.py,被 conviction_scan.py 第 69 行的 f"WITH {trust.cte(now)}" 和 validate_timing.py 调用):

  • trust.cte(now) 返回一个 SQL CTE,只保留:
    • 有共识 res_t(跨钱包一致、非 fallback 的结算时间戳)
    • resolved IS NOT False
    • pulled_at 足够新
  • 所有需要"真实结算结果"的统计(信念画像、复制复现、回测)都用这个 CTE 过滤后的行

这一步非常重要——如果跳过 trust,整个 pipeline 会把高频做市商识别为"顶级 alpha 钱包"


第 4 层:5 门 z-score 统计漏斗(skill.py → watch_skilled.json

核心公式skill.py 第 50-57 行 zstats):

z = (实际获胜数 − Σ入场价) / √Σ(入场价 × (1 − 入场价))

Σ入场价 = 如果该钱包所有 bet 都以"市场估计的胜率"随机开奖,预期赢几场。z > 0 意味着它实际赢的比市场预期多。

5 门门槛skill.py 第 60-161 行 score_wallet + main 的选择逻辑):

编号 源码位置 含义
1 MIN_N = 15 已结算 bets 第 37 行 + 第 70 行 样本量门槛
2 MAX_N = 2500 排除超高频 第 39 行 + 第 70 行 排除做市机器人(单钱包几千条 bets 是做市不是 alpha)
3 z > 0 隐式(z 排序后配合 FDR 阈值) 实际胜率 > 市场预期
4 Benjamini-Hochberg FDR @ 5% 第 94-103 行 bh_threshold + 128 行 thresh 控制"同时检验几千个钱包"的多重比较错误率
5 前半/后半样本外持续性(z_is/z_oos 第 73-78 行 + 第 131-137 行 z_oos > 0 才算 tier=validated(真正决定性的门)

额外统计并写入:

  • avg_entry(平均入场价,用于区分 favorite-rider vs value
  • band_02040.2-0.4 带 bets 占比,alpha 高地带)

并行化ThreadPoolExecutorWORKERS=10(第 42 行 + 114-123 行)

输出

  • watch_skilled.json(当前 ~71 个钱包 —— 你 dashboard 看到的就是它)
  • watch_skilled_scored.json(完整中间结果,含未通过门槛的钱包)

关键细节skilled set 的 tier 分级:

  • tier=validated:同时有前后两半数据 AND z_oos > 0(真正可信)
  • tier=candidate:只有半边数据或 z_oos ≤ 0(数据不够,暂存观察)

为什么不是胜率:胜率会被"只买 0.90 热门"的钱包欺骗(看起来胜率高,但是赔率薄且无复制价值)。z-score 对标入场价本身的信息含量,稳健得多。


第 5 层:信念画像扫描(conviction_scan.py → conviction_wallets.json

问题z-score 统计的是钱包所有 bets 的表现,但复制 bot 只能复制"他认真下注"的那些 bet。他用 $5 小钱玩的 bet 你去 $50 抄,盈亏没意义。

定义"信念 bet" = 该钱包下注金额 Top 20%p80)的那些 bets。

  • CONV_PCTILE = 0.80conviction_scan.py 第 41 行)
  • p80 阈值仅在 TRAIN 窗口(res_t < 2026-06-01)上计算,避免测试数据泄漏(第 8-9 行注释 + 第 71 行 SQL

扫描逻辑conviction_scan.py 第 62-144 行 main):

  1. 从 cache.duckdb 读所有钱包的 TRUSTED rows(经过 trust.py 过滤)
  2. 对每个钱包,计算 TRAIN 窗口的信念门槛 p80
  3. 只保留 TRAIN 窗口信念 bets ≥ 12 条的钱包
  4. 进一步过滤:
    • 胜率 ≥ 65%WIN_MIN = 0.65,第 43 行)
    • 平均入场价在 [0.30, 0.75](排除 0.90+ favorite-rider,第 44 行)
    • 信念 copy-ROI > 0(第 96 行)
    • whole-book z_all > 2.0(第 47 行 Z_ALL_MIN)—— 这是 2026-07-03 加入的最强门:该钱包整个交易簿都有正 z,不只是信念 bet
    • 中位信念 stake ≥ $50(第 48 行 MIN_MED_STAKE = 50)—— 排除只玩 $2-$6 clips 的 dust 钱包
  5. BH-FDR 控制(第 103-110 行)
  6. 计算 6 月 1 日后的前瞻表现(forward validation

输出conviction_wallets.json(约 20-40 个,每个带 train/forward 两套统计)

重要注释conviction_scan.py 第 26-32 行):50/50 REFUNDS 市场把两方都标记为 won,这会让统计数字虚高。本层有意"过度生成候选",真正去毒在 validate_timing.py 里通过链上 payout 核对。


第 6 层:fee-aware 复制复现(validate_timing.py → watch_sharps.json

这是从 71 个到 10 个可复制钱包的最关键门

问题conviction_wallets.json 里有些钱包其实是"卖得好(scalper)" — 他们高入场后低出赚利差,但他们 buy 的时候价格还没动。你(copier)跟在后面买,滑点吃掉全部利润。

做法validate_timing.py):

  1. 对 conviction_wallets.json 里的每个候选钱包
  2. 用与真实 copybot 完全一致的逻辑做"模拟复制":
    • STAKE = 50.0(每笔 $50 固定)
    • FEE_RATE = 0.03sports 类费率,fee = shares · rate · price · (1-price),双边收)
    • 持有到结算(_clob_winner 通过 CLOB winner 字段判断胜负)
  3. 得到:
    • copy_pnl:复现的净收益(扣除两边 fee 后的实际收入)
    • held_pnl:持有到结算的收益(延迟鲁棒的那条腿)
    • 中位 lead timeentry → resolution 的小时数)
  4. 通过门:
    • copy_pnl > 0(复制它真实赚钱
    • held_pnl > 0(hold 到结算的收益也是正的 —— 说明不是只靠卖的时机精准)
    • median_lead >= COPYABLE_MED_LEAD = 24h(第 45 行,排除 sub-hour snipers
    • 最近 30 天有活动

输出watch_sharps.json~10-20 个真正可复制的 sharp 钱包)

这一步与 copybot 的资金管理、fee 模型完全一致,所以 watch_sharps.json 里钱包的数字就是"如果你真的在这段时间复制他们,你会赚多少钱"的最诚实估计。


第 7 层:同步信念门槛到 bot 配置(sync_floors.py → copybot.paper.json

问题copybot 的 follow 配置里每个钱包都有"信念门槛"(低于这个金额的 bet 不抄)。这个阈值从哪来?

做法sync_floors.py 从 cache 里每个钱包的 TRAIN 数据计算 p80 信念 stake,写回 copybot.paper.jsonfloor 字段。

同时 backtest.json 也用同样的阈值,确保回测和 live bot 判断同一笔 bet 时的结论一致(daily.sh 第 55-62 行还做了 class_pct 的一致性校验,如果两个文件这个参数不同会报错)。

输出:更新后的 copybot.paper.json(每个钱包加了 floor 数字,如 Kruto2027 的门槛约 $2000xbadaf319 约 $44


第 8 层:滚动回测(portfolio.py → portfolio.json

最后一步$1000 起步资金,把 watch_sharps.json(或 backtest.json 指定的钱包集合)过去 30 天的信念 bets 按时间轴复现一遍。

  • 每笔 stake = 当时权益 × class_pct(通常 4%
  • 上限 ≤ 信号钱包自己下注的金额
  • 扣除 CLOB 双边 fee(费率按 sports 0.03 计算)
  • 链上赎回免费
  • 结算用 CLOB winner 字段 + 链上 payout 双保险

输出portfolio.json,含:

  • equity:最终权益(核心指标,如果你问"回测赚多少"就是这个)
  • realized:已结算盈亏
  • deployed:当前持仓成本
  • cash:剩余现金

第 9 层:daily.sh 一键跑

daily.sh 第 37-100 行按顺序执行:

python3 enumerate.py 14                      # 发现最近 14 天的新候选
cache.invalidate(watch_skilled + watch_sharps)  # 强制刷新 watchlist 的数据
python3 collect.py                           # 从 Polymarket 拉新钱包 + 刷新过期钱包
python3 skill.py                             # 重新 5 门评分 → watch_skilled.json
python3 conviction_scan.py                   # 信念画像 → conviction_wallets.json
python3 validate_timing.py                   # fee-aware 复现 → watch_sharps.json
python3 sync_floors.py                       # 写 p80 门槛 → copybot.paper.json
python3 portfolio.py                         # $1000 回测 → portfolio.json
python3 dashboard.py                         # → dashboard.html
cp watch_skilled.json history/watch_YYYYMMDD.json  # 可审计快照
git add + commit + push                      # bot 下次重启会拉最新配置

注意 publish 步骤daily.sh 第 102-115 行):bot(不论是 paper 还是 live)在每次重启时 git pull 最新的 copybot.paper.json。所以 daily.sh 的输出实际上是"更新 bot 配置"的唯一入口。


三、你现在看到的 dashboard 71 个 —— 怎么更新?

3.1 如果你想让 dashboard 数字是最新的

只需要单独跑:

cd live
python3 dashboard.py

它只读 watch_skilled.json,生成 dashboard.html不会碰网络dashboard.py 本身不碰 Polymarket API)。

3.2 如果你想让 watch_skilled.json 的 z-score 用最新 bets 重算

cd live
python3 collect.py     # 拉新钱包 + 刷新过期钱包的 bets 到 cache.duckdb
python3 skill.py       # 从 cache 重新 5 门评分 → 覆盖 watch_skilled.json
python3 dashboard.py   # 刷新仪表盘

collect.py 每轮只拉新钱包 + 最近 14 天未拉过的钱包中的 STALE_CAP=2500 个,不会全量重拉(全量可能几小时到十几小时)。

如果你只想刷新"当前 watchlist 里的那几个钱包",可以先手动 invalidate

# 先强制 watchlist 的钱包过期
python3 -c "import cache; cache.invalidate(['0x...','0x...','0x...'])"
# 然后收集
python3 collect.py
# 重算
python3 skill.py
python3 dashboard.py

3.3 全流程跑一次(等同于 daily.sh 的简化版)

cd live
python3 enumerate.py 14
python3 collect.py
python3 skill.py
python3 conviction_scan.py
python3 validate_timing.py
python3 portfolio.py
python3 dashboard.py

首次跑会比较慢(主要是 collect.py 拉新钱包),之后每次很快。


四、copybot.py 与筛选 pipeline 的关系

4.1 copybot 的 follow 列表从哪来?

copybot 启动时读取 live/copybot.paper.jsonpaper 模式)或 live/copybot.paper.jsonlive 模式)。这个文件里的 follow 数组,正是 sync_floors.py 从 watch_sharps.json 里挑出的最终子集,加上每个钱包的 floorp80 信念金额)。

4.2 bot 实时触发的过滤规则

对每个 RTDS 或 5 分钟轮询捕获到的新 bet,copybot 检查:

  1. 钱包在 follow 集合里?(只跟踪 watch_sharps.json 最后挑出的那几个)
  2. 方向是 BUY?(只抄入场;SELL 作为 exit 触发器,但"跟卖"不支持)
  3. 下注金额 ≥ 该钱包的 floor(信念门槛,由 sync_floors.py 写入)
  4. 入场价在 [0.00, 0.95] 区间(排除 near-certain 热门)
  5. 价格漂移门:如果 bot 下单价比信号钱包成交价高 > 0.05 绝对点位,跳过(滑点保护)
  6. 深度门:价差 > 0.08 或 5c ask 深度 < $50 的市场跳过(薄盘不可靠)
  7. 资金管理:stake = 当前权益 × 4%,上限 ≤ 信号钱包自己下注的金额,下限 $1

4.3 paper bot 的账本状态保存在哪?

paper 模式下,bot 的 state(持有的 positions、现金、已结算盈亏)保存在命令行 --state 指定的 JSON 文件里(你用的 wwf_state.json)。

live 模式类似,文件是 copybot_live.json,由 bot 自己 commit/push 回 GitHub 以便每日校准(daily.sh 第 71-96 行做 live_equity vs model_equity 比较,结果写入 history/calibration.csv)。


五、关键数字速查(代码里的硬常量)

常量 位置 含义
WINDOW_DAYS 180 enumerate.py:31 / cache.py:43 拉取 bet 的时间窗口(最近 180 天)
MIN_VOLUME 20000 enumerate.py:35 只看 $20k+ 流动性的市场
TOP_TRADERS 30 enumerate.py:34 每个市场取 Top 30 名义金额交易者
MAX_MARKETS 1200 enumerate.py:32 最多枚举市场数
MIN_N 15 skill.py:37 z-score 至少 15 条已结算 bet
MAX_N 2500 skill.py:39 超过这个数可能是做市机器人
FDR_Q 0.05 skill.py:40 BH 多重检验控制率
CONV_PCTILE 0.80 conviction_scan.py:41 / cache.py:51 信念 bet 的 p80 阈值
JUN1 2026-06-01 conviction_scan.py:40 TRAIN/TEST 切分点
WIN_MIN 0.65 conviction_scan.py:43 信念 bet 胜率门槛
ENTRY_LO/HI 0.30/0.75 conviction_scan.py:44 信念 bet 的入场价区间
Z_ALL_MIN 2.0 conviction_scan.py:47 whole-book z-score 门
MIN_MED_STAKE $50 conviction_scan.py:48 信念 bet 中位金额门(dust 过滤)
FEE_RATE 0.03 validate_timing.py:53 CLOB sports 类 taker 费率(fee = shares·rate·price·(1-price)
COPYABLE_MED_LEAD 24h validate_timing.py:45 可复制判定的中位 lead time
STAKE $50 validate_timing.py:47 复现时每笔固定模拟金额
MAX_AGE_DAYS 14 cache.py:44-45 钱包缓存新鲜度阈值(超过则下次重新拉取)
STALE_CAP 2500 collect.py:28 单轮 collect.py 强制刷新的钱包数上限(避免一次跑几小时)

六、流程总结图

Polymarket API (gamma / clob / data-api)
         │
         ▼
enumerate.py ──→ candidates.json ( ~3 万钱包, 按 markets_seen 排序 )
                     │
                     ▼
collect.py / cache.py ──→ cache.duckdb ( 每钱包的 resolved bets, 14 天自动刷新 + 累计归档,
                                      upsert 而非 overwrite, 含 asset/token_id 去重避免 double-count,
                                      trust.cte() 过滤做市商 poison 数据)
                     │
                     ▼
┌──────────── skill.py ────────────┐
│  1. MIN_N=15 已结算 bets          │
│  2. z = (wins - Σp)/√Σp(1-p)      │
│  3. BH-FDR @ 5%                   │
│  4. split-half: z_is/z_oos 前后半 │
│  5. MAX_N=2500 排除做市           │
│  6. avg_entry 分 value/favorite   │
└───────────────────────────────────┘
         │
         ▼
watch_skilled.json ( ~71 个, 你 dashboard 看到的 )
         │
         ▼
┌──────── conviction_scan.py ───────┐
│  只取每个钱包 Top 20% stake (p80) │
│  TRAIN: res_t < 2026-06-01        │
│  TEST:  res_t >= 2026-06-01        │
│  门槛: ≥12 信念 bet + win% ≥65%   │
│        + entry 0.30-0.75 + ROI>0  │
│        + z_all>2 + med stake≥$50  │
└───────────────────────────────────┘
         │
         ▼
conviction_wallets.json ( ~20-40 个 )
         │
         ▼
┌────── validate_timing.py ─────────┐
│  flat-$50/stake fee-aware 复现     │
│  真实 CLOB winner 判定胜负         │
│  门: copy_pnl>0 AND held_pnl>0    │
│      AND med_lead ≥ 24h           │
│      AND 30 天内有活动            │
└───────────────────────────────────┘
         │
         ▼
watch_sharps.json ( ~10-20 个可复制 )
         │
         ▼
┌────── sync_floors.py ─────────────┐
│  每个钱包计算 p80 信念金额         │
│  → copybot.paper.json 的 floor    │
│  → backtest.json 的 floor (一致)   │
└───────────────────────────────────┘
         │
         ▼
copybot.paper.json / backtest.json ( copybot 实际跟踪的 5-10 个钱包 + 各自 floor )
         │
         ▼
┌────── copybot.py ─────────────────┐
│  RTDS WebSocket + 5 分钟轮询兜底   │
│  过滤: 钱包 in follow set + BUY   │
│        + stake ≥ floor            │
│        + entry 价 [0, 0.95]       │
│        + 价格漂移保护 (+0.05 abs) │
│        + 深度门 (spread + 5c ask) │
│        + 4% 权益 stake, 上限信号  │
└───────────────────────────────────┘
         │
         ▼
wwf_state.json ( paper 账本 ) / copybot_live.json ( 实盘账本 )
portfolio.json ( 回测结果, $1000 起步的权益曲线 )
dashboard.html ( 当前 71 个钱包的 z / z_oos / win% / entry 概览 )
history/calibration.csv ( daily.sh: live_equity vs model_equity 的每日校准行 )
history/watch_YYYYMMDD.json ( watch_skilled.json 每日快照 —— 可审计 )

七、你需要多久重新拉一次?

如果你只是跑 paper bot 玩

  • 不用刻意重新拉。bot 启动时会 baseline 校准(copybot.py baseline 逻辑),RTDS 实时推送新 bet。
  • 每 2-4 周跑一次 python3 collect.py && python3 skill.py && python3 dashboard.py 刷新 z-score 即可。

如果你认真做回测

  • 每周跑一次 daily.sh 全流程(enumerate → collect → skill → conviction_scan → validate_timing → sync_floors → portfolio → dashboard
  • 确保 watch_sharps.json 始终用最新 bets 复现

如果你跑 live 实盘(你当前没这么做,但记录一下):

  • 每次 python3 sync_floors.py 更新后 git commit && fly apps restart copybot-live
  • bot 启动时的 geo-gategeocheck.py)验证必须通过(斯德哥尔摩区域可交易)

八、已知的方法论限制(来自代码注释)

  1. 回测上偏:回测是"事后挑出表现好的钱包然后说'如果我过去跟着他们会怎样'",真实复制需要预先选出那些钱包。这是所有筛选型回测的固有问题。
  2. 复制滞后:RTDS 已经比信号钱包晚几百毫秒到几秒,加上 bot 处理、下单、CLOB 排队,实际入场价总会比信号钱包差。滑点吃掉部分 alpha 是不可避免的。
  3. 深度限制:市场上某 outcome 只有 $X 的 5c ask 深度,你不能复制一个下注 $10X 的钱包——他能拿到的价你拿不到。
  4. ban 风险:被识别为"总是跟着别人下大单"可能被 Polymarket 限制。
  5. refund 机器:有些钱包 z-score 高其实是因为他们高频参与 50/50 refund 市场(两边都算赢)。conviction_scan.py 第 26-32 行专门注释说本层会过度生成,由 validate_timing.py 的链上 payout 去毒。
  6. CLOB winner=False 语义陷阱:未结算市场的每个 token winner 都为 False。把 False 当"输"会把所有未结算仓位记为亏损。代码里 _clob_winner() 显式处理:只有 winner is True 才算赢;其他都是 unresolved。(validate_timing.py 第 58-78 行注释)

以上所有步骤每一行代码都可以在 live/ 目录下的同名 .py 文件里找到对应的实现,欢迎直接看源码验证。