2026-07-21 07:35:48 +08:00
|
|
|
|
# 问题排查与踩坑记录
|
|
|
|
|
|
|
|
|
|
|
|
> 本文档记录了从 paper 部署到 live 上线过程中遇到的所有问题和解决办法。任何第一次接触这个项目的 AI 代理或人类工程师都可以通过本文档快速了解已知坑和解决方案。
|
|
|
|
|
|
>
|
|
|
|
|
|
> 最后更新:2026-07-20
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 目录
|
|
|
|
|
|
|
|
|
|
|
|
1. [部署阶段](#1-部署阶段)
|
|
|
|
|
|
2. [代理阶段](#2-代理阶段)
|
|
|
|
|
|
3. [钱包与资金阶段](#3-钱包与资金阶段)
|
|
|
|
|
|
4. [Live Bot 运行阶段](#4-live-bot-运行阶段)
|
|
|
|
|
|
5. [Dashboard 阶段](#5-dashboard-阶段)
|
|
|
|
|
|
6. [代码修复记录](#6-代码修复记录)
|
|
|
|
|
|
7. [操作陷阱](#7-操作陷阱)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 1. 部署阶段
|
|
|
|
|
|
|
|
|
|
|
|
### 1.1 portfolio.py OverflowError: mktime argument out of range
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:`python3 portfolio.py --days 7` 崩溃,报 `OverflowError: mktime argument out of range`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:Polymarket 某些市场的 `endDate` 是 sentinel 值(如 0001-01-01),超出 Windows/Linux 的 `time.mktime` 范围。`_end_ts()` 只捕获了 `ValueError`,没捕获 `OverflowError`。
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:`live/portfolio.py:336`,把 `except ValueError` 改成 `except (ValueError, OverflowError)`
|
|
|
|
|
|
|
|
|
|
|
|
### 1.2 ModuleNotFoundError: No module named 'duckdb'
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:`python3 portfolio.py` 报缺少 duckdb
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:`pip3 install duckdb --break-system-packages`(Debian/Ubuntu 需要 `--break-system-packages`)
|
|
|
|
|
|
|
|
|
|
|
|
### 1.3 wwf 用户 git commit 报 Author identity unknown
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:bot 以 wwf 用户运行时 git commit 失败:`Author identity unknown`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:建了 wwf 系统用户但没配 git 身份
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
sudo -u wwf git config --global user.name "copybot[bot]"
|
|
|
|
|
|
sudo -u wwf git config --global user.email "copybot@wwf.local"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 1.4 root 访问 wwf 的仓库报 dubious ownership
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:`git log` 报 `fatal: detected dubious ownership`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:仓库 chown 给了 wwf,root 访问被 git 安全机制拒绝
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:`git config --global --add safe.directory /opt/winning-wallet-finder`
|
|
|
|
|
|
|
|
|
|
|
|
### 1.5 config.live.json 权限错误
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:live bot 报 `PermissionError: [Errno 13] Permission denied: config.live.json`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:config.live.json 是 root 创建的,wwf 用户读不了
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:`chown wwf:wwf config.live.json && chmod 640 config.live.json`
|
|
|
|
|
|
|
|
|
|
|
|
### 1.6 LIVE_CONFIRM 值不匹配
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:`Aborted - LIVE_CONFIRM is set but does not match the phrase`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:确认短语是 `TRADE LIVE`(`copytrade.py:48` 的 `CONFIRM_PHRASE`),不是 `I understand real money is at risk`
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:`/etc/copybot/live.env` 里设 `LIVE_CONFIRM=TRADE LIVE`(不加引号)
|
|
|
|
|
|
|
|
|
|
|
|
### 1.7 systemd EnvironmentFile 引号问题
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:LIVE_CONFIRM 的值带了引号导致不匹配
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:systemd EnvironmentFile 不需要引号,加了引号会变成值的一部分
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:`LIVE_CONFIRM=TRADE LIVE`(不要写 `LIVE_CONFIRM="TRADE LIVE"`)
|
|
|
|
|
|
|
|
|
|
|
|
### 1.8 私钥含非 ASCII 字符
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:`UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:重写 live.env 时占位符 `你的真实私钥` 没替换成真实私钥
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:确保 live.env 里 `LIVE_PRIVATE_KEY=0x` + 64 位纯 hex
|
|
|
|
|
|
|
|
|
|
|
|
### 1.9 git push 被拒(remote 有 bot 自动 commit)
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:`! [rejected] main -> main (fetch first)`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:服务器上的 bot 会自动 commit state/feed 文件到 Gitea,本地 push 时远程已有新 commit
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:`git pull --rebase --autostash origin main && git push origin main`
|
|
|
|
|
|
|
|
|
|
|
|
### 1.10 git reset --hard 恢复了腐败的 state
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:清了 state 文件后 `git reset --hard`,bot 启动后又出现巨大的 LEDGER DRIFT
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:bot 已经把腐败的 state auto-commit 到 git,`git reset --hard` 又把它拉回来了
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:`git reset --hard` 之后**再清一次 state**:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
git fetch origin && git reset --hard origin/main
|
|
|
|
|
|
rm -f copybot_state.live.json copybot_fills.live.jsonl live/copybot_live_real.json
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2. 代理阶段
|
|
|
|
|
|
|
|
|
|
|
|
### 2.1 服务器在 Polymarket 禁单地区
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:`host/geocheck.py` 返回 `VERDICT: BLOCKED`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:服务器 IP 在美国/英国/法国等禁单地区
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:部署 mihomo 代理,通过日本/香港节点绕开 geo-block。详见 `mihomo代理部署教程.md`
|
|
|
|
|
|
|
|
|
|
|
|
### 2.2 机场返回假节点
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:mihomo 配置里的节点名是"当前Clash客户端不支持本机场协议",连接地址是 127.0.0.1:65535
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:机场检测 wget 的 User-Agent 不是 Clash 客户端
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:加 UA 伪装 + flag 参数:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
wget -O /etc/mihomo/config.yaml \
|
|
|
|
|
|
--user-agent="clash-verge/v1.7.7" \
|
|
|
|
|
|
"订阅链接&flag=meta"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2.3 选了英国节点导致 GEO-BLOCKED
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:live bot 启动报 `GEO-BLOCKED: this box cannot place Polymarket orders`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:健康检查脚本自动切换到了英国节点(英国也在禁单列表),但旧脚本只排除了美国
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:见 2.4
|
|
|
|
|
|
|
|
|
|
|
|
### 2.4 健康检查脚本两个 bug
|
|
|
|
|
|
|
|
|
|
|
|
**bug 1**:只排除了美国,没排除英国/法国/德国等其它禁单地区
|
|
|
|
|
|
**bug 2**:测的是 `GET /markets`(不 geo-block),不是 `POST /order`(才 geo-block)
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:改用**白名单**(只选日本/香港)+ 测 `POST /order`(401=通过,403=被 block)。脚本在 `host/mihomo-healthcheck.sh`
|
|
|
|
|
|
|
|
|
|
|
|
### 2.5 mihomo 重启后节点回到 DIRECT
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:重启 mihomo 后代理不走节点了
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:第一次启动后没手动选过节点,cache.db 里没记录
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:启动后手动选一次节点,mihomo 会记住(cache.db 持久化)
|
|
|
|
|
|
|
|
|
|
|
|
### 2.6 代理影响其它服务
|
|
|
|
|
|
|
|
|
|
|
|
**担心**:配了代理会不会影响 paper bot / dashboard / Gitea
|
|
|
|
|
|
|
|
|
|
|
|
**结论**:不会。mihomo 不是透明代理(没开 TUN),只有设了 `HTTPS_PROXY` 的程序才走代理。`HTTPS_PROXY` 只在 `/etc/copybot/live.env` 里,只 live bot 读
|
|
|
|
|
|
|
|
|
|
|
|
### 2.7 Clash Verge 拦截 dashboard 访问
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:本地浏览器打不开 `http://45.207.206.36:18080/`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:本地 Clash Verge 系统代理把直连 IP 也走了代理
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:关掉 Clash 系统代理,或在 Clash 规则里加 `IP-CIDR,45.207.206.36/32,DIRECT`
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3. 钱包与资金阶段
|
|
|
|
|
|
|
|
|
|
|
|
### 3.1 SecureClient.create 报 Builder API Key 错误
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:`Gasless transactions require a Builder API Key or Relayer API Key`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:邮箱登录(POLY_PROXY)的钱包没有存款钱包(Deposit Wallet),SecureClient 尝试自动创建但需要 Builder API key
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:用 Builder API 凭证创建存款钱包(一次性):
|
|
|
|
|
|
```python
|
|
|
|
|
|
bk = BuilderApiKey(key=..., secret=..., passphrase=...)
|
|
|
|
|
|
client = SecureClient.create(private_key=pk, api_key=bk)
|
|
|
|
|
|
```
|
|
|
|
|
|
或改用 MetaMask 登录(自动创建存款钱包,不需要 Builder key)
|
|
|
|
|
|
|
|
|
|
|
|
### 3.2 充错钱包
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:bot 余额 $0,但 Polymarket 网站显示有钱
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:充到了 Polymarket 网站显示的充值地址(代理钱包),不是 bot 用的存款钱包
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:必须充到 `SecureClient.create()` 返回的存款钱包地址
|
|
|
|
|
|
|
|
|
|
|
|
### 3.3 USDC vs pUSD
|
|
|
|
|
|
|
|
|
|
|
|
**问题**:bot 需要的是 pUSD(Polymarket 抵押代币),不是原始 USDC
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:通过 Polymarket 网站充值会自动转换。或直接充 USDC 到存款钱包,Polymarket 自动转成 pUSD
|
|
|
|
|
|
|
|
|
|
|
|
### 3.4 wrap_via_bridge.py 硬编码了原作者的钱包地址
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:`host/wrap_via_bridge.py` 里 `DW = "0x455e..."` 是原作者的存款钱包,不是你的
|
|
|
|
|
|
|
|
|
|
|
|
**注意**:这个脚本的 `DW` 和 `EXPECTED_BRIDGE_EVM` 是硬编码的,直接跑会在第 145 行报错退出。如果需要用,改成你自己的存款钱包地址
|
|
|
|
|
|
|
|
|
|
|
|
### 3.5 bankroll_usd 必须精确匹配链上 pUSD 余额
|
|
|
|
|
|
|
|
|
|
|
|
**问题**:bankroll 设成整数(如 $5),但链上实际是 $5.45,导致 CASH≠CHAIN 警告
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:每次清 state 前先查链上实际余额,设精确值:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
python3 -c "from polymarket import SecureClient; c=SecureClient.create(private_key='...'); b=c.get_balance_allowance(asset_type='COLLATERAL'); print('%.2f' % (b.balance/1e6)); c.close()"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4. Live Bot 运行阶段
|
|
|
|
|
|
|
|
|
|
|
|
### 4.1 CASH≠CHAIN / LEDGER DRIFT(核心问题)
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:bot 账本与链上实际余额不一致
|
|
|
|
|
|
|
|
|
|
|
|
**根因**:代理网络不稳 -> 订单验证调用(get_order / _shares_held)失败 -> 误判订单未成交 -> 账本漂移
|
|
|
|
|
|
|
|
|
|
|
|
**手动修复**(仍然有效):
|
|
|
|
|
|
```bash
|
|
|
|
|
|
systemctl stop copybot-live
|
|
|
|
|
|
# 查链上余额 -> 设 bankroll -> 清 state -> 重启
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**自动修复**(已实现):`copybot.py` 的 `summary()` 心跳里,当 `chain_cash_gap > $1` 时自动把 book cash 设为链上 pUSD 余额
|
|
|
|
|
|
|
|
|
|
|
|
### 4.2 auto-absorb 反馈循环(已回滚)
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:LEDGER DRIFT 从 $1 指数增长到 $4,000,000+
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:auto-absorb 把 `-drift` 加到 adjustments,但 adjustments 是 ledger_drift 计算的一部分,导致每次心跳 drift 翻倍:$1 -> $2 -> $4 -> $8 -> ...
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:删掉 auto-absorb 代码。LEDGER DRIFT 只警告不自动修(避免反馈循环)。CASH≠CHAIN 仍然自动修(cash anchor 不影响 ledger_drift 计算)
|
|
|
|
|
|
|
|
|
|
|
|
**教训**:不要用 adjustments 来"修复" ledger_drift -- adjustments 本身是 drift 计算的输入,改它只会让 drift 更大
|
|
|
|
|
|
|
|
|
|
|
|
### 4.3 in-play hold 导致订单"未成交"但实际成交
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:bot 日志显示 `pending expired unfilled`,但 Polymarket 网站上仓位实际存在
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:in-play 赛事(Dota 2 / LoL 等正在进行中的比赛)价格波动快,bot 保守挂单(in-play hold),超时后判定"未成交"并 cancel,但订单在 cancel 前刚好成交了
|
|
|
|
|
|
|
|
|
|
|
|
**修复**(已实现):`copybot.py:1512` 加了 late fill 检测 -- cancel 后再查一次 `get_order`,如果 `size_matched > 0` 就采纳为成交
|
|
|
|
|
|
|
|
|
|
|
|
### 4.4 RTDS / user-ws 频繁断线
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:日志反复出现 `rtds: stream down - reconnect in 60s` 和 `user-ws: down - reconnect`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:代理网络不稳,WebSocket 连接频繁断开
|
|
|
|
|
|
|
|
|
|
|
|
**影响**:检测延迟从 ~3 秒变成 ~17-74 秒(fallback 到 60 秒轮询)
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:重启 live bot 重连 WebSocket:`systemctl restart copybot-live`
|
|
|
|
|
|
|
|
|
|
|
|
### 4.5 book unreliable spread too wide
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:`skip (book unreliable (spread 0.12 > 0.08))`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:live bot 有 paper bot 没有的保护机制 -- 价差 > 8 分就跳过(避免在流动性差的市场吃大滑点)
|
|
|
|
|
|
|
|
|
|
|
|
**结论**:正常行为,保护真钱。不建议改阈值
|
|
|
|
|
|
|
|
|
|
|
|
### 4.6 paper 有持仓但 live 没有
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:
|
|
|
|
|
|
1. paper 有 $1,000(能持很多仓),live 只有 $5(最多 5 笔)
|
|
|
|
|
|
2. paper 直接记录交易(100% 成交),live 真实下单可能被 in-play hold / book unreliable 跳过
|
|
|
|
|
|
3. live 跟了卖单(平仓了),所以 open 0
|
|
|
|
|
|
4. 清过 state 丢了持仓追踪
|
|
|
|
|
|
|
|
|
|
|
|
**结论**:正常,两个 bot 执行环境不同
|
|
|
|
|
|
|
|
|
|
|
|
### 4.7 on-chain settle fallback: OFF
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:日志显示 `on-chain settle fallback: OFF - set ALCHEMY_RPC_URL`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:live.env 里没配 Alchemy RPC
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:`/etc/copybot/paper.env` 加 `ALCHEMY_RPC_URL=https://polygon-mainnet.g.alchemy.com/v2/你的KEY`(paper bot 用的,live bot 也可以加到 live.env)
|
|
|
|
|
|
|
|
|
|
|
|
### 4.8 feed 文件不更新(心跳显示几百分钟前)
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:dashboard 显示心跳 400+ 分钟前,但 bot 在跑
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:bot 用 commit-on-change 节流(`copybot.py:1328-1330`),feed 内容没变(没新交易/结算)就不重写文件
|
|
|
|
|
|
|
|
|
|
|
|
**结论**:正常。bot 在跑(`Live Bot: active`),只是没新事件。超过 1 小时可以重启确认
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 5. Dashboard 阶段
|
|
|
|
|
|
|
|
|
|
|
|
### 5.1 dashboard 打不开
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:浏览器访问 `http://45.207.206.36:18080/` 超时
|
|
|
|
|
|
|
|
|
|
|
|
**排查**:
|
|
|
|
|
|
1. 服务挂了?-> `systemctl restart copybot-dashboard`
|
|
|
|
|
|
2. 端口没监听?-> `ss -tlnp | grep 18080`
|
|
|
|
|
|
3. 本地 Clash 拦截?-> 关掉 Clash 系统代理
|
|
|
|
|
|
|
|
|
|
|
|
### 5.2 LIVE 模式显示 HTTP 404
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:切到 LIVE 模式显示 `断开:HTTP 404`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:`copybot_live_real.json` 文件不存在
|
|
|
|
|
|
|
|
|
|
|
|
**可能原因**:
|
|
|
|
|
|
1. feed_path 路径错误(`self.here` 是 copybot.py 所在目录 = 项目根,不是 live/)
|
|
|
|
|
|
2. bot 刚启动还没写 feed(等 60 秒)
|
|
|
|
|
|
3. 清 state 时把 feed 文件也删了
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:feed_path 必须是 `live/copybot_live_real.json`(带 `live/` 前缀,因为 bot 的 `self.here` 是项目根目录)
|
|
|
|
|
|
|
|
|
|
|
|
### 5.3 dashboard 健康面板显示 CASH≠CHAIN 一百万美元
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:`CASH≠CHAIN: $1069795.15`
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:auto-absorb 反馈循环导致 adjustments 累积到 $4M(见 4.2)
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:停 bot -> 清 state -> 重启(auto-absorb 代码已删除)
|
|
|
|
|
|
|
|
|
|
|
|
### 5.4 dashboard 数据不更新
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:dashboard 显示的数据是几小时前的
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:bot 用 commit-on-change 节流,没新交易就不重写 feed 文件。dashboard 读的是磁盘上的 feed 文件
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:正常行为。或手动触发 bot 写 feed:`sudo -u wwf git -C /opt/winning-wallet-finder add -A && sudo -u wwf git commit -m "manual sync" && sudo -u wwf git push`
|
|
|
|
|
|
|
|
|
|
|
|
### 5.5 开放订单数字与表格不符
|
|
|
|
|
|
|
|
|
|
|
|
**症状**:卡片显示"开放订单 15"但表格只有 11 条
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:bot 的 `open_count` 和 `bets` 数组是两个独立的计数器,`open_count` 包含不在 `bets` 数组里的早期仓位
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:dashboard 已统一用 `bets.filter(!settled).length`(表格的数字),不用 `d.open_count`
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 6. 代码修复记录
|
|
|
|
|
|
|
|
|
|
|
|
| 日期 | 文件 | 修复内容 | commit |
|
|
|
|
|
|
|------|------|---------|--------|
|
|
|
|
|
|
| 07-17 | `live/portfolio.py:336` | `except (ValueError, OverflowError)` 捕获 mktime 越界 | b916633 |
|
|
|
|
|
|
| 07-17 | `live/dashboard.py` | `encoding="utf-8"` 修复 Windows 中文渲染 | b916633 |
|
|
|
|
|
|
| 07-18 | `copybot.py:1512` | late fill 检测:cancel 后再查一次 get_order | ea0faf6 |
|
|
|
|
|
|
| 07-20 | `copybot.py:1714` | cash anchor:CASH≠CHAIN > $1 时自动对齐链上余额 | b689acb |
|
|
|
|
|
|
| 07-20 | `copybot.py:1714` | 删除 auto-absorb(反馈循环 bug) | f4d1c2a |
|
|
|
|
|
|
| 07-20 | `host/mihomo-healthcheck.sh` | 白名单(JP/HK)+ 测 POST /order | 83a385b |
|
|
|
|
|
|
| 07-20 | `live/serve_dashboard.py` | 新增 /api/health /api/daily /api/wallets | 03748c1 |
|
|
|
|
|
|
| 07-20 | `live/bot_dashboard.html` | 新增系统健康/每日流水线/钱包建议面板 | 03748c1 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 7. 操作陷阱
|
|
|
|
|
|
|
|
|
|
|
|
### 7.1 git reset --hard 顺序
|
|
|
|
|
|
|
|
|
|
|
|
**错误**:先清 state -> git reset --hard -> state 被恢复(腐败的 state 已被 bot commit 到 git)
|
|
|
|
|
|
|
|
|
|
|
|
**正确**:git reset --hard -> 再清 state
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
git fetch origin && git reset --hard origin/main
|
|
|
|
|
|
# 重要:reset 之后再清 state(bot 可能已把腐败 state commit 到 git)
|
|
|
|
|
|
rm -f copybot_state.live.json copybot_state.live.json copybot_fills.live.jsonl live/copybot_live_real.json
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 7.2 不要全局设 HTTPS_PROXY
|
|
|
|
|
|
|
|
|
|
|
|
**错误**:`echo "HTTPS_PROXY=..." >> /etc/environment`(所有程序都走代理)
|
|
|
|
|
|
|
|
|
|
|
|
**正确**:只在 `/etc/copybot/live.env` 里设(只 live bot 走代理)
|
|
|
|
|
|
|
|
|
|
|
|
### 7.3 不要用 adjustments 修 ledger_drift
|
|
|
|
|
|
|
|
|
|
|
|
**错误**:把 `-drift` 加到 adjustments 试图清零 drift
|
|
|
|
|
|
|
|
|
|
|
|
**原因**:adjustments 是 ledger_drift 计算的输入,改它会导致 drift 翻倍(反馈循环)
|
|
|
|
|
|
|
|
|
|
|
|
**正确**:ledger_drift 只警告不自动修。如果影响使用,手动清 state
|
|
|
|
|
|
|
|
|
|
|
|
### 7.4 改完配置必须重启
|
|
|
|
|
|
|
|
|
|
|
|
**忘记**:改了 `config.live.json` / `copybot.paper.json` / `live.env` 但没重启 bot
|
|
|
|
|
|
|
|
|
|
|
|
**解决**:改完任何配置都要 `systemctl restart copybot-live`(或对应服务)
|
|
|
|
|
|
|
|
|
|
|
|
### 7.5 新钱包 floor 先设 $25
|
|
|
|
|
|
|
|
|
|
|
|
**注意**:换跟单钱包时,新钱包的 floor 先设 $25(最低门槛),`daily.sh` 的 `sync_floors.py` 第二天自动算真实 p80 门槛覆盖掉
|
|
|
|
|
|
|
|
|
|
|
|
### 7.6 两个配置文件必须一致
|
|
|
|
|
|
|
|
|
|
|
|
**注意**:`config.live.json` 和 `copybot.paper.json` 的 `wallets` 数组必须一致(paper 和 live 跟同一批钱包,结果才可比)
|
|
|
|
|
|
|
|
|
|
|
|
**验证**:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
python3 -c "import json; [print(w['name']) for w in json.load(open('config.live.json'))['wallets']]"
|
|
|
|
|
|
python3 -c "import json; [print(w['name']) for w in json.load(open('live/copybot.paper.json'))['wallets']]"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 7.7 paper 和 live 的 feed_path 不同
|
|
|
|
|
|
|
|
|
|
|
|
**注意**:bot 的 `self.here` = `os.path.dirname(os.path.abspath(__file__))` = copybot.py 所在目录(项目根 `/opt/winning-wallet-finder/`),不是 systemd 的 WorkingDirectory
|
|
|
|
|
|
|
|
|
|
|
|
- paper feed_path:`live/copybot_live.json` -> 写到 `/opt/winning-wallet-finder/live/copybot_live.json`
|
|
|
|
|
|
- live feed_path:`live/copybot_live_real.json` -> 写到 `/opt/winning-wallet-finder/live/copybot_live_real.json`
|
|
|
|
|
|
|
|
|
|
|
|
如果 feed_path 不带 `live/` 前缀,文件会写到项目根目录,dashboard 读不到
|
|
|
|
|
|
|
|
|
|
|
|
### 7.8 bot 会自动 commit + push 到 Gitea
|
|
|
|
|
|
|
|
|
|
|
|
**注意**:bot 每次有状态变化会自动 `git add + commit + push` state/feed/fills 文件到 Gitea
|
|
|
|
|
|
|
|
|
|
|
|
**影响**:
|
|
|
|
|
|
- 本地 `git push` 经常被拒(remote 有 bot 的 auto-commit)-> 用 `git pull --rebase`
|
|
|
|
|
|
- `git reset --hard` 会恢复 bot auto-commit 的 state(可能腐败)-> reset 后再清 state
|
|
|
|
|
|
|
|
|
|
|
|
### 7.9 健康检查脚本不在 git 仓库里
|
|
|
|
|
|
|
|
|
|
|
|
**历史**:健康检查脚本最初是用 heredoc 直接在服务器上创建的,不在 git 仓库
|
|
|
|
|
|
|
|
|
|
|
|
**已修复**:脚本已放入 `host/mihomo-healthcheck.sh`,git pull 后 `cp host/mihomo-healthcheck.sh /opt/mihomo-healthcheck.sh`
|
|
|
|
|
|
|
|
|
|
|
|
### 7.10 Polymarket 禁单地区完整清单
|
|
|
|
|
|
|
|
|
|
|
|
以下地区的 IP 不能下单(CLOB /order 返回 403):
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
美国 (US) · 英国 (GB) · 法国 (FR) · 德国 (DE) · 意大利 (IT)
|
|
|
|
|
|
荷兰 (NL) · 波兰 (PL) · 新加坡 (SG) · 澳大利亚 (AU) · 加拿大安大略 · 巴西 (BR)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**允许的常见地区**:日本、香港、韩国、台湾、瑞典、南非、印度
|
|
|
|
|
|
|
|
|
|
|
|
> ⚠️ 新加坡很多人以为是允许的,实际在禁单列表里!
|
|
|
|
|
|
|
2026-07-21 09:10:57 +08:00
|
|
|
|
### 7.11 胜率是骗人的(作者核心研究发现)
|
|
|
|
|
|
|
|
|
|
|
|
**Polymarket 的胜率有幸存者偏差**:平台只兑现赢的份额,输的份额永远躺在 `/positions` 里不进 `/closed-positions`。一个钱包显示 90.6% 胜率,实际只有 48.3%。
|
|
|
|
|
|
|
|
|
|
|
|
**只有 Copy P&L(费后复制盈亏)才是真实指标**:
|
|
|
|
|
|
- ArbTraderRookie 显示 99.5% 胜率,但实际复制后亏 $790
|
|
|
|
|
|
- 全市场第一的钱包(43% 胜率)90 天亏了 $3.8M
|
|
|
|
|
|
|
|
|
|
|
|
**教训**:永远不要按胜率选钱包。dashboard 的"信念胜率"只是辅助参考,决策看前瞻 realized。
|
|
|
|
|
|
|
|
|
|
|
|
### 7.12 edge 可能随时消失
|
|
|
|
|
|
|
|
|
|
|
|
作者的一个顶级钱包(ArbTraderRookie)在分析过程中突然从 Polymarket API 消失了(2026-07-03)。
|
|
|
|
|
|
|
|
|
|
|
|
**edge 的来源**可能是比赛操纵相关的内幕信息,这些信息源随时可能被封禁或改变行为。
|
|
|
|
|
|
|
|
|
|
|
|
**防范**:
|
|
|
|
|
|
- 每周重新评估(daily.sh 自动重算,但人工 review 也很重要)
|
|
|
|
|
|
- 赚钱了定期取出来(不要假设 edge 永久存在)
|
|
|
|
|
|
- 如果某个钱包连续 1 周没有信号,考虑踢掉
|
|
|
|
|
|
|
|
|
|
|
|
### 7.13 长持仓杀死复利
|
|
|
|
|
|
|
|
|
|
|
|
leegunner 终身 P&L +$274k(看起来很厉害),但**复制后亏 $180**。原因是持仓 7.6 天才结算,资金被占用,复利效率极低。
|
|
|
|
|
|
|
|
|
|
|
|
**教训**:选钱包不只看盈亏,还要看**持仓时间**。持仓 > 7 天的钱包即使赚钱,复制后可能因为资金占用而亏。
|
|
|
|
|
|
|
|
|
|
|
|
### 7.14 紧急退出工具
|
|
|
|
|
|
|
|
|
|
|
|
如果需要一键清仓所有 live 仓位(bot 失控 / 紧急撤资):
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
systemctl stop copybot-live
|
|
|
|
|
|
cd /opt/winning-wallet-finder
|
|
|
|
|
|
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 host/flatten_positions.py
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
> 这是 `host/flatten_positions.py`,市价卖出所有仓位。真钱操作,只在紧急情况用。
|
|
|
|
|
|
|
2026-07-21 07:35:48 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 快速排查流程
|
|
|
|
|
|
|
|
|
|
|
|
遇到问题时的排查顺序:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
1. dashboard 打不开?
|
|
|
|
|
|
-> systemctl restart copybot-dashboard
|
|
|
|
|
|
-> 关掉本地 Clash
|
|
|
|
|
|
|
|
|
|
|
|
2. live bot 报错?
|
|
|
|
|
|
-> journalctl -u copybot-live --since "30 minutes ago" | tail -30
|
|
|
|
|
|
-> 看是 GEO-BLOCKED / CASH≠CHAIN / RTDS down / 还是其它
|
|
|
|
|
|
|
|
|
|
|
|
3. GEO-BLOCKED?
|
|
|
|
|
|
-> 代理节点切到禁单地区了
|
|
|
|
|
|
-> curl -s http://127.0.0.1:9090/proxies/GLOBAL | python3 -c "import sys,json; print(json.load(sys.stdin).get('now'))"
|
|
|
|
|
|
-> 手动切回日本节点
|
|
|
|
|
|
-> /opt/mihomo-healthcheck.sh 测试
|
|
|
|
|
|
|
|
|
|
|
|
4. CASH≠CHAIN / LEDGER DRIFT?
|
|
|
|
|
|
-> 停 bot -> 查链上余额 -> 设 bankroll -> 清 state -> 重启
|
|
|
|
|
|
-> (CASH≠CHAIN > $1 会自动修,LEDGER DRIFT 只能手动清)
|
|
|
|
|
|
|
|
|
|
|
|
5. RTDS down?
|
|
|
|
|
|
-> systemctl restart copybot-live(重连 WebSocket)
|
|
|
|
|
|
|
|
|
|
|
|
6. 代理异常?
|
|
|
|
|
|
-> systemctl status mihomo
|
|
|
|
|
|
-> /opt/mihomo-healthcheck.sh
|
|
|
|
|
|
-> HTTPS_PROXY=http://127.0.0.1:7890 python3 host/geocheck.py | tail -1
|
|
|
|
|
|
|
|
|
|
|
|
7. daily.sh 没跑?
|
|
|
|
|
|
-> tail -10 /opt/winning-wallet-finder/live/daily.log
|
|
|
|
|
|
-> 手动跑:cd /opt/winning-wallet-finder/live && bash daily.sh
|
|
|
|
|
|
```
|