全部文章
指南PythonSDKPolymarket API

2026 年的 Polymarket Python SDK(以及如何迁移出 py-clob-client)

如果你的代码还在从 py_clob_client 导入 ClobClient,那它就建立在一个已被取代的包之上,AI 助手为你写的大部分 Polymarket 代码也是如此。下面介绍当前的 SDK 以及如何迁移。

阅读约 10 分钟

要点

Polymarket 现在提供统一 SDK:Python 版是 polymarket-client,TypeScript 版是 @polymarket/client。它们取代了 py-clob-client、@polymarket/clob-client-v2、@polymarket/builder-relayer-client 和 @polymarket/builder-signing-sdk。统一的 Rust SDK 正在开发中。

这比一次普通的版本升级更重要,原因只有一个:互联网上几乎所有的 Polymarket 代码示例都早于它。博客文章、Stack Overflow 回答、GitHub 示例,以及(因为是用这些材料训练出来的)当你让 AI 助手写一个 Polymarket 机器人时它写出的代码。如果你发现自己在调试根本不存在的导入,这就是原因。

到底变了什么

旧的方式是每个 Polymarket 服务一个客户端。你导入一个 CLOB 客户端处理订单簿,用原始 HTTP 调用 Gamma 发现市场,单独请求 Data API 获取持仓,需要 Relayer 交易时还要引入一个 builder-signing 包。四套心智模型,四种错误格式,四种分页方式。

统一 SDK 把这些合并成一个覆盖所有接口的客户端。

旧客户端统一 SDK
包多个,每个服务一个一个
Polymarket 接口各服务专用的 API一个客户端接口
数据模型原始 JSON 字典类型化模型
分页因 API 而异一个统一的分页器
认证和签名每个客户端各自实现SDK 辅助函数
实时数据分别连接每个 WebSocketsubscribe() 合并数据流

安装

pip install polymarket-client
# uv add polymarket-client
# poetry add polymarket-client

包名和导入名不同

你安装的是 polymarket-client,但导入的是 polymarket。很多人在第一行就栽了跟头,这也是识别从未运行过的生成代码的可靠方法:如果一段代码写的是 import polymarket_client,那就没人执行过它。

四个客户端:慎重选择

客户端公开数据交易实时数据适用于
AsyncPublicClient是否是机器人、数据采集程序
AsyncSecureClient是是是交易机器人
PublicClient是否否脚本、notebook
SecureClient是是否执行交易的脚本

实时数据仅支持异步

PublicClient 和 SecureClient 没有实现 subscribe()。如果你打算流式接收订单簿更新(任何认真的机器人都应该这样做),就需要用其中一个异步客户端。一开始选了同步客户端,后来才发现这一点,会带来一次恼人的重构。

import asyncio
from polymarket import AsyncPublicClient


async def main() -> None:
    async with AsyncPublicClient() as client:
        pages = client.list_markets(closed=False)
        first = await pages.first_page()
        for market in first.items:
            print(market.slug)


asyncio.run(main())

公开数据不需要凭证,所以在引入密钥之前,尽可能对着 AsyncPublicClient 构建和测试一切。市场发现、解析、分页、信号生成和退避都可以在没有任何风险的情况下检验。

分页

所有列表方法共用一个分页器接口。根据你是否关心页面边界,有三种使用方式:

pages = client.list_markets(closed=False, page_size=10)

# 1. Page at a time — use this when you need to control pacing
#    against the tight /markets rate limit (300 req / 10s).
async for page in pages:
    for market in page.items:
        ...

# 2. Item at a time, boundaries ignored.
async for market in pages.iter_items():
    ...

# 3. Manual, resumable.
page = await pages.first_page()
if page.next_cursor:
    nxt = await pages.from_cursor(page.next_cursor).first_page()

next_cursor 是不透明的,请原样存储

不要解析、解码或自行构造游标。如果你想稍后恢复一次长时间扫描,就把这个字符串原样保存;省略它则从头开始。自己构造游标属于那种在编码方式改变之前都能用的做法。

类型化模型

方法返回的是真正的类型而不是字典,从顶层包导出:

from polymarket import Event, Market, OrderBook, PriceHistoryPoint

这是最不起眼的改进,却可能是价值最高的。在旧客户端下,一个被重命名或缺失的字段,会在运行时以 KeyError 的形式出现在你策略循环的深处,往往发生在生产环境,往往发生在持仓期间。类型化模型把这种失败移到了它该在的地方。

实时订阅

subscribe() 把多个数据流合并成一个类型化的事件流,相比手动管理多个 WebSocket 连接,这是实实在在的改进。

from polymarket.streams import MarketSpec, SportsSpec

async with await client.subscribe(
    [MarketSpec(token_ids=[token_id]), SportsSpec()],
) as stream:
    async for event in stream:
        # MarketBookEvent | MarketPriceChangeEvent
        # | MarketLastTradePriceEvent | MarketTickSizeChangeEvent
        # | MarketBestBidAskEvent | NewMarketEvent
        # | MarketResolvedEvent | SportsEvent
        handle(event)

SDK 会处理你原本需要自己实现的心跳、帧和重连,包括在原始连接上每 10 秒发送一次 PING 的要求。详见 WebSocket 指南。

下单

market = await client.get_market(slug="<market-slug>")
token_id = market.outcomes.yes.token_id
assert token_id is not None

response = await client.place_market_order(
    token_id=token_id,
    side="BUY",
    amount="10",     # pUSD to spend, not shares to buy
)

if not response.ok:
    raise RuntimeError(response.message)

# Settlement is on-chain and asynchronous.
hashes = await client.wait_for_order_fill_settlement(response)

# Reconcile rather than assuming.
page = await client.list_positions(market=[market.condition_id]).first_page()
position = next((p for p in page.items if p.token_id == token_id), None)

amount 是花费金额,不是数量

place_market_order(amount="10") 的意思是最多花费 10 pUSD,而不是买入 10 份。在一份价格为 0.20 的合约上,这大约是 50 份。理解错了这一点,很容易建立一个比预期大五倍的仓位。

从 py-clob-client 迁移

  1. 盘点每一个 Polymarket 调用,包括对 Gamma 和 Data API 的原始 requests 调用。它们也在迁移范围内:统一 SDK 覆盖了它们,把它们并进来就是大部分的收益。
  2. 安装 polymarket-client,移除旧包。为了逐步迁移而同时保留两者,容易导入错误的 client 符号。
  3. 替换客户端的构造方式。一个 AsyncSecureClient.create(...) 取代了旧的各服务客户端以及它们各自的凭证处理。
  4. 把字典访问改为属性访问。market["condition_id"] 变成 market.condition_id。很繁琐,但这正是类型检查器开始发挥价值的地方。
  5. 重写分页,改用分页器接口,而不是手动的 offset 或游标循环。
  6. 用 subscribe() 替换手写的 WebSocket 代码,并删除你的心跳和重连逻辑。
  7. 先重新运行只读路径,对着公开客户端运行,然后再让任何东西下单。

TypeScript 提供签名者适配器

TypeScript SDK 提供了 Viem、Privy 和 Ethers v5 的适配器,所以你可以接入现有的钱包库,而不必实现 CLOB 专用的签名逻辑。如果你之前基于旧的 builder-signing 包维护着一个自定义签名者,那段代码现在可以删掉了。

为什么你的 AI 助手会写错

值得直接说一说,因为很多人就是因此来到这里的。让一个 LLM 写 Polymarket 的 Python 代码,你经常会得到 py_clob_client 导入、ClobClient(...) 构造和 OrderArgs 对象。模型并没有出故障:它只是在复现它见过的绝大多数 Polymarket 代码,而这些代码都早于统一 SDK。

  • 先检查导入行。from polymarket import ... 是当前的写法;from py_clob_client... 不是。
  • 把当前文档粘贴到上下文中。Polymarket 在 docs.polymarket.com/llms.txt 发布了机器可读的 Markdown,每个页面都有 .md 版本。给模型提供真实的文档,胜过和它争论。
  • 不要相信那些自信满满却跑不起来的代码。生成的代码经常把新旧 API 混在一起,拼出一个从未存在过的东西。

同样的问题也存在于数据提供商。我们发布了 llms.txt、llms-full.txt 和一份 OpenAPI 规范,并允许 AI 爬虫访问,正是为了让助手无需猜测就能写出正确的 PolyTest 集成。有些提供商屏蔽了这些爬虫,这是合理的选择,但意味着你的助手会自己编造他们的 API 接口。

SDK 仍然做不到的事

统一 SDK 是一个好得多的 Polymarket API 接口。但它并不会改变这些 API 所包含的内容,而机器人开发者最常想要的东西并不在其中。

没有历史订单簿。client.get_market() 会返回已结算市场的元数据,但它的订单簿已经没了:/book 返回 404,prices-history 只保留大约每分钟一个点。没有任何 SDK 方法、套餐或凭证能找回订单簿。

要回测,你需要在市场运行期间记录的快照。PolyTest 为加密货币 Up/Down 市场提供这些快照:240M+ 条时点快照,每边 8 档深度,亚秒级时间戳,已结算的市场也会保留。它是一个普通的 REST API,使用 X-API-Key 请求头,可以直接放进与 SDK 相同的异步代码中。免费开始,或阅读如何构建机器人了解完整流程。

常见问题

2026 年官方的 Polymarket Python SDK 是什么?
官方 Python SDK 是 polymarket-client,用 pip install polymarket-client 安装,以 polymarket 导入。它是统一 SDK,通过一个客户端接口覆盖 CLOB、Gamma 和 Data API 以及实时数据流,并取代了 py-clob-client。TypeScript 对应的是 @polymarket/client,统一的 Rust SDK 正在开发中。
py-clob-client 已经弃用了吗?
它已被统一的 polymarket-client SDK 取代,一同被取代的还有 TypeScript 包 @polymarket/clob-client-v2、@polymarket/builder-relayer-client 和 @polymarket/builder-signing-sdk。Polymarket 发布了迁移指南,用于迁移现有集成。大多数教程和 AI 生成的代码仍然引用旧包,因为它们远早于统一 SDK。
交易机器人应该用哪个 Polymarket Python 客户端?
用 AsyncSecureClient。一共有四个客户端:AsyncPublicClient 和 PublicClient 用于公开数据,AsyncSecureClient 和 SecureClient 用于交易和账户访问。实时订阅仅支持异步,同步客户端没有实现 subscribe(),所以任何需要流式接收订单簿更新的机器人都需要异步客户端。在引入凭证之前,先对着 AsyncPublicClient 构建和测试。
如何用 Polymarket Python SDK 对结果分页?
列表方法返回一个分页器。直接迭代它可以逐页控制;调用 iter_items() 可以忽略页面边界逐条迭代记录;也可以用 first_page() 和 from_cursor() 进行可恢复的手动扫描。next_cursor 的值是不透明的,所以要原样存储,而不是解析或自行构造;省略它则从第一页开始。
为什么 ChatGPT 或 Claude 生成的 Polymarket 代码跑不起来?
因为训练数据中绝大多数 Polymarket 代码都早于统一 SDK,模型倾向于生成 py_clob_client 导入、ClobClient 构造和 OrderArgs 对象。先检查导入行:from polymarket import 是当前的写法,from py_clob_client 不是。Polymarket 在 docs.polymarket.com/llms.txt 发布了机器可读的文档,每个页面都有 .md 版本,所以把当前文档粘贴到上下文中,比反复纠正模型更有效。
Polymarket SDK 能获取历史订单簿数据吗?
不能。SDK 是 Polymarket API 的接口,无法返回这些 API 本身没有的数据。已结算市场的元数据可以获取,但它的订单簿返回 404,价格历史只保留大约每分钟一个点。回测需要由第三方在市场运行期间记录的时点快照。

获取 Polymarket 不保留的历史数据

PolyTest 在 Polymarket 加密货币 Up/Down 市场运行期间实时记录:240M+ 条快照,包含 8 档订单簿深度、亚秒级时间戳,并保留已结算的市场。从 3 天免费试用开始。

继续阅读