Polymarket Bot Tutorial · บทที่ 18 จาก 32
บอททำนายข้อพิพาท UMA บน Polymarket: ตรวจจับข้อเสนอ Optimistic Oracle, ทำนายความน่าจะเป็นของการโต้แย้ง, ใช้ประโยชน์จากความไม่สมมาตรของราคาก่อนและหลังการโต้แย้ง, และหลีกเลี่ยงวงจรมรณะของตลาดที่ถูกโต้แย้ง
บทนี้ครอบคลุมอะไรบ้าง
UMA's Optimistic Oracle เป็นกลไกที่ใช้ตัดสินตลาดของ Polymarket และเมื่อเกิดข้อพิพาทจะทำให้เกิดความผิดปกติของราคาก่อนและหลังเหตุการณ์นั้น รูปแบบการเทรดมีอยู่ทั้งสองฝั่งของการโต้แย้ง แต่กลยุทธ์นี้มีความซับซ้อนเชิงปฏิบัติการสูง และทำให้บอทพังมาเยอะกว่าที่เคยทำกำไรได้ บทนี้คือ playbook แบบตรงไปตรงมา
- UMA Optimistic Oracle ทำงานอย่างไร
- การตรวจจับ proposal บน-chain
- ตัวทำนายการโต้แย้ง (volume, ความกำกวม, ประวัติ)
- ความไม่สมมาตรของราคาก่อน dispute
- รูปแบบการเทรดหลัง dispute
- เมื่อไม่ควรเทรดตลาดที่ถูกโต้แย้ง
- Code: subscribe ไปที่ event proposed/disputed ของ UMA
UMA Optimistic Oracle ทำงานอย่างไร
UMA's Optimistic Oracle (OO) คือเลเยอร์สำหรับการตัดสินข้อพิพาทของ Polymarket การปิดตลาดทุกครั้งต้องผ่าน OO; ส่วนใหญ่ไม่มีการคัดค้านและจะ settle อัตโนมัติ รายที่มีการคัดค้าน-disputes-จะเข้าสู่ช่วงโหวต 24-72 ชั่วโมง ซึ่งผู้ถือโทเคน UMA จะเป็นผู้ตัดสินผลลัพธ์
ลำดับเหตุการณ์คือ: resolver ของ Polymarket เสนอราคา (0 = NO ชนะ, 1 = YES ชนะ) หลังจากช่วง challenge window 2 ชั่วโมง หากไม่มีใครโต้แย้ง ราคาจะถูก final และสัญญา CTF จะกระจายเงินรางวัล หากมีคน dispute ตลาดจะเข้าสู่ voting window และผู้ถือ UMA จะลงคะแนน เสียงข้างมากเป็นผู้ชนะ
สำหรับบอท เหตุการณ์ที่สำคัญคือ ProposePrice (มีการยื่นข้อเสนอ, challenge window เปิด) และ DisputePrice (มีการยื่น dispute, ช่วงโหวตเริ่มต้น) ให้ subscribe เหตุการณ์เหล่านี้เพื่อติดตามสถานะการปิดตลาดแบบเรียลไทม์
การตรวจจับ proposal บน-chain
สัญญา UMA OO บน Polygon จะส่ง event ProposePrice พร้อมพารามิเตอร์ (requester, identifier, timestamp, ancillaryData, proposer, proposedPrice) ให้กรองด้วย address requester ที่ Polymarket รู้จักไว้แล้วเพื่อจำกัดเฉพาะข้อเสนอที่เกี่ยวข้อง
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 ซึ่งอธิบายคำถามของตลาด เมื่อถอดรหัสจะได้ market identifier ที่นำไป cross-reference กับตำแหน่งที่คุณถืออยู่ได้
ตัวทำนาย dispute (volume, ความกำกวม, ประวัติ)
สัญญาณก่อน dispute สามอย่างมีความสัมพันธ์กับการเกิด dispute จริงในภายหลัง
- Total volume: ตลาดที่มี volume ตลอดอายุเกิน > $1M จะถูกโต้แย้งในอัตราที่สูงกว่าตลาดเล็ก 4 เท่า ยิ่งมีเงินเดิมพันมาก = ยิ่งมีแรงจูงใจให้คัดค้าน
- Ambiguous wording: ตลาดที่มีคำว่า "or similar," "officially confirmed," หรือเงื่อนไขแบบผสม (วันที่ AND ผลลัพธ์เฉพาะ) จะมีอัตราการ dispute สูงขึ้น
- Past disputes on the same event: ถ้าข้อเสนอครั้งก่อนถูก dispute ไปแล้วและถูกเสนอใหม่ การเสนอครั้งที่สองจะถูก dispute ในอัตราประมาณ 2-3 เท่าของปกติ
บอทสามารถคำนวณคะแนน "dispute probability" จากคุณลักษณะเหล่านี้ และหลีกเลี่ยงการเปิดสถานะในตลาดที่คะแนนเกิน threshold ใกล้เวลาปิดตลาด
ความไม่สมมาตรของราคาก่อน dispute
ในช่วงไม่กี่ชั่วโมงก่อนที่การ dispute จะมีแนวโน้มเกิดขึ้น ราคาตลาดมักเคลื่อนไหวแบบไม่สมมาตร: ฝั่งที่ proposer ระบุว่าเป็น YES มักค่อย ๆ ลดลง (เพราะเทรดเดอร์กลัวว่าการ dispute จะพลิกผล) ส่วนอีกฝั่งจะค่อย ๆ สูงขึ้น
ถ้าคุณมีมุมมองเชิงทิศทางว่าการ dispute จะจบแบบไหน นี่คือช่วงเวลาที่เทรดได้ ความเสี่ยงคือ: ถ้า dispute ไม่เกิดขึ้น ความไม่สมมาตรจะกลับทิศเมื่อ challenge window ปิดลงแบบไม่มีอะไรเกิดขึ้น และราคาจะเด้งกลับไปตาม direction ที่เสนอไว้
พูดตรง ๆ: การเทรด pre-dispute asymmetry ส่วนใหญ่เป็นดีลที่ขาดทุน เพราะส่วนใหญ่ challenge จะจบลงโดยเข้าข้างข้อเสนอเดิม กลยุทธ์นี้จะใช้ได้ก็ต่อเมื่อคุณมีข้อมูลเฉพาะเจาะจงว่าทำไม dispute นี้จึงมีแนวโน้มจะถูก sustain
รูปแบบการเทรดหลัง dispute
หลังจากมีการยื่น dispute ตลาดจะเทรดอยู่ในภาวะ "limbo" 24-72 ชั่วโมง-รู้แน่ว่ามีการโต้แย้ง แต่ผลลัพธ์ยังต้องรอโหวต มีรูปแบบการเทรดอยู่สองแบบ
Convergence to UMA consensus: ถ้าสัญญาณการยุติข้อพิพาทปรากฏตั้งแต่เนิ่น ๆ (เช่น ผู้โหวต UMA ที่มีชื่อเสียงออกมาระบุข้างชัดเจน) ราคาจะเคลื่อนไปหา outcome นั้น บอทที่เฝ้าดูสัญญาณจาก UMA Discord / Twitter ควบคู่กับ price action สามารถจับจังหวะนี้ได้ประมาณ 30-60% ของเวลา
Volatility farming: ช่วง limbo มี spread กว้าง market maker ที่อดทนสามารถเก็บ spread tax จากเทรดเดอร์หลายรายที่ผลัดกันเข้าออกระหว่างช่วงโหวตได้ ความเสี่ยงด้าน inventory สูง; ควรปรับขนาดให้เหมาะสม
ทั้งสองแบบต้องยอมรับความเป็นไปได้จริง ๆ ว่าผลจะออกมาตรงข้ามกับสถานะของคุณ ให้ถือ inventory ในช่วง dispute เป็นขนาดไม่เกินครึ่งหนึ่งเป็นอย่างมาก
เมื่อไม่ควรเทรดตลาดที่ถูกโต้แย้ง
มีสามสถานการณ์ที่ trade dispute มักจะผิดตั้งแต่ต้น
- คุณไม่มีมุมมองเฉพาะของ UMA. ถ้า edge ของคุณมีแค่ว่า "ข้อเสนอเดิมดูถูกต้องสำหรับฉัน" คุณไม่ได้มีข้อได้เปรียบเหนือ proposer เดิม-และคนที่ยื่น dispute ก็คิดตรงกันข้าม ผลโหวตจึงแทบเป็นการโยนเหรียญที่คุณคาดไม่ได้
- dispute นั้นเกิดกับถ้อยคำที่กำกวม. โดยทั่วไปผู้โหวต UMA จะยืนฝั่งการอ่านคำถามแบบเคร่งครัด ถ้าตลาดระบุว่า "by January 31" แต่เหตุการณ์เกิดวันที่ 1 กุมภาพันธ์ UMA จะตัดสินเป็น NO ไม่ว่าผู้เล่นในตลาดจะรู้สึกอย่างไร
- คุณถือ inventory มาตั้งแต่ก่อน dispute. การเพิ่มสถานะเดิมเพื่อ "average down" ระหว่าง limbo คือรูปแบบคลาสสิกของการเผาทุน ให้ถือไว้หรือออกจากตลาด อย่าเพิ่ม
Code: subscribe ไปที่ event proposed/disputed ของ UMA
อ้างอิง: การ subscribe แบบ WebSocket ไปยัง event ของ UMA OO โดยกรองด้วย 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 การลงมือเทรดด้วยอัลกอริทึมเมื่อเกิด dispute มีความเสี่ยงสูง; หน้าที่ของบอทโดยทั่วไปคือส่ง event ไปให้มนุษย์เป็นผู้ตรวจทาน





