# Polymarket 套利机器人 — 中文使用手册 > 适用版本:v0.1.0 · Python 3.12+ · Windows / Linux / macOS > > 本文从环境准备到日常运维,按真实使用顺序逐步讲解。 --- ## 目录 1. [项目简介](#1-项目简介) 2. [系统要求](#2-系统要求) 3. [快速安装](#3-快速安装) 4. [首次配置](#4-首次配置) 5. [首次运行](#5-首次运行) 6. [日常使用(Paper 模式)](#6-日常使用paper-模式) 7. [Web 仪表板](#7-web-仪表板) 8. [切换到 Live 模式](#8-切换到-live-模式) 9. [监控与运维](#9-监控与运维) 10. [故障排查](#10-故障排查) 11. [安全建议](#11-安全建议) 12. [附录:环境变量参考](#附录环境变量参考) --- ## 1. 项目简介 **Polymarket NegRisk 多结果套利机器人**。Polymarket 的某些分类事件(例如"2028 大选谁赢")每个结果独立挂牌交易。当**所有结果的卖一价加总 < $1** 时,买入一整套结果,结算时一定收回 $1 → **无风险套利**。 本机器人扫描所有活跃 negRisk 事件,实时计算套利空间,提供两种模式: | 模式 | 资金风险 | 用途 | |------|---------|------| | **Paper** | $0 | 模拟成交,验证策略,观察 PnL | | **Live** | 实盘资金 | 真实下单,需提供钱包私钥 | --- ## 2. 系统要求 | 项目 | 要求 | |------|------| | **Python** | 3.12 或更高 | | **操作系统** | Windows 10+ / Linux / macOS | | **内存** | ≥ 512 MB | | **磁盘** | ≥ 1 GB(含 SQLite 与日志) | | **网络** | **必须**能访问 `polymarket.com`(国内需配置代理) | | **钱包**(仅 Live) | Polygon 上的专用 EOA,持有 USDC.e | **国内用户注意**:Polymarket 服务器在国内无法直连,必须配置 HTTP 代理(详见 [§4.2 网络代理](#42-网络代理))。 --- ## 3. 快速安装 ### 3.1 克隆项目 ```bash git clone https://github.com/matthewnyc2/arbitrage cd arbitrage ``` ### 3.2 创建虚拟环境 **Windows (PowerShell)**: ```powershell python -m venv .venv .\.venv\Scripts\Activate.ps1 ``` **Linux / macOS**: ```bash python3 -m venv .venv source .venv/bin/activate ``` ### 3.3 安装依赖 ```bash pip install -e ".[dev]" ``` > **⚠️ 重要**:默认会装 `websockets>=13.0`,pip 可能会拉到 **15.x** 版本,但该版本与项目不兼容(参见 [§10.3 websockets 版本问题](#103-websockets-版本问题))。**显式锁版本**: > ```bash > pip install "websockets==14.2" > ``` ### 3.4 验证安装 ```bash arb --help ``` 应显示:`init / discover / scan / web / resolve` 五个子命令。 --- ## 4. 首次配置 ### 4.1 复制环境变量模板 ```bash cp .env.example .env ``` `.env` 关键字段(Paper 模式默认值即可运行): ```ini ARB_MODE=paper # paper = 模拟盘;live = 实盘 ARB_CLOB_HOST=https://clob.polymarket.com ARB_GAMMA_HOST=https://gamma-api.polymarket.com ARB_PROXY= # 国内用户填代理,见下文 ``` ### 4.2 网络代理 **国内 / 防火墙环境下必须配置**,否则 `arb discover` 会报 `httpx.ConnectTimeout`。 **PowerShell 临时设置**(仅当前会话): ```powershell $env:HTTPS_PROXY="http://127.0.0.1:7890" # 改成你的代理地址 $env:HTTP_PROXY="http://127.0.0.1:7890" ``` **永久设置**(写入 `.env`): ```ini ARB_PROXY=http://127.0.0.1:7890 ``` > **常见代理端口**:Clash 默认 7890,V2Ray 默认 10809,SSR 默认 1080。 > > 配置完成后 httpx(REST)和 websockets(WS)都会通过代理连接。 ### 4.3 验证代理可用 ```bash arb discover ``` 预期输出: ``` seen=2000 negRisk=928 upserted=894 malformed=34 ``` 如果仍超时,回到 [§10.1 网络连通性](#101-网络连通性)。 --- ## 5. 首次运行 ### 5.1 初始化数据库 ```bash arb init ``` 创建 SQLite 表结构(含 events / outcomes / opportunities / baskets / fills / live_orders / resolutions / denylist / daily_pnl)。 ### 5.2 发现事件 ```bash arb discover ``` 从 Polymarket Gamma API 拉取所有活跃 negRisk 事件。需要约 10–20 秒。 **持续发现**(生产部署推荐,每 180 秒刷新): ```bash arb discover --loop --interval 180 ``` ### 5.3 启动扫描 ```bash arb scan ``` 开始监听 CLOB WebSocket,实时检测套利机会,写入 paper baskets。 预期日志: ``` scan loop started (885 events hydrated) ws subscribed to N tokens ``` ### 5.4 启动 Web 仪表板(另一终端) ```bash arb web ``` 打开浏览器访问 。 --- ## 6. 日常使用(Paper 模式) ### 6.1 标准三进程部署 | 终端 | 命令 | 作用 | |------|------|------| | 终端 1 | `arb discover --loop --interval 180` | 每 3 分钟刷新事件列表 | | 终端 2 | `arb scan` | 实时扫描 + 模拟成交 | | 终端 3 | `arb web` | Web 仪表板 | **Linux/macOS 后台运行**: ```bash nohup arb discover --loop --interval 180 > logs/discover.log 2>&1 & nohup arb scan > logs/scan.log 2>&1 & ``` ### 6.2 CLI 命令速查 | 命令 | 功能 | |------|------| | `arb init` | 创建 SQLite schema | | `arb discover` | 单次拉取事件 | | `arb discover --loop` | 持续拉取 | | `arb scan` | 启动扫描 | | `arb web` | 启动仪表板(默认 127.0.0.1:8000) | | `arb resolve --winner ` | 手动标记事件结算结果 | | `arb resolve ` | 标记为 invalid | ### 6.3 停止服务 **正常停止**:在运行终端按 `Ctrl+C`。 **强制清理残留进程**(Windows): ```powershell Get-Process python | Where-Object { $_.StartTime -gt (Get-Date).AddHours(-1) } | Stop-Process -Force ``` --- ## 7. Web 仪表板 仪表板每 2–3 秒自动刷新(HTMX 轮询),无需手动操作。 ### 7.1 主要面板 | 面板 | 显示内容 | |------|---------| | **Paper PnL** | 已实现盈亏、各状态组合数、Kill Switch 按钮 | | **Baskets** | 最近 25 个组合:ID、事件、份数、成本、状态、PnL | | **Recent Opportunities** | 最近 25 个检测到的机会:Σ asks、净边际、最大组合、预期利润 | ### 7.2 关键指标解读 **Σ asks < $1** → 存在套利空间。典型值: - `0.98` → 净边际 ~2%(扣费前) - `0.95` → 净边际 ~5%(扣费前) - `< 0.90` → 非常罕见的深度套利 **net edge bps**:扣除手续费 + 分摊 gas 后的净边际。低于 50 bps 会被 `ARB_MIN_NET_EDGE_BPS` 过滤。 **status**: | 状态 | 含义 | |------|------| | `pending_resolution` | 等待事件结算 | | `redeemed` | 已结算,PnL 入账 | | `failed` | 部分腿未成交(paper 模拟时深度消失) | | `invalid` | 事件被标记为无效 | ### 7.3 Kill Switch 仪表板右下角红色 **kill** 按钮,点击后立即创建 `./KILL` 文件,执行器会拒绝所有新单。再次点击 **unkill** 删除文件即可恢复。 也可在终端手动: ```bash # Windows New-Item -Path .\KILL -ItemType File # Linux/macOS touch ./KILL ``` --- ## 8. 切换到 Live 模式 ### 8.1 准备工作 1. **专用钱包**:在 Polygon 上创建一个新的 EOA,**不要复用个人钱包** 2. **充值**:向钱包转入 USDC.e(建议 ≥ $200,含 gas) 3. **批准授权**:按 `docs/api/order-signing.md` §8 的脚本,对 CTF Exchange + NegRisk Exchange + NegRisk Adapter 三个合约授权 ### 8.2 派生 L2 API 凭证 按 `docs/api/order-signing.md` §2 的 `bootstrap_clob_creds.py` 脚本执行一次,生成: - `CLOB_API_KEY` - `CLOB_SECRET` - `CLOB_PASSPHRASE` **这三个凭证无法恢复,丢失需重新派生。** ### 8.3 修改 `.env` ```ini ARB_MODE=live ARB_PRIVATE_KEY=0x... # 钱包私钥(0x 前缀) ARB_FUNDER_ADDRESS=0x... # 资金地址(EOA 模式 = 私钥对应地址) ARB_SIGNATURE_TYPE=0 # 0=EOA, 1=Polymarket proxy, 2=Gnosis Safe ARB_API_KEY=... ARB_API_SECRET=... ARB_API_PASSPHRASE=... # 风险上限(强烈建议保持默认值) ARB_MAX_BASKET_USD=50 ARB_MAX_OPEN_BASKETS=3 ARB_DAILY_LOSS_STOP_USD=100 ``` ### 8.4 首次实盘(强烈建议 dry_run 验证) **第 1 步**:先用 dry_run 验证签名链路: ```python # 在 Python REPL 中手动测试 from arbitrage.engine.live_executor import LiveExecutor, RiskLimits from arbitrage.book.l2 import BookRegistry books = BookRegistry() ex = LiveExecutor(books=books, dry_run=True) # 只签名不提交 ``` **第 2 步**:把 `cli.py:87` 的 `dry_run=False` 保持不变(默认就是 False),但**先把 `ARB_MAX_BASKET_USD` 设为 `5`**: ```ini ARB_MAX_BASKET_USD=5 ARB_MAX_OPEN_BASKETS=1 ``` **第 3 步**:观察 1–2 天无异常后,再逐步放大到默认值。 --- ## 9. 监控与运维 ### 9.1 日志 日志写在 `logs/arbitrage.jsonl`(结构化 JSON,每天 0 点轮转,保留 7 天)。 **实时查看**: ```bash # Linux/macOS tail -f logs/arbitrage.jsonl | jq . # Windows PowerShell Get-Content logs\arbitrage.jsonl -Wait ``` **按事件过滤**: ```bash grep "new_market" logs/arbitrage.jsonl | tail -20 ``` ### 9.2 数据库 位置:`./arbitrage.db`(SQLite + WAL 模式) **直接查询**: ```bash sqlite3 arbitrage.db "SELECT status, COUNT(*) FROM baskets GROUP BY status;" sqlite3 arbitrage.db "SELECT * FROM opportunities ORDER BY detected_at DESC LIMIT 10;" ``` **备份**: ```bash cp arbitrage.db arbitrage.db.bak-$(date +%Y%m%d) ``` **重置**(清空所有 paper 数据): ```bash rm arbitrage.db arb init arb discover ``` ### 9.3 进程监控 **检查运行中的 arb 进程**: ```powershell # Windows Get-Process | Where-Object { $_.Name -eq "python" -and $_.Path -like "*Python312*" } # Linux ps aux | grep arb ``` **查看资源占用**: ```bash # 内存占用(正常 100-300 MB) Get-Process python | Select-Object Id, @{n='Mem(MB)';e={[int]$_.WorkingSet64/1MB}} ``` ### 9.4 升级 ```bash cd arbitrage git pull pip install -e ".[dev]" # 重启 arb scan / arb web ``` --- ## 10. 故障排查 ### 10.1 网络连通性 **症状**:`httpx.ConnectTimeout`,`arb discover` 卡住。 **排查**: ```powershell Test-NetConnection -ComputerName gamma-api.polymarket.com -Port 443 ``` 如果失败,确认 `ARB_PROXY` 设置正确,或切换代理节点。 ### 10.2 WebSocket 反复重连 **症状**:`ws disconnect (TimeoutError); reconnecting in 1.0s` 大量重复。 **根因**:WebSocket 没有走代理。 **修复**:确认 `.env` 中设置了 `ARB_PROXY=http://...`,代码会自动通过 HTTP CONNECT 隧道建立 WS 连接。 ### 10.3 websockets 版本问题 **症状**:`AttributeError: 'ClientConnection' object has no attribute 'recv_messages'`,或 `got an unexpected keyword argument 'proxy'`。 **根因**:`websockets 15.0` 与项目不兼容。 **修复**: ```bash pip install "websockets==14.2" ``` ### 10.4 日志 PermissionError **症状**:`PermissionError: [WinError 32] 另一个程序正在使用此文件` **根因**:loguru 在 Windows 上的 50MB 轮转触发 `close() → os.rename()` 竞态。 **修复**(已默认配置):`rotation="1 day"` + `retention="7 days"`,避免高并发期轮转。 如果仍出现: ```powershell # 清理残留进程 Get-Process python | Where-Object { $_.Path -like "*Python312*" } | Stop-Process -Force ``` ### 10.5 残留进程占用文件 **症状**:杀掉 `arb scan` 后,新进程仍报 PermissionError。 **排查**: ```powershell Get-Process | Where-Object { $_.Name -eq "python" } ``` **清理**: ```powershell Get-Process python -ErrorAction SilentlyContinue | Stop-Process -Force ``` ### 10.6 仪表板 404 / 端口冲突 **症状**:浏览器访问 `http://127.0.0.1:8000` 返回 404 或连接拒绝。 **排查**: ```powershell Test-NetConnection -ComputerName 127.0.0.1 -Port 8000 Get-NetTCPConnection -LocalPort 8000 -State Listen ``` **修复**:更换端口启动: ```bash arb web --port 8888 ``` ### 10.7 没有任何套利机会 **症状**:仪表板显示 `recent opportunities` 为空或 net edge bps 全部 < 50。 **原因**: 1. 当前 Polymarket 没有负空间(正常 — 套利机会稀少) 2. WS 数据未刷新(检查 `ws subscribed` 日志) 3. `ARB_MIN_NET_EDGE_BPS` 设得太高(默认值 50 合理) --- ## 11. 安全建议 ### 11.1 私钥保护 - **永远不要把 `.env` 提交到 Git**(已在 `.gitignore` 中) - 实盘私钥使用**专用钱包**,与其他资产隔离 - 服务器上 `.env` 文件权限设为 `chmod 600`(Linux) - 考虑使用硬件钱包或多签 ### 11.2 Web 仪表板 - 默认绑定 `127.0.0.1`,**不要**改为 `0.0.0.0` 后暴露到公网 - `kill` / `unkill` 端点**无身份认证**,暴露即等于把钱包控制权交给攻击者 - 如果需要远程访问,使用 SSH 隧道: ```bash ssh -L 8000:127.0.0.1:8000 user@server ``` ### 11.3 依赖管理 - 锁定关键依赖版本,避免供应链风险: ```bash pip install "websockets==14.2" "py-clob-client==0.34.6" ``` - 定期升级时检查 changelog ### 11.4 Live 模式额外建议 - 先用 ≥ $10 的小资金跑 1 周 - 每日检查 realized PnL,确认与 paper 结果趋势一致 - 设置价格告警(Discord webhook / Telegram bot 等) - 监控 `daily_pnl` 表,日亏损接近 `ARB_DAILY_LOSS_STOP_USD` 时手动 kill --- ## 附录:环境变量参考 完整 `.env` 配置项: | 变量 | 默认值 | 说明 | |------|--------|------| | `ARB_MODE` | `paper` | `paper` / `live` | | `ARB_CLOB_HOST` | `https://clob.polymarket.com` | CLOB API | | `ARB_GAMMA_HOST` | `https://gamma-api.polymarket.com` | Gamma REST | | `ARB_DATA_HOST` | `https://data-api.polymarket.com` | Data API | | `ARB_WS_URL` | `wss://ws-subscriptions-clob.polymarket.com/ws/market` | WS 端点 | | `ARB_POLYGON_RPC` | `https://polygon-rpc.com` | Polygon RPC | | `ARB_PROXY` | _空_ | HTTP 代理(REST + WS 共享) | | `ARB_PRIVATE_KEY` | _空_ | 钱包私钥(Live 必填) | | `ARB_FUNDER_ADDRESS` | _空_ | 资金地址(Live 必填) | | `ARB_SIGNATURE_TYPE` | `0` | 0=EOA / 1=proxy / 2=Safe | | `ARB_API_KEY` | _空_ | CLOB L2 API key | | `ARB_API_SECRET` | _空_ | CLOB L2 API secret | | `ARB_API_PASSPHRASE` | _空_ | CLOB L2 API passphrase | | `ARB_MIN_NET_EDGE_BPS` | `50` | 最低净边际(基点) | | `ARB_MAX_BASKET_USD` | `50` | 单笔组合上限 USD | | `ARB_MAX_OPEN_BASKETS` | `3` | 全局未结算组合上限 | | `ARB_DAILY_LOSS_STOP_USD` | `100` | 日亏损止损 USD | | `ARB_KILL_SWITCH_FILE` | `./KILL` | Kill switch 文件路径 | | `ARB_PAPER_LATENCY_MS` | `250` | Paper 模拟延迟(毫秒) | | `ARB_DB_PATH` | `./arbitrage.db` | SQLite 路径 | | `ARB_WEB_HOST` | `127.0.0.1` | Web 监听地址 | | `ARB_WEB_PORT` | `8000` | Web 端口 | | `ARB_LOG_LEVEL` | `INFO` | 控制台日志级别 | --- ## 联系与反馈 - 项目主页: - GitHub Issues: - API 参考:`docs/api/order-signing.md`、`docs/api/negrisk.md` - 设计文档:`DESIGN.md`