Polymarket Bot 教程 · 第 18 章,共 32 章
Polymarket 上的 UMA dispute prediction bots:检测 Optimistic Oracle proposals,预测 dispute 发生概率,利用 dispute 前后价格不对称,并避免 disputed-market 的死亡螺旋。
本章内容
UMA 的 Optimistic Oracle 为 Polymarket 市场提供结算,disputes 会在触发前后造成价格异常。争议两侧都存在可交易模式,但这个策略在操作上很复杂,已经让比它喂饱的 bot 更多地亏损了。本章会给出诚实的实战指南。
- UMA Optimistic Oracle 的工作原理
- 如何在链上检测 proposal
- dispute 预测信号(volume、歧义、历史)
- dispute 前价格不对称
- dispute 后的交易设置
- 什么时候不应交易 disputed markets
- 代码:订阅 UMA proposed/disputed events
UMA Optimistic Oracle 的工作原理
UMA 的 Optimistic Oracle(OO)是 Polymarket 的 dispute resolution 层。每个市场的结算都要经过 OO;大多数都不会被争议,并会自动结算。被争议的那些-disputes-会触发一个 24-72 小时的 voting period,期间由 UMA token holders 决定结果。
生命周期如下:Polymarket 的 resolver 提议一个价格(0 = NO 胜出,1 = YES 胜出)。经过 2 小时的 challenge window 后,如果没有人 dispute,价格就会最终确定,CTF 合约分发 payout。如果有人 dispute,市场会进入 voting window;UMA holders 进行投票,少数服从多数。
对于 bot 来说,相关事件是 ProposePrice(proposal 已进入,challenge window 打开)和 DisputePrice(dispute 已提交,投票期开始)。订阅这些事件,就能实时跟踪市场结算状态。
如何在链上检测 proposal
Polygon 上的 UMA OO 合约会发出一个 ProposePrice 事件,参数为 (requester, identifier, timestamp, ancillaryData, proposer, proposedPrice)。通过 Polymarket 已知的 requester 地址进行过滤,可以将范围缩小到相关 proposals。
POLY_REQUESTER = "0x..." # Polymarket Adjudicator
filt = oo_contract.events.ProposePrice.create_filter(
fromBlock="latest",
argument_filters={"requester": POLY_REQUESTER}
)
for event in filt.get_new_entries():
market_id = decode_ancillary(event.args.ancillaryData)
proposed = "YES" if event.args.proposedPrice == 1e18 else "NO"
print(f"PROPOSE: market {market_id} → {proposed}")
ancillaryData 字段是用 hex 编码的 JSON,用来描述市场问题。对其解码后,你就能得到市场标识,并将其与自己的持仓进行交叉比对。
dispute 预测信号(volume、歧义、历史)
三个 dispute 前信号与后续真实 disputes 有相关性。
- 总 volume:生命周期 volume 超过 $1M 的市场,dispute 率是小型市场的 4 倍。涉及的资本越多,越有动力去 challenge。
- 措辞歧义:任何包含“or similar”、“officially confirmed”,或复合条件(日期 AND 特定结果)的市场,dispute 率都会更高。
- 同一事件的历史 disputes:如果早先的 proposal 已经被 dispute 并重新提议,那么第二次 proposal 的 dispute 率是正常水平的 2-3 倍。
bot 可以基于这些特征计算一个“dispute probability”分数,并在接近结算时避开超过阈值的市场持仓。
dispute 前价格不对称
在高概率 dispute 发生前的几小时里,市场价格往往会出现不对称移动:proposer 指定为 YES 的那一侧会下跌(因为交易者担心 dispute 会把结果翻转),另一侧则会上涨。
如果你对 dispute 最终会如何裁定有方向性判断,这就是一个可交易窗口。风险在于:如果 dispute 没有发生,当 challenge window 平静关闭后,这种不对称会反向,价格会迅速回到 proposal 方向。
诚实地说:大多数 dispute 前不对称交易都是亏损的,因为大多数 challenge 最终都会支持原始 proposal。只有在你掌握了为什么这个 dispute 很可能会被维持的具体信息时,这个策略才有效。
dispute 后的交易设置
dispute 一旦提交,市场就会在 24-72 小时内处于“limbo”状态-已知存在 dispute,但结果要靠投票决定。这里有两种设置。
向 UMA consensus 收敛:如果 dispute resolution 很早就有信号(例如某位知名 UMA voter 公开站队),价格会朝那个结果移动。监控 UMA Discord / Twitter 信号 + 价格行为的 bot,有 30-60% 的概率能抓到这一段。
波动 farming:limbo 期间价差很宽。一个有耐心的 market maker 可以在 voting window 内随着多个 trader 进出反复赚取 spread tax。库存风险很高;仓位大小要相应控制。
这两种方式都要求你能够接受结果可能与自己的仓位相反。把 dispute 期间的 inventory 看作最多半仓。
什么时候不应交易 disputed markets
以下三种情况里,dispute 交易默认就是错的。
- 你没有 UMA 专属观点。如果你唯一的优势只是“我觉得原始 proposal 看起来更合理”,那你并没有比原始 proposer 更强的优势-而 dispute 发起者恰好持相反观点。投票结果对你来说就是不可预测的抛硬币。
- dispute 针对的是措辞歧义。UMA voters 通常会站在“严格按问题字面意思理解”的一边。如果市场写的是“by January 31”,而事件发生在 2 月 1 日,那么无论交易者群体直觉如何,UMA 都会判定为 NO。
- 你在 dispute 之前就持有 inventory。在 limbo 期间通过“摊薄成本”继续加仓,是典型的资本毁灭模式。持有或退出,绝不要加仓。
代码:订阅 UMA proposed/disputed events
参考:基于 WebSocket 订阅 UMA OO events,并通过 Polymarket requester 过滤。
from web3 import Web3
w3 = Web3(Web3.WebsocketProvider(POLYGON_WSS))
oo = w3.eth.contract(address=UMA_OO_ADDR, abi=UMA_OO_ABI)
POLY = "0x...".lower()
dispute_filter = oo.events.DisputePrice.create_filter(fromBlock="latest")
propose_filter = oo.events.ProposePrice.create_filter(fromBlock="latest")
while True:
for event in dispute_filter.get_new_entries():
if event.args.requester.lower() == POLY:
on_dispute(event)
for event in propose_filter.get_new_entries():
if event.args.requester.lower() == POLY:
on_propose(event)
time.sleep(2)
def on_dispute(event):
market_q = decode_ancillary_to_question(event.args.ancillaryData)
send_telegram(f"DISPUTE: {market_q}")
# If we hold a position in this market, alert + consider exit
if market_q in our_positions:
flag_position_for_review(market_q)
模式就是:订阅、解码、告警。对 disputes 进行算法化操作风险很高;bot 的职责通常只是把事件呈现给人工审核者。





