Polymarket Bot Tutorial · 32章中18章
PolymarketにおけるUMAのdispute予測ボット:Optimistic Oracleの提案を検知し、dispute発生確率を予測し、dispute前後の価格の非対称性を活用し、dispute市場のデススパイラルを回避します。
この章の内容
UMAのOptimistic OracleはPolymarketのマーケットを解決し、disputeは発生前後に価格の異常を生みます。disputeの両側には取引可能なパターンがありますが、この戦略は運用が複雑で、利益をもたらしたボットよりも破壊したボットのほうが多いのが現実です。この章では、その実態を正直に解説します。
- UMA Optimistic Oracleの仕組み
- 提案をオンチェーンで検知する方法
- dispute予測指標(出来高、曖昧さ、履歴)
- dispute前の価格非対称性
- dispute後の取引セットアップ
- dispute市場で取引しないべきタイミング
- コード:UMAのproposed/disputedイベントを購読する
UMA Optimistic Oracleの仕組み
UMAのOptimistic Oracle(OO)は、Polymarketのdispute解決レイヤーです。すべてのマーケット解決はOOを通ります。ほとんどは争われることなく自動で確定します。争われたもの、つまりdisputeは24〜72時間の投票期間に入り、UMAトークン保有者が結果を決定します。
流れは次のとおりです。Polymarketのresolverが価格を提案します(0 = NOが勝利、1 = YESが勝利)。2時間のchallenge windowが経過し、誰もdisputeしなければ、その価格が確定し、CTFコントラクトが配当を分配します。誰かがdisputeすると、マーケットは投票ウィンドウに入り、UMA保有者が投票します。多数派が勝ちます。
ボットにとって重要なのは、ProposePrice(提案が入り、challenge windowが開く)とDisputePrice(disputeが提出され、投票期間が始まる)です。これらを購読して、マーケット解決の状態をリアルタイムで追跡します。
提案をオンチェーンで検知する方法
Polygon上のUMA OOコントラクトは、パラメータ(requester, identifier, timestamp, ancillaryData, proposer, proposedPrice)を持つProposePriceイベントを発行します。Polymarketの既知のrequesterアドレスでフィルタリングして、関連する提案だけに絞り込みます。
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予測指標(出来高、曖昧さ、履歴)
dispute前の3つのシグナルは、後に実際にdisputeが起きる確率と相関します。
- 総出来高:生涯出来高が$1Mを超えるマーケットは、小規模マーケットの4倍の確率でdisputeされます。賭け金が大きいほど、異議を申し立てるインセンティブが強くなります。
- 曖昧な文言: "or similar"、"officially confirmed"、あるいは複合条件(date AND specific outcome)を含むマーケットは、dispute率が高くなります。
- 同じイベントでの過去のdispute:以前の提案がすでにdisputeされて再提案された場合、2回目の提案は通常の2〜3倍の確率でdisputeされます。
ボットは、これらの特徴から「dispute確率」スコアを算出し、解決が近いマーケットでポジションを取るのを避けることができます。
dispute前の価格非対称性
disputeが起きそうな数時間前には、マーケット価格が非対称に動くことがよくあります。提案者がYESとした側は下落し(disputeでひっくり返される懸念があるため)、反対側は上昇します。
どちら向きにdisputeが決着するかについて方向感があるなら、この時間帯は取引可能です。リスクは、disputeが起きなかった場合、challenge windowが何事もなく閉じた瞬間に非対称性が反転し、価格が提案方向へ戻ることです。
率直に言えば、ほとんどのdispute前の非対称性トレードは負けトレードです。なぜなら、ほとんどのchallengeは元の提案に有利に解決するからです。この戦略が機能するのは、そのdisputeが維持される可能性について具体的な情報がある場合だけです。
dispute後の取引セットアップ
disputeが提出されると、マーケットは24〜72時間「宙ぶらりん」の状態で取引されます。dispute中であり、結果は投票で決まることが分かっている状態です。セットアップは2つあります。
UMAコンセンサスへの収束:disputeの決着シグナルが早期に出る場合(たとえば、著名なUMA投票者が公にどちらかの側につく)、価格はその決着に向かって動きます。UMAのDiscord / Twitterシグナルと価格アクションを監視するボットなら、この動きを30〜60%の確率で捉えられます。
ボラティリティ・ファーミング:宙ぶらりんの期間はスプレッドが広くなります。忍耐強いマーケットメイカーは、投票期間中に出入りする複数のトレーダーからスプレッドを回収できます。インベントリリスクは高いため、サイズはそれに合わせて抑えてください。
どちらも、自分のポジションに反する解決が本当に起こりうることを受け入れる必要があります。dispute期間中のインベントリは、最大でも半分サイズとして扱ってください。
dispute市場で取引しないべきタイミング
disputeトレードがデフォルトで間違いになる3つの状況があります。
- UMA特有の見解を持っていない。もし自分のエッジが「元の提案は正しそうに見える」だけなら、元の提案者に対する優位性はありませんし、disputeを出した側は逆の見方をしています。投票結果は予測不能なコイントスです。
- disputeが曖昧な文言に対するもの。UMAの投票者は通常、質問文を厳密に読む側につきます。マーケットが「by January 31」と言っていて、実際の出来事が2月1日に起きたなら、トレーダー全体の直感に関係なくUMAはNOで解決します。
- dispute前から在庫を持っている。宙ぶらりんの状態で既存ポジションに「ナンピン」するのは、典型的な資本破壊パターンです。保有を続けるか、退出するかのどちらかで、追加はしないでください。
コード:UMAのproposed/disputedイベントを購読する
参考:Polymarket requesterでフィルタしたUMA OOイベントへのWebSocket購読。
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)
パターンは、購読、デコード、アラートです。disputeにアルゴリズムで対応するのは高リスクなので、ボットの役割は通常、イベントを人間のレビュー担当者に提示することです。





