Initial commit with translated description
This commit is contained in:
44
SKILL.md
Normal file
44
SKILL.md
Normal file
@@ -0,0 +1,44 @@
|
||||
---
|
||||
name: polymarket
|
||||
description: "查询Polymarket预测市场。用于关于预测市场、投注赔率、市场价格、事件概率的问题,或当用户询问Polymarket数据时使用。"
|
||||
---
|
||||
|
||||
# Polymarket
|
||||
|
||||
Query prediction market data from Polymarket's public API (no auth required).
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Top markets by 24h volume
|
||||
python3 scripts/polymarket.py --top
|
||||
|
||||
# Search markets
|
||||
python3 scripts/polymarket.py --search "trump"
|
||||
|
||||
# Get specific market by slug
|
||||
python3 scripts/polymarket.py --slug "will-trump-win-the-2024-election"
|
||||
|
||||
# List events (grouped markets)
|
||||
python3 scripts/polymarket.py --events
|
||||
```
|
||||
|
||||
## Script Location
|
||||
|
||||
`skills/polymarket/scripts/polymarket.py`
|
||||
|
||||
## API Endpoints
|
||||
|
||||
The script uses `gamma-api.polymarket.com`:
|
||||
- `/markets` - Individual markets with prices, volumes
|
||||
- `/events` - Event groups containing related markets
|
||||
|
||||
## Output Format
|
||||
|
||||
Markets show: question, Yes/No prices (as percentages), 24h volume, total volume.
|
||||
|
||||
## Interpreting Prices
|
||||
|
||||
- `outcomePrices` are 0-1 representing probability
|
||||
- Price of 0.65 for "Yes" = market thinks 65% chance of Yes
|
||||
- Higher volume = more liquid, more reliable signal
|
||||
6
_meta.json
Normal file
6
_meta.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"ownerId": "kn7caxjvqk9fengp67p290smnn800sv9",
|
||||
"slug": "polymarket-api",
|
||||
"version": "1.0.0",
|
||||
"publishedAt": 1769515386284
|
||||
}
|
||||
150
scripts/polymarket.py
Normal file
150
scripts/polymarket.py
Normal file
@@ -0,0 +1,150 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Query Polymarket prediction markets via public API."""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
from typing import Optional
|
||||
|
||||
BASE_URL = "https://gamma-api.polymarket.com"
|
||||
|
||||
def fetch(endpoint: str, params: dict = None) -> list | dict:
|
||||
"""Fetch from Polymarket API."""
|
||||
url = f"{BASE_URL}{endpoint}"
|
||||
if params:
|
||||
url += "?" + urllib.parse.urlencode(params)
|
||||
req = urllib.request.Request(url, headers={
|
||||
"User-Agent": "Mozilla/5.0 (compatible; polymarket-skill/1.0)",
|
||||
"Accept": "application/json"
|
||||
})
|
||||
with urllib.request.urlopen(req, timeout=15) as resp:
|
||||
return json.loads(resp.read())
|
||||
|
||||
def format_market(m: dict) -> str:
|
||||
"""Format a single market for display."""
|
||||
q = m.get("question", "Unknown")[:80]
|
||||
prices = json.loads(m.get("outcomePrices", '["0","0"]'))
|
||||
yes_pct = float(prices[0]) * 100 if prices else 0
|
||||
no_pct = float(prices[1]) * 100 if len(prices) > 1 else 0
|
||||
vol24h = m.get("volume24hr", 0) or 0
|
||||
vol_total = m.get("volumeNum", 0) or 0
|
||||
closed = "🔒" if m.get("closed") else ""
|
||||
return f"{closed}{q}\n Yes: {yes_pct:.1f}% | No: {no_pct:.1f}% | 24h: ${vol24h:,.0f} | Total: ${vol_total:,.0f}"
|
||||
|
||||
def top_markets(limit: int = 10) -> None:
|
||||
"""Show top markets by 24h volume."""
|
||||
markets = fetch("/markets", {
|
||||
"active": "true",
|
||||
"closed": "false",
|
||||
"limit": limit,
|
||||
"order": "volume24hr",
|
||||
"ascending": "false"
|
||||
})
|
||||
print(f"📈 Top {len(markets)} Markets by 24h Volume\n")
|
||||
for m in markets:
|
||||
print(format_market(m))
|
||||
print()
|
||||
|
||||
def search_markets(query: str, limit: int = 10) -> None:
|
||||
"""Search markets by text."""
|
||||
# The API doesn't have a search param, so we fetch more and filter
|
||||
markets = fetch("/markets", {
|
||||
"active": "true",
|
||||
"closed": "false",
|
||||
"limit": 100,
|
||||
"order": "volume24hr",
|
||||
"ascending": "false"
|
||||
})
|
||||
query_lower = query.lower()
|
||||
matches = [m for m in markets if query_lower in m.get("question", "").lower()
|
||||
or query_lower in m.get("description", "").lower()][:limit]
|
||||
|
||||
if not matches:
|
||||
print(f"No markets found matching '{query}'")
|
||||
return
|
||||
|
||||
print(f"🔍 Markets matching '{query}'\n")
|
||||
for m in matches:
|
||||
print(format_market(m))
|
||||
print()
|
||||
|
||||
def get_market(slug: str) -> None:
|
||||
"""Get a specific market by slug."""
|
||||
markets = fetch("/markets", {"slug": slug})
|
||||
if not markets:
|
||||
print(f"No market found with slug: {slug}")
|
||||
return
|
||||
|
||||
m = markets[0]
|
||||
print(f"📊 {m.get('question', 'Unknown')}\n")
|
||||
prices = json.loads(m.get("outcomePrices", '["0","0"]'))
|
||||
outcomes = json.loads(m.get("outcomes", '["Yes","No"]'))
|
||||
|
||||
for i, (outcome, price) in enumerate(zip(outcomes, prices)):
|
||||
pct = float(price) * 100
|
||||
print(f" {outcome}: {pct:.1f}%")
|
||||
|
||||
print(f"\n 24h Volume: ${m.get('volume24hr', 0):,.0f}")
|
||||
print(f" Total Volume: ${m.get('volumeNum', 0):,.0f}")
|
||||
print(f" Liquidity: ${m.get('liquidityNum', 0):,.0f}")
|
||||
print(f" Status: {'Closed' if m.get('closed') else 'Open'}")
|
||||
if m.get("endDate"):
|
||||
print(f" End Date: {m.get('endDate')[:10]}")
|
||||
if m.get("description"):
|
||||
desc = m.get("description", "")[:500]
|
||||
print(f"\n {desc}{'...' if len(m.get('description', '')) > 500 else ''}")
|
||||
|
||||
def list_events(limit: int = 10) -> None:
|
||||
"""List top events (grouped markets)."""
|
||||
events = fetch("/events", {
|
||||
"active": "true",
|
||||
"closed": "false",
|
||||
"limit": limit,
|
||||
"order": "volume24hr",
|
||||
"ascending": "false"
|
||||
})
|
||||
print(f"📅 Top {len(events)} Events\n")
|
||||
for e in events:
|
||||
title = e.get("title", "Unknown")[:70]
|
||||
vol = e.get("volume", 0) or 0
|
||||
markets_count = len(e.get("markets", []))
|
||||
print(f"• {title}")
|
||||
print(f" Volume: ${vol:,.0f} | Markets: {markets_count}")
|
||||
print()
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Query Polymarket prediction markets")
|
||||
parser.add_argument("--top", action="store_true", help="Show top markets by 24h volume")
|
||||
parser.add_argument("--search", "-s", type=str, help="Search markets by text")
|
||||
parser.add_argument("--slug", type=str, help="Get market by slug")
|
||||
parser.add_argument("--events", "-e", action="store_true", help="List top events")
|
||||
parser.add_argument("--limit", "-n", type=int, default=10, help="Number of results")
|
||||
parser.add_argument("--json", action="store_true", help="Output raw JSON")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.json:
|
||||
if args.search:
|
||||
data = fetch("/markets", {"active": "true", "closed": "false", "limit": 100})
|
||||
data = [m for m in data if args.search.lower() in m.get("question", "").lower()][:args.limit]
|
||||
elif args.slug:
|
||||
data = fetch("/markets", {"slug": args.slug})
|
||||
elif args.events:
|
||||
data = fetch("/events", {"active": "true", "closed": "false", "limit": args.limit})
|
||||
else:
|
||||
data = fetch("/markets", {"active": "true", "closed": "false", "limit": args.limit, "order": "volume24hr", "ascending": "false"})
|
||||
print(json.dumps(data, indent=2))
|
||||
return
|
||||
|
||||
if args.search:
|
||||
search_markets(args.search, args.limit)
|
||||
elif args.slug:
|
||||
get_market(args.slug)
|
||||
elif args.events:
|
||||
list_events(args.limit)
|
||||
else:
|
||||
top_markets(args.limit)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user