PolyMarket 预测市场是如何运转的01
PolyMarket 预测市场研究
最近预测市场开始流行起来了。
其实自己的感悟是,这个世界的很多玩法本质上都没有什么改变, 但是这种游戏的方式却是一直在改变。
说是调用群体的智慧,对未来的事件进行预测,但是我理解博彩公司做的也是这件事情,用户下赌注,猜测某个事件,
只不过他们给到的是一个结果,是一个理论上的概率,这中间的过程都是不透明的。
1. 传统博彩的玩法
注: 这篇文章,并不鼓励大家参与赌,下面的案例是用于说明和展示。
首先可以先看一场比赛的赔率,赔率在每一场比赛中这里都有展示,比如利雅得胜利队 vs 阿尔索拉,这里的赔率,就代表如果放一块钱进去,对应如果赢的话,能够拿到的金额数量。
这个是一个经典的主客平的赔率,同时投入1美元,利雅得胜利拿到1.15美元,平局的话,获得6.6美元,阿尔索拉胜利的话,获得13美元。
公式很简单, 概率为赔率的倒数
隐含概率 ≈ 1 / 赔率
所有
- 主胜, 1/1.15 = 0.8696
- 平局, 1/6.6=0.1515
- 客胜, 1/13 =0.0769
求和得到 0.8696 + 0.1515 + 0.0769 =1.098
最终结果为什么会大于一呢, 因为剩下的 0.098 ,大概 9.8% 这部分多出来的是赌场抽的水的比例。
所以庄家盘本身承担赔率的提供,以及如果单场比赛全被玩家赌中,钱被他们赚走的风险, 所以 他们不在乎一常比赛的赢和输,
赌场的思维是要留住这些用户留住这些玩家,这样才能长期的稳定的赚钱。
博彩公司给出的赔率是专家预测 和投注者共识的联合作用的结果,作为一个没有任何内幕消息的,如果把机会压在单次预测上,没有什么理由相信自己比他们更厉害呀。
2.PolyMarket 的玩法
这个时候 问题出来了,传统的方式都是菠菜,公司自己去定赔赔率,自己定水线(利润)。
最终玩家的对手方式平台,如果站在平台的角度,平台肯定是不会亏的,羊毛来自羊身上。
PolyMarket 的创新在于,用户的对手方 从平台转变为用户自身,当前的概率是由用户用自己的真金白银投票的一个结果。
把概率变为一种资产,对一件事情的判断,正确本身也是非常有价值的。
继续这里从Fed 联邦二月份的降息结果来看,按照当下的实时概率来看,降息50个基点的概率大概是1.6%,反之,如果二月份不降西50个基点的概率是98.5%,两个概率之和是1.001。
理想状态,两份概率之和应该 = 1
P(Yes)+P(No)=1
多出的0.001% 来源于两边统计的都是卖方的ask的价格,都是两边的最贵的价格。
Polymarket 在交易中是不抽水的,所以这一部分的Spread 价差,就是在市场中 做LP 的收益的核心来源。
预测收益代币
购买的价格,也是严格的按照赔率来的,比如这个25基点下调的概率是12%,那么我想买100个shares 的价格,就是100 * 0.12 = 12 USD, 如果最终事件落定,我会真的在这个事件结束的时刻, 收到 100 USD
交易属性
Polymarket 用户和用户做对手盘,在持有这个仓位的周期中都是可以进行交易的。
如果由于突发其他事件影响这件事情,造成我的这个事件(比如, 2月降息的可能性 )突然变高,那么这个shares 代币的价格,则会突然上涨(因为买量变得更大更多了)
反过来也是一样, 可能性变得越来越越低,那么手中的shares 价格,即代表用户手中的仓位,也是突然骤降。
3. 像庖丁一样去解Polymarket
看一个项目我们不能只看表面,接下来这个章节,我们从如何 How to build a Polymarket的角度来分析, 这个项目是怎么一点点搭起来的。
前面一个章节,我们从用户的视角是去看,去玩,接下来这个章节就是从开发者的角度,如何搭建一个Polymarket 的预测市场。

3.1 订单的生命周期
充值钱进来后,用户在前端这里进行交互,直接使用EIP712 签名,下了一个订单,这个订单走到了我的后台,后台来判断这个订单是限价单,还是市价单。
限价单,会放到订单中来做排序,市价单,会被撮合引擎直接撮合,然后执行成交,成交之后,这个结果会被记录,成交后的积累会被统计到数据库。
用户拿到这些 yes / no 的仓位凭证,等待事件结束,Oracle 向系统报告结果,等待仲裁。
如果用户的仓位结果正确无误,这些结果会被放到链上来做最终的Settlement ,最终预测成功的用户得到对应的奖励。
3.2 不同层的作用与模块拆分
如上的图所示,把整个项目的层次分开来,获得不同层的,不同模块的用户服务。
-
用户层
用户钱包对接,用户充值的模板,钱包托管钱包的逻辑, 这里使用的
magic.link来进行聚合的 -
前端层
前端就包括当前所有的这些市场数据展示, 实时数据的WSS 方式进行推送,用户签名之后,订单的生成,自己仓位的各种Dashboard界面
-
后台 API层
这层API需要聚合很多中间件,IP限制,用户认证,后台接口防刷,对外API-Key的管理,Market 接口数据的处理,订单簿接口的处理
-
撮合引擎层
撮合引擎,是整个预测项目的核心,这里包括后台用户订单进来的验证逻辑,匹配错误逻辑,成交后状态仓位更新的逻辑,订单风险控制,以及真实成交后交易的记录,对外LP可以接入的流动性管理。
-
存储层
为了更高效处理这些订单, 缓存是非常必要的,内存效率是不够的,所以需要缓存来处理部分订单簿,之后 订单完成之后,需要向数据库里面进行持久化更新,这些更新后的数据还需要一个Relaye r服务,来向链上同 步这些状态
- 智能合约与链层
最终这些数据要上链,智能合约要处理Relayer 提交上来的交割逻辑,以及Oracle 要处理最终事件解决后,价值分发的逻辑。
3.3 前端层
直接打开F12,就可以看到在前端展示后端所有后台的接口的数据。
前端这一层,主要做订单的构造和订单的展示,比如这一个接口https://polymarket.com/_next/data/BZrpuHvjUrPs-p4TCbw6c/index.json 这里面就封装了,一个个的具体的event
每一个Event 里面有多个market, 这个market 也就是 一个Event 中不同 选择,每个market 的独立标识符是conditionId 。
这个里面最重要的就是字段就是 clob 的tokenId , 这个就是真实的买卖的代币的token id ,包括之后调用接口我们都需要和 tokenId 打交道。
订单构造很简单,在选择自己想要的限价单的价格和对应的数量就可以下单,下单的过程是不上链的,

3.4. 后台接口层
后台接口层,是非常重要的。
首先订单进来,验证用户的签名和参数,防止无效的订单进入系统, 包括用户的额检查和单位检查, 防止系统被被黑客攻击,并且要做数据的聚合,最终构造完整的接口给到前端用户。
这些接口,都可以在Developer Docs (https://docs.polymarket.com/quickstart/introduction/main) 这里找到,这里既有市场的接口数据,也有订单的API, 和相关的不同语言的sdk,以供用户可以方便的和系统交互。
举几个例子
Auth 相关
const client = new ClobClient(
HOST,
CHAIN_ID,
signer
);
// 构造Clob Client, 使用Signer 生成对应的APIKey, API Secret和passphrase
const apiCreds = await client.createOrDeriveApiKey();
市场相关
这个接口进行查询, 可以查到这个市场的Detail 的信息
const conditionID = "0x17815081230e3b9c78b098162c33b1ffa68c4ec29c123d3d14989599e0c2e113"
const market = await client.getMarket(conditionID)
{
enable_order_book: true,
active: true,
closed: false,
archived: false,
condition_id: '0x17815081230e3b9c78b098162c33b1ffa68c4ec29c123d3d14989599e0c2e113',
question: 'Fed decreases interest rates by 50+ bps after January 2026 meeting?',
tokens: [
{
token_id: '11862165566757345985240476164489718219056735011698825377388402888080786399275',
outcome: 'Yes',
price: 0.0155,
winner: false
},
{
token_id: '71478852790279095447182996049071040792010759617668969799049179229104800573786',
outcome: 'No',
price: 0.9845,
winner: false
}
]
...
}
我们继续查询, 根据这个tokenId 可以拿到这个订单簿的各种信息
const tokenId = "11862165566757345985240476164489718219056735011698825377388402888080786399275"
const book = await client.getOrderBook(tokenId)
从下面的API拿到的订单簿结果,和页面展示的数据可以看到
两边的数据是一致。
{
market: '0x17815081230e3b9c78b098162c33b1ffa68c4ec29c123d3d14989599e0c2e113',
asset_id: '11862165566757345985240476164489718219056735011698825377388402888080786399275',
timestamp: '1766592519469',
hash: 'd4fb542b4fcb53d57eccbd1d09a4224c77f21755',
bids: [
{ price: '0.001', size: '4675420.53' },
---
{ price: '0.015', size: '323321.32' }
],
asks: [
{ price: '0.999', size: '11027226.28' },
---
{ price: '0.016', size: '375903.84' }
],
min_order_size: '5',
tick_size: '0.001',
neg_risk: true
}

订单相关
其实API给到我们另外一个更重要的作用,我们可以直接在这些接口上操纵我们的订单。
下面是我写的例子
const signatureType = 2; // 说明我使用的是POLY_GNOSIS_SAFE 钱包来操作订单的
let clobClient = new ClobClient(host, 137, signer, await creds, signatureType, funder);
// 订单查询, 当前查询出来我当前的所有的订单信息
const openOrders = await clobClient.getOpenOrders();
// 订单历史, 打印我当前的交互的历史
const trades = await clobClient.getTrades();
// 用户下单
const tokenId = "47417397531146322654664798599881734644831475868113880548085177510038074601189"
// 用户撤单 Cancel order, 指定刚才下的订单Id
const orderId = "0x6f72ae3bb430a945b773405c4e65a582722a90471d8f6c01993de853afb21ed9"
const cancelResponse = await clobClient.cancelOrder({orderID: orderId})
// 用户批量 Calcel Order ,批量Cancel order 会把上面的所有的限价单,全部cancel掉
const cancelAllResponse = await clobClient.cancelAll();

3.5 撮合引擎层
接下来到了,整个系统最神秘,也是最高效的部分了。
其实,真正检验这个系统高效,还是在2024 年总统的预测上面,能够承受10万+ TPS,交易处理速度,说明PolyMarket 的处理效率是非常高效,也是非常稳的。
其实,Poly Market之前的价格也是放在链上, 最早也是LMSR(Logarithmic Market Scoring Rule) 类似AMM 的架构,所有的买卖都直接对应的交易的AMM合约,进行交互。但是这样的问题是,效率很低。
之后系统慢慢迭代,现在已经变成了完全链下中心化的撮合,这样对用户来说是非常高效的,当然这样的架构,风险也是有的,这套撮合系统目前对用户来看是个黑盒,社区里面有很多问自己订单的问题。
所以接下来一篇文章,目的就是更深密度的去研究并build这个撮合系统,一个好的系统要符合这些条件
- 低延迟(这个不用说了,重中之重,不可能说,用户下个单需要等几秒才上链)
- 高频HFT,效率很重要
- 复杂的撮合需求(FOK FAK GTC GTD)这些订单处理的需求
3.6 区块链层
这块链层是整个系统中唯一不可回滚的部分。
最终事件收到Oracle 裁决,并得到结果,胜出的Outcome Token会被对称有价值的代币,并按照对应的赔率反馈给用户价值,而失败的仓位,则永久失去了价格。
目前链上没有撮合逻辑,脸上只有可信的Relayer提交的 交割逻辑,最终结算完成,任何链下数据就没有意义了。
结尾
这篇文章传统预测玩法,到当前预测市场方法,到技术上去实现和交互这些逻辑。
但是真正核心的部分,撮合系统的设计,各种订单的复杂需求(Fill or Kill , Fill And Kill, Good-Til-Cancelled , Good-Til-Date order),和具体的Oracle 设计,合约代码编写, 这些都没有很详细的编辑。
这些模块对放在接下来一篇文章去编写, 包括核心的订单簿数据结构和架构设计这些,链下-> 链上的数据一致性,Oracle 周期,安全性的处理。
其实用户视角的预测市场并不复杂,但是真正想做一个高效安全的系统,不止是简单的买Yes/No 代币那么简单,
敬请期待。