79 lines
2.6 KiB
Python
79 lines
2.6 KiB
Python
import requests
|
||
import json
|
||
|
||
GAMMA = "https://gamma-api.polymarket.com"
|
||
CLOB = "https://clob.polymarket.com"
|
||
|
||
def parse_jsonish_list(v):
|
||
if v is None:
|
||
return []
|
||
if isinstance(v, list):
|
||
return v
|
||
if isinstance(v, str):
|
||
return json.loads(v)
|
||
return []
|
||
|
||
def get_market_by_slug(slug: str):
|
||
r = requests.get(f"{GAMMA}/markets/slug/{slug}", timeout=20)
|
||
r.raise_for_status()
|
||
return r.json()
|
||
|
||
def get_best_price(token_id: str, side: str) -> float | None:
|
||
# side: "buy" => best bid, "sell" => best ask
|
||
r = requests.get(f"{CLOB}/price", params={"token_id": token_id, "side": side}, timeout=20)
|
||
r.raise_for_status()
|
||
p = r.json().get("price")
|
||
return float(p) if p is not None else None
|
||
|
||
def get_mid_or_fallback(token_id: str):
|
||
bid = get_best_price(token_id, "buy")
|
||
ask = get_best_price(token_id, "sell")
|
||
if bid is None and ask is None:
|
||
return None, bid, ask, None
|
||
|
||
# 如果只拿到一侧,就退化
|
||
if bid is None:
|
||
return ask, bid, ask, None
|
||
if ask is None:
|
||
return bid, bid, ask, None
|
||
|
||
spread = ask - bid
|
||
mid = (bid + ask) / 2
|
||
return mid, bid, ask, spread
|
||
|
||
def web_like_up_down(slug: str, decimals=0):
|
||
m = get_market_by_slug(slug)
|
||
outcomes = [str(x) for x in parse_jsonish_list(m.get("outcomes"))]
|
||
token_ids = [str(x) for x in parse_jsonish_list(m.get("clobTokenIds"))]
|
||
|
||
token_map = dict(zip(outcomes, token_ids))
|
||
up_id = token_map.get("Up") or token_map.get("Yes") or token_ids[0]
|
||
down_id = token_map.get("Down") or token_map.get("No") or token_ids[1]
|
||
|
||
up_mid, up_bid, up_ask, up_spread = get_mid_or_fallback(up_id)
|
||
dn_mid, dn_bid, dn_ask, dn_spread = get_mid_or_fallback(down_id)
|
||
|
||
if up_mid is None or dn_mid is None:
|
||
return {"error": "missing price", "up": (up_mid, up_bid, up_ask), "down": (dn_mid, dn_bid, dn_ask)}
|
||
|
||
# 归一化(避免因为点差导致 up+down != 1)
|
||
s = up_mid + dn_mid
|
||
up_pct = round(up_mid / s * 100, decimals)
|
||
dn_pct = round(dn_mid / s * 100, decimals)
|
||
|
||
return {
|
||
"question": m.get("question"),
|
||
"market_id": m.get("id"),
|
||
"slug": m.get("slug"),
|
||
"up_pct": up_pct,
|
||
"down_pct": dn_pct,
|
||
"debug": {
|
||
"up": {"token_id": up_id, "bid": up_bid, "ask": up_ask, "mid_used": up_mid, "spread": up_spread},
|
||
"down":{"token_id": down_id, "bid": dn_bid, "ask": dn_ask, "mid_used": dn_mid, "spread": dn_spread},
|
||
"note": "网页通常用 mid;若点差>0.10 则可能改用 last trade price。"
|
||
}
|
||
}
|
||
|
||
if __name__ == "__main__":
|
||
print(web_like_up_down("eth-updown-15m-1767069900", decimals=0))
|