Files
my-polymarket-copytrader/polymarket_api_research.md

16 KiB
Raw Permalink Blame History

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 公开 / 鉴权 实时订单簿、成交、用户事件

官方 SDKPython (py-clob-client)TypeScript (@polymarket/clob-client)Rust (rs-clob-client)。第三方封装很多(polymarket-pandaspolybricks-sdkalmanak-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 — 市场唯一条件 ID0x + 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 1500,默认 20
offset 分页偏移
include_chat, include_template 是否包含聊天/模板字段

示例:

# 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_idtag_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_idasset_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=trueoutcomePrices 中某 outcome 价格 ≥ 0.99 即为赢家。PnL 模型:win = S*(1-p)/ploss = -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_idasset_idsidesizefee_rate_bpspricestatusmatch_timeoutcomeownermaker_addresstransaction_hashtrader_sidemaker_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 结算

订阅消息:

{"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 APICloudflare 前置):
    • 同一 IP ≤30 req/s 持续 → 安全
    • 100+ req/s 突发 → 偶发 429(重试可恢复)
    • 500 req/s 持续 → 限流 / 封禁 10–60s
    • 响应头 Cache-Control 通常 3060s
  • 推荐:单 fetcher 进程 + 本地 LRU 缓存(30s TTL),多个消费者读取本地副本
  • 大量拉取时建议加 1 fetcher × N consumers,避免多 fetcher 抢配额

8. 常用查询模式速查

8.1 找"现在最热"的市场

curl "https://gamma-api.polymarket.com/events?active=true&closed=false&order=volume24hr&ascending=false&limit=100"

8.2 查某个分类所有活跃市场

# 政治类(Politics tag = 2
curl "https://gamma-api.polymarket.com/events?tag_id=2&active=true&closed=false&order=volume&ascending=false"

8.3 拿单个市场的实时报价

# 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=<TOKEN_ID>"
# 3. 查历史价
curl "https://clob.polymarket.com/prices-history?market=<TOKEN_ID>&interval=1d&fidelity=60"

8.4 监控一个鲸鱼地址

# 当前持仓
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 持有人

curl "https://data-api.polymarket.com/v1/market-positions?market=<CONDITION_ID>&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 是客户端发 PINGSports 是服务端发 ping。两者别搞反。
  8. tick_size_change 是做市关键事件tick 改了还用旧值会被拒单。
  9. /markets 在 CLOB 与 Gamma 两个端点都有,含义不同:
    • clob.polymarket.com/markets:交易用的简化市场(limit 上限 100,需游标)
    • gamma-api.polymarket.com/markets:元数据 + 内嵌 marketslimit 上限 500offset
  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 获取。