# Polymarket API 完整调研报告 > 数据来源:官方文档 https://docs.polymarket.com/、Polymarket/agent-skills GitHub、polymarkets.co.il 教程 (2026-07) > 调研日期:2026-07-13 --- ## 0. 总体架构 Polymarket 将数据拆分为 **4 个 REST API + 3 个 WebSocket 频道**,前 3 个完全公开(无需 API Key): | API | Base URL | 鉴权 | 用途 | |---|---|---|---| | **Gamma API** | `https://gamma-api.polymarket.com` | 公开 | 市场元数据、发现、搜索、标签 | | **CLOB API** | `https://clob.polymarket.com` | 读公开 / 写需 L2 | 订单簿、价格、深度、历史价 | | **Data API** | `https://data-api.polymarket.com` | 公开 | 用户持仓、交易、活跃度、Holder、OI | | **Bridge API** | `https://bridge.polymarket.com` | 钱包 | 充提(fun.xyz 代理) | | **RTDS WebSocket** | `wss://ws-subscriptions-clob.polymarket.com/ws/{market,user}` + `wss://sports-api.polymarket.com/ws` | 公开 / 鉴权 | 实时订单簿、成交、用户事件 | 官方 SDK:**Python (`py-clob-client`)**、**TypeScript (`@polymarket/clob-client`)**、**Rust (`rs-clob-client`)**。第三方封装很多(`polymarket-pandas`、`polybricks-sdk`、`almanak-sdk` 等)。 --- ## 1. 数据模型(核心概念) ``` Event(事件) ──┬── Market A ── Yes token / No token (条件 ID = conditionId) ├── Market B ── Yes token / No token └── Market N ``` - **Event**:顶级问题(如 "2024 大选谁赢?")。每个 event 含 ≥1 个 market。 - **Market**:实际可交易的二元/多元合约,对应一对 ERC-1155 `token_id`。 - **核心 ID**: - `conditionId` — 市场唯一条件 ID(0x + 64 hex) - `questionID` — UMA 解析用的哈希 - `tokenID / asset_id` — Yes/No 各自的 ERC-1155 token ID(**下单/查订单簿都用它**) - `slug` — URL 友好标识 - **价格含义**:`outcomePrices` 是隐含概率,二元市场 `[Yes, No]` 数值相加 ≈ 1。 - **市场类型**:`negRisk=true` → 多结果互斥事件;`enableOrderBook=true` → 可在 CLOB 交易。 --- ## 2. Gamma API — 市场发现与元数据 > 无需鉴权,REST。 ### 2.1 端点列表 | 端点 | 用途 | |---|---| | `GET /events` | 列出 events(带过滤、分页) | | `GET /events/{id}` | 单个 event | | `GET /events/keyset` | keyset 分页版本(用于游标分页) | | `GET /markets` | 列出 markets | | `GET /markets/{id}` | 单个 market | | `GET /public-search` | 全文搜索 events/markets/profiles | | `GET /tags` | 标签(分类)列表 | | `GET /series` | 系列(分组 event) | | `GET /sports` | 体育元数据 | | `GET /teams` | 球队 | | `GET /comments` | 评论(部分端点) | ### 2.2 `/events` 关键过滤参数 | 参数 | 说明 | |---|---| | `slug` | URL slug 精确匹配 | | `id` | event id | | `tag_id` | 标签 ID(可多次传入,支持 `related_tags=true`) | | `tag_slug` | slug 形式过滤 | | `exclude_tag_id` | 排除的标签 | | `series_id` | 系列 ID(体育赛事分组) | | `active` | 是否上架 | | `closed` | 是否已结算(默认 `false`) | | `archived` | 是否归档 | | `new`, `featured`, `restricted` | 状态布尔 | | `live` | 是否 live | | `order` | `volume_24hr` / `volume` / `liquidity` / `start_date` / `end_date` / `competitive` / `closed_time` | | `ascending` | `true` / `false` | | `limit` | 1–500,默认 20 | | `offset` | 分页偏移 | | `include_chat`, `include_template` | 是否包含聊天/模板字段 | 示例: ```bash # 24h 成交量最高的活跃事件 curl "https://gamma-api.polymarket.com/events?active=true&closed=false&order=volume24hr&ascending=false&limit=100" # NBA 标签下的活动 curl "https://gamma-api.polymarket.com/events?tag_id=745&active=true&closed=false" ``` ### 2.3 `/markets` 关键过滤参数 `/markets` 支持几乎所有 `/events` 的参数,外加: | 参数 | 说明 | |---|---| | `condition_ids` / `clob_token_ids` / `question_ids` | 用 ID 精确匹配 | | `slug` | URL slug | | `archived`, `featured`, `new`, `restricted`, `closed`, `active` | 状态 | | `order` / `ascending` | 排序 | | `liquidity_num_min`, `volume_num_min` | 数值范围过滤 | | `end_date_min`, `end_date_max` | 截止日期范围 | | `limit` (≤500) / `offset` | 分页 | ### 2.4 `/tags` 常用分类与 ID | Tag | ID | |---|---| | Sports(运动) | 1 | | Politics(政治) | 2 | | Election(选举) | 3 | | Crypto(加密货币) | 21 | | Bitcoin(比特币) | 100196 | | Ethereum(以太坊) | 100383 | | NFL | 450 | | NBA | 745 | | Tennis | 864 | | Esports | 702 | | Soccer(足球) | 1059 | | EPL | 739 | | UCL | 2186 | | Middle East | 1432 | ⚠️ 教程建议生产环境只用数值 `tag_id`,`tag_slug` 和 `?q=...` 不稳定。 --- ## 3. CLOB API — 价格与订单簿 > 读端点公开,写端点(挂单/撤单)需 L2 钱包签名鉴权。 ### 3.1 公共只读端点 | 端点 | 说明 | |---|---| | `GET /markets` | 列出 CLOB markets(**注意与 Gamma 的 `/markets` 不同**,是简化版) | | `GET /markets/{conditionId}` | 单个 market 详情 | | `GET /book?token_id=...` | 某 token 的订单簿快照 | | `POST /books` | 批量订单簿(≤500 token) | | `GET /price?token_id=...&side=BUY\|SELL` | 买/卖最优价 | | `POST /prices` | 批量最优价 | | `GET /midpoint?token_id=...` | 中间价 | | `POST /midpoints` | 批量中间价 | | `GET /spread?token_id=...` | 价差 | | `POST /spreads` | 批量价差 | | `GET /last-trade-price?token_id=...` | 最近成交价 | | `POST /last-trades-prices` | 批量最近成交 | | `GET /prices-history?market=...` | **历史价格** | | `POST /prices-history` | 批量历史价格 | ### 3.2 历史价格 `/prices-history` 参数 | 参数 | 必填 | 说明 | |---|---|---| | `market` | ✅ | token_id(asset_id) | | `startTs` | ❌ | Unix 秒(与 `interval` 互斥) | | `endTs` | ❌ | Unix 秒 | | `interval` | ❌ | `max` / `all` / `1m` / `1w` / `1d` / `6h` / `1h` | | `fidelity` | ❌ | 精度(分钟),默认 1 | 返回 `[{ "t": timestamp, "p": price }, ...]`。 ### 3.3 `/markets` (CLOB) 参数 - 支持 `next_cursor` 游标分页(新版上限 limit=100,需用 `after_cursor`) - 过滤字段:`active`, `closed`, `archived`, `condition_ids`, `clob_token_ids`, `question_ids`, `slug`, `tags`, `order`, `ascending` ### 3.4 鉴权写入端点(L2) 挂单、撤单、查用户订单、心跳、API key 创建等。需用 `POLY_API_KEY / POLY_ADDRESS / POLY_SIGNATURE / POLY_PASSPHRASE / POLY_TIMESTAMP` 头部 HMAC 签名。 --- ## 4. Data API — 持仓、交易、Holder、OI > 全部公开。 ### 4.1 端点列表 | 端点 | 关键参数 | |---|---| | `GET /positions` | `user` (0x 地址, 必填), `market` (conditionId 数组), `eventId`, `sizeThreshold`, `redeemable`, `mergeable`, `limit` (≤500), `offset` (≤10000), `sortBy` (`CURRENT`/`INITIAL`/`TOKENS`/`CASHPNL`/`PERCENTPNL`/`TITLE`/`RESOLVING`/`PRICE`/`AVGPRICE`), `sortDirection` (`ASC`/`DESC`), `title` | | `GET /closed-positions` | `user` (必填), `market[]`, `eventId[]`, `title`, `limit` (≤50), `offset` (≤100000), `sortBy` (`REALIZEDPNL`/`TITLE`/`PRICE`/`AVGPRICE`/`TIMESTAMP`), `sortDirection` | | `GET /activity` | `user` (必填), `market[]`, `eventId[]`, `type` (`TRADE`/`SPLIT`/`MERGE`/`REDEEM`/`REWARD`/`CONVERSION`/`DEPOSIT`/`WITHDRAWAL`/`YIELD`/`MAKER_REBATE`/`TAKER_REBATE`/`REFERRAL_REWARD`), `side` (`BUY`/`SELL`), `start`/`end` Unix 秒, `sortBy` (`TIMESTAMP`/`TOKENS`/`CASH`), `sortDirection`, `limit` (≤500), `offset` | | `GET /v1/market-positions` | **按市场查 top 持仓人**:`market` (conditionId, 必填), `user`, `status` (`OPEN`/`CLOSED`/`ALL`), `sortBy` (`TOKENS`/`CASH_PNL`/`REALIZED_PNL`/`TOTAL_PNL`), `sortDirection`, `limit` (≤500), `offset` | | `GET /value?user=...` | 用户所有持仓的总价值(美元) | | `GET /oi` | 全市场未平仓量(按市场聚合) | | `GET /holders?market={conditionId}` | 某市场的 top 持仓人 | | `GET /trades` | 全市场成交流(见下) | > **⚠️ 踩坑笔记(`/closed-positions`)** > > 1. **`limit` 上限是 50,不是 100**。服务端会忽略超过 50 的请求或截断,导致 PnL/信誉分计算漏数据。`data_api.py:get_closed_positions` 已用 `min(limit, 50)` 防御性 clamp。 > 2. **默认 `sortBy=REALIZEDPNL` 是个坑**:返回的是"最赚/最亏的 50 条",而不是"最近的 50 条"。如果直接按 `timestamp >= cutoff` 在 Python 端过滤,窗口内的平仓可能根本不在前 50 盈亏里 → 静默漏数。正确做法:用 `sortBy=TIMESTAMP` + `sortDirection=DESC` + `offset` 翻页,直到拿到 `ts < cutoff` 的记录就停。封装见 `data_api.py:get_closed_positions_since`。 > > 本项目曾因这两个问题导致 PnL 和信誉分偏小,已在 `wallet_pool.py` / `bayesian.py` 修复。 > **📝 `/markets` 端点用法(信号结果回填)** > > 信号回填服务(`outcome_resolver.py`)调 Gamma `/markets?condition_id=...` 拉市场结算结果。关键字段(按官方 `/markets/{id}` schema): > > - `closed` (bool):市场是否已关闭/结算 > - `closedTime` (str):结算时间 > - `outcomes` (str):JSON 数组,如 `'["Yes", "No"]'` > - `outcomePrices` (str):JSON 数组,结算后赢家价格 = 1,输家 = 0 > > 判定逻辑:`closed=true` 且 `outcomePrices` 中某 outcome 价格 ≥ 0.99 即为赢家。PnL 模型:win = `S*(1-p)/p`,loss = `-S`(理论全仓执行,不建模滑点)。 ### 4.2 `/trades`(成交历史)参数 | 参数 | 说明 | |---|---| | `market` | conditionId | | `asset_id` | token ID | | `maker_address` | 必填,按 maker 过滤 | | `before`, `after` | Unix 秒时间窗 | | `next_cursor` | base64 游标分页 | | `id` | 单笔 trade ID | 鉴权:需 L2 API key 头。返回字段包括 `taker_order_id`、`asset_id`、`side`、`size`、`fee_rate_bps`、`price`、`status`、`match_time`、`outcome`、`owner`、`maker_address`、`transaction_hash`、`trader_side`、`maker_orders[]`。 ### 4.3 返回字段(持仓示例) ``` proxyWallet, asset, conditionId, size, avgPrice, initialValue, currentValue, cashPnl, percentPnl, totalBought, realizedPnl, percentRealizedPnl, curPrice, redeemable, mergeable, title, slug, icon, eventSlug, outcome, outcomeIndex, oppositeOutcome, oppositeAsset, endDate, negativeRisk ``` ### 4.4 其他 Data 端点 - `GET /leaderboard` — 排行榜 - `GET /profiles/{address}` — 公开档案 - `GET /comments/by-user/{address}` — 用户评论 - `GET /builder-leaderboard` — builder 排行榜 - `GET /v1/accounting/snapshot` — 会计快照下载(ZIP/CSV) - `GET /v1/positions/combos`, `/v1/activity/combos` — 组合仓 --- ## 5. WebSocket — 实时数据 | 频道 | Endpoint | 鉴权 | 订阅方式 | |---|---|---|---| | Market | `wss://ws-subscriptions-clob.polymarket.com/ws/market` | 否 | 按 `assets_ids[]`(token_id) | | User | `wss://ws-subscriptions-clob.polymarket.com/ws/user` | **是** | 按 `markets[]`(conditionId),省略=全部 | | Sports | `wss://sports-api.polymarket.com/ws` | 否 | 无需订阅 | ### 5.1 Market 频道事件类型 | 事件 | 触发 | |---|---| | `book` | 订阅时 + 影响订单簿的成交 | | `price_change` | 挂单/撤单 | | `last_trade_price` | 成交 | | `tick_size_change` | 价格越过 0.96 / 0.04(**做市必听**) | | `best_bid_ask` | 需 `custom_feature_enabled=true` | | `new_market` | 新市场创建 | | `market_resolved` | 结算 | 订阅消息: ```json {"assets_ids":["TOKEN_ID"], "type":"market", "custom_feature_enabled":true} ``` ### 5.2 User 频道事件 - `trade` — 成交生命周期(MATCHED / MINED / CONFIRMED / RETRYING / FAILED) - `order` — 订单生命周期(PLACEMENT / UPDATE / CANCELLATION) ### 5.3 心跳 - Market/User:**客户端每 10 秒发 `PING`** - Sports:**服务端每 5 秒发 `ping`,客户端必须在 10 秒内回 `pong`**,否则断连 --- ## 6. 子图 / 链上数据(Goldsky Subgraph) 通过 GraphQL 查询 Polymarket on-chain 数据: | 子图 | 内容 | |---|---| | Positions | 用户 token 余额 | | Orders | 订单簿和成交事件 | | Activity | Split / Merge / Redeem | | OpenInterest | 市场 OI | | PNL | 用户盈亏 | 端点(Goldsky 托管): ``` https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/orderbook-subgraph/0.0.1/gn ``` --- ## 7. 速率限制 & 缓存建议 - Gamma / Data API(Cloudflare 前置): - 同一 IP **≤30 req/s** 持续 → 安全 - **100+ req/s** 突发 → 偶发 429(重试可恢复) - **500 req/s** 持续 → 限流 / 封禁 10–60s - 响应头 `Cache-Control` 通常 30–60s - 推荐:单 fetcher 进程 + 本地 LRU 缓存(30s TTL),多个消费者读取本地副本 - 大量拉取时建议加 1 fetcher × N consumers,避免多 fetcher 抢配额 --- ## 8. 常用查询模式速查 ### 8.1 找"现在最热"的市场 ```bash curl "https://gamma-api.polymarket.com/events?active=true&closed=false&order=volume24hr&ascending=false&limit=100" ``` ### 8.2 查某个分类所有活跃市场 ```bash # 政治类(Politics tag = 2) curl "https://gamma-api.polymarket.com/events?tag_id=2&active=true&closed=false&order=volume&ascending=false" ``` ### 8.3 拿单个市场的实时报价 ```bash # 1. 用 slug 查 conditionId / clobTokenIds curl "https://gamma-api.polymarket.com/events?slug=fed-decision-in-october" # 2. 用 token_id 查订单簿 curl "https://clob.polymarket.com/book?token_id=" # 3. 查历史价 curl "https://clob.polymarket.com/prices-history?market=&interval=1d&fidelity=60" ``` ### 8.4 监控一个鲸鱼地址 ```bash # 当前持仓 curl "https://data-api.polymarket.com/positions?user=0x...&sizeThreshold=1&limit=500&sortBy=CURRENT" # 历史成交 curl "https://data-api.polymarket.com/activity?user=0x...&type=TRADE&limit=500" # 订阅 User WebSocket 实时 trade/order ``` ### 8.5 找热门市场的 top 持有人 ```bash curl "https://data-api.polymarket.com/v1/market-positions?market=&status=OPEN&sortBy=TOTAL_PNL&sortDirection=DESC&limit=50" ``` --- ## 9. 注意事项 / 坑 1. **Gamma 的 `outcomes` / `outcomePrices` / `clobTokenIds` 字段是 JSON 字符串而非数组**,需 `json.loads()` 再用。 2. **不要用 `?q=...` 搜索**:`/events` 不支持自由文本,文档显式说"silently returns default ordering",请用 `/public-search` 或 slug。 3. **`tag_slug` 不稳定**:教程建议生产环境只用数值 `tag_id`。 4. **排序与标签同时过滤可能返回空**:tag 下市场太少 + `volume24hr desc` 时会空,需要 over-fetch 客户端再过滤。 5. **WebSocket 必须立刻发订阅**:连接后未立刻发订阅消息会被立刻断开。 6. **CLOB 价格用 token_id 不是 slug**:先 Gamma 拿 `clobTokenIds` 再查 CLOB。 7. **WSS 心跳**:Market/User 是**客户端发 PING**;Sports 是**服务端发 ping**。两者别搞反。 8. **`tick_size_change` 是做市关键事件**:tick 改了还用旧值会被拒单。 9. **`/markets` 在 CLOB 与 Gamma 两个端点都有**,含义不同: - `clob.polymarket.com/markets`:交易用的简化市场(limit 上限 100,需游标) - `gamma-api.polymarket.com/markets`:元数据 + 内嵌 markets(limit 上限 500,offset) 10. **地理限制**:某些地区会被 Cloudflare 屏蔽,必要时用代理。 --- ## 10. 常用分类/标签 ID 速查 | 分类 | Tag ID | |---|---| | Sports | 1 | | Politics | 2 | | Election | 3 | | Crypto | 21 | | Bitcoin | 100196 | | Ethereum | 100383 | | Pop Culture / Entertainment | (通过 `/tags` 动态查询) | | Middle East | 1432 | | NBA | 745 | | NFL | 450 | | Tennis | 864 | | Esports | 702 | | Soccer | 1059 | | EPL | 739 | | UCL | 2186 | 完整列表通过 `GET https://gamma-api.polymarket.com/tags?limit=500` 获取。