Polymarket Bot Tutorial · Chapter 18 of 32
باتهای پیشبینی dispute در UMA روی Polymarket: proposalهای Optimistic Oracle را شناسایی کنید، احتمال dispute را پیشبینی کنید، عدمتقارن قیمت قبل و بعد از dispute را exploit کنید، و از death spiral در بازارهای disputed دوری کنید.
این فصل چه چیزهایی را پوشش میدهد
Optimistic Oracle (OO) مربوط به UMA بازارهای Polymarket را resolve میکند، و disputeها قبل و بعد از رخ دادنشان anomalyهای قیمتی ایجاد میکنند. الگوهای قابل معامله در هر دو سمت dispute وجود دارند، اما این strategy از نظر عملیاتی پیچیده است و بیشتر از آنکه به botها غذا بدهد، آنها را سوزانده است. این فصل playbook صادقانه است.
- چگونه UMA Optimistic Oracle کار میکند
- تشخیص proposal روی-chain
- پیشبینیکنندههای dispute (volume، ambiguity، history)
- عدمتقارن قیمت قبل از dispute
- trade setupهای بعد از dispute
- چه زمانی نباید در بازارهای disputed معامله کرد
- Code: subscribe به رویدادهای proposed/disputed در UMA
چگونه UMA Optimistic Oracle کار میکند
Optimistic Oracle (OO) مربوط به UMA لایهی dispute resolution برای Polymarket است. هر resolution بازار از OO عبور میکند؛ بیشترشان بدون contest هستند و بهصورت خودکار settle میشوند. موارد contested - disputeها - یک دوره رأیگیری 24 تا 72 ساعته را فعال میکنند که طی آن token holderهای UMA درباره outcome تصمیم میگیرند.
چرخه کار اینگونه است: resolver در Polymarket یک price پیشنهاد میدهد (0 = NO برنده شد، 1 = YES برنده شد). بعد از یک window چالش 2 ساعته، اگر کسی dispute نکند، price نهایی میشود و قرارداد CTF payoutها را توزیع میکند. اگر کسی dispute کند، بازار وارد voting window میشود؛ holderهای UMA رأی میدهند و اکثریت برنده است.
برای یک bot، رویدادهای مرتبط ProposePrice (proposal ثبت شد، challenge window باز میشود) و DisputePrice (dispute ثبت شد، دوره رأیگیری آغاز میشود) هستند. برای track کردن وضعیت resolution بازار بهصورت real-time به اینها subscribe کنید.
تشخیص proposal روی-chain
قرارداد UMA OO روی Polygon یک رویداد ProposePrice با پارامترهای (requester, identifier, timestamp, ancillaryData, proposer, proposedPrice) emit میکند. برای محدود کردن به proposalهای مرتبط، روی آدرس requester شناختهشده Polymarket filter بگذارید.
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 دادهی JSON کدشده به hex است که question بازار را توصیف میکند. با decode کردن آن، شناسه بازار را بهدست میآورید که میتوانید با positionهای باز خود cross-reference کنید.
پیشبینیکنندههای dispute (volume، ambiguity، history)
سه سیگنال پیش از dispute با disputeهای واقعی بعدی همبستگی دارند.
- Total volume: بازارهایی با بیش از $1M در lifetime volume، 4 برابر نرخ بازارهای کوچک dispute میشوند. capital بیشتر در خطر = انگیزه بیشتر برای challenge.
- Ambiguous wording: هر بازاری که عبارتهایی مثل "or similar," "officially confirmed," یا شرطهای ترکیبی (date AND outcome خاص) داشته باشد، نرخ dispute بالاتری دارد.
- Past disputes on the same event: اگر یک proposal قبلی already disputed شده و دوباره پیشنهاد شده باشد، proposal دوم با نرخ 2 تا 3 برابر حالت عادی dispute میشود.
یک bot میتواند از این ویژگیها یک score برای "dispute probability" بسازد و در بازارهایی که نزدیک resolution هستند و از آستانه بالاترند، position نگیرد.
عدمتقارن قیمت قبل از dispute
در ساعتهای قبل از یک dispute محتمل، قیمت بازار اغلب حرکت نامتقارن نشان میدهد: سمتی که proposer آن را YES نامگذاری کرده پایین میآید (چون traderها میترسند dispute آن را برگرداند)، و سمت دیگر بالا میرود.
اگر دید directional درباره اینکه dispute به چه سمتی resolve میشود داشته باشید، این یک window قابل معامله است. ریسک: اگر dispute رخ ندهد، با بسته شدن بیدردسر challenge window عدمتقارن معکوس میشود و قیمتها به سمت proposed بازمیگردند.
صادقانه: بیشتر tradeهای pre-dispute asymmetry ضرر میدهند، چون بیشتر challengeها به نفع proposal اصلی resolve میشوند. این strategy فقط وقتی کار میکند که اطلاعات مشخصی درباره اینکه چرا این dispute احتمالاً sustained میماند داشته باشید.
trade setupهای بعد از dispute
بعد از ثبت dispute، بازار برای 24 تا 72 ساعت در حالت "limbo" معامله میشود - میدانیم disputed است، اما outcome قرار است رأیگیری شود. دو setup وجود دارد.
Convergence به UMA consensus: اگر resolution dispute زود signal شود (مثلاً یک UMA voter برجسته علناً سمت مشخصی را بگیرد)، قیمت به سمت آن resolution حرکت میکند. یک bot که سیگنالهای UMA Discord / Twitter + price action را رصد میکند میتواند 30 تا 60 درصد مواقع این را شکار کند.
Volatility farming: دورههای limbo spreadهای بزرگی دارند. یک market maker صبور میتواند در طول window رأیگیری از spread tax میان چندین trader که وارد و خارج میشوند درآمد کسب کند. inventory risk بالاست؛ size را متناسب تنظیم کنید.
هر دو نیاز دارند با احتمال واقعی resolve شدن بر خلاف position شما راحت باشید. inventory دوره dispute را حداکثر نصف-size در نظر بگیرید.
چه زمانی نباید در بازارهای disputed معامله کرد
سه وضعیت که در آن trade dispute بهطور پیشفرض اشتباه است.
- You do not have a UMA-specific view. اگر تنها edge شما این است که "proposal اصلی به نظرم درست میرسد"، هیچ برتریای نسبت به proposer اصلی ندارید - و کسی که dispute را ثبت کرده هم برعکسش را فکر میکند. نتیجه رأیگیری یک coin flip است که نمیتوانید پیشبینی کنید.
- The dispute is on an ambiguous wording. رأیدهندگان UMA معمولاً به strict-reading-of-the-question سمت میگیرند. اگر market گفته بود "by January 31" و رویداد در February 1 رخ داده، UMA صرفنظر از intuition جمع traderها، NO را resolve میکند.
- You hold inventory from before the dispute. اضافه کردن به position موجود برای "average down" در طول limbo، الگوی کلاسیک destruction سرمایه است. نگه دارید یا خارج شوید، هرگز اضافه نکنید.
Code: subscribe به رویدادهای proposed/disputed در UMA
Reference: subscription WebSocket به رویدادهای UMA OO، با filter بر اساس requester مربوط به Polymarket.
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)
الگو این است: subscribe، decode، alert. اقدام algorithmic روی disputeها ریسک بالایی دارد؛ کار bot معمولاً این است که رویداد را به یک reviewer انسانی منتقل کند.





