FinHub API
量化接口 总览 Polymarket

用 Python 接入数据(只需标准库)

第一步:拿一把免费 key。 注册后在「我的 API Key」里自助创建。 免费档就能取当前窗口的完整数据(含 2 秒序列),不付费。

一、最小可用客户端

import json, os, urllib.request, urllib.error, urllib.parse

BASE = "https://api.wanminguo.top/quant/polymarket/v1"
KEY  = os.environ.get("PM_API_KEY", "")

class ApiError(Exception):
    def __init__(self, status, code, message, body=None):
        super().__init__(f"[{status}] {code}: {message}")
        self.status, self.code, self.message, self.body = status, code, message, body

def call(path, **params):
    """调一个 /v1 端点。返回 (data, meta)。"""
    if not KEY:
        raise SystemExit("请先设置环境变量 PM_API_KEY(免费注册:"
                         "https://api.wanminguo.top/me/register.php)")
    qs = "&".join(f"{k}={urllib.parse.quote(str(v))}" for k, v in params.items() if v is not None)
    url = f"{BASE}/{path}" + (f"?{qs}" if qs else "")
    req = urllib.request.Request(url, headers={"X-Api-Key": KEY,
                                               "Accept": "application/json"})
    try:
        with urllib.request.urlopen(req, timeout=15) as r:
            body = json.loads(r.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        try:
            body = json.loads(e.read().decode("utf-8"))
        except Exception:
            body = {}
        raise ApiError(e.code, body.get("error", "http_error"),
                       body.get("message", ""), body) from None
    if not body.get("ok"):
        raise ApiError(200, body.get("error", "unknown"), body.get("message", ""), body)
    return body.get("data"), body.get("meta", {})

if __name__ == "__main__":
    data, meta = call("window.php", market="eth")
    print("窗口     :", data["slug"])
    print("距 beat  :", data["official_bp"], "bp  →", data["leading_side"])
    print("剩余     :", data["remaining"], "秒")
    print("额度余额 :", meta["credits"]["balance"], "股(1 股 = 1 额度,成交才扣)")

二、响应信封(每次都要看的两处)

{
  "ok": true,
  "data": { ... },
  "meta": {
    "plan": "free",
    "quota": { "mode": "subscription", "daily_limit": null,
               "used_today": 0, "remaining": null, "reset_at": null },
    "credits": { "balance": 10000, "total_in": 10000, "total_used": 0 },
    "limits": { "qps": 20, "history_days": 1, ... },
    "feed": { "ok": true, "latest_slug": "eth-updown-5m-...", "latest_age_sec": 3 },
    "server_ts": 1790409000
  }
}
  • meta.credits.balance —— 账号额度余额(股),成交 1 股扣 1 额度; 信号订阅制**无请求配额**(不再按请求数计费);
  • meta.feed.latest_age_sec —— 采集器是否还在正常写数。 这个值持续变大说明数据流断了,此时拿到的「当前窗口」可能是旧的;
  • 错误时 ok=false 且带 error / message。

三、常用端点

路径(都带 .php)用途关键参数
/v1/window.php当前/指定窗口快照 market slug series=1 n
/v1/settle.php结算核对 market slug last
/v1/history.php历史窗口列表 market from to limit offset
/v1/samples.php原始 2 秒样本(需套餐) slug limit tail
/v1/stats.php汇总统计(免费档可用)—
/v1/index.php端点清单与你的套餐限额—

7 个市场的 ?market= 短名:btc eth sol xrp doge hype bnb (也接受 ETH-5m / eth-updown-5m 这种写法)。

⚠️ 路径必须带 .php —— 本站没有配置 URL rewrite, 写成 /v1/window 会 404。

四、429 要怎么处理

错误码含义正确做法
rate_limited同一秒请求过多(秒级防护,20 qps 上限) 按响应头 Retry-After 退避 1 秒后重试即可

信号订阅制下**没有请求配额**(额度按成交股数扣),不再有 daily_quota_exceeded。

五、轮询频率建议

数据本身就是 约 2 秒一条,所以轮询窗口端点 1~2 秒一次就够了, 更密没有信息增益。订阅制下请求不限量,不用再计算"配额够不够撑多久"—— 只有**实际成交**才扣账号额度(1 股 = 1 额度)。

六、现成的完整示例

站上有一份客户端本体与四个示例,全部只用标准库,下载到同一目录即可运行:

https://api.wanminguo.top/quant/polymarket/examples/pm_api_client.py   ← 客户端本体(可 import)
https://api.wanminguo.top/quant/polymarket/examples/current_window.py  ← 当前窗口快照
https://api.wanminguo.top/quant/polymarket/examples/settle_recent.py   ← 最近结算(--verify 本地复算四规则)
https://api.wanminguo.top/quant/polymarket/examples/history.py         ← 历史窗口(自动翻页)
https://api.wanminguo.top/quant/polymarket/examples/samples.py         ← 原始 2 秒样本
export PM_API_KEY=pm_live_xxxxxxxx
python current_window.py --market eth          # 当前窗口
python settle_recent.py --last 10 --verify     # 最近 10 个结算并本地复算
python history.py --from 2026-09-25 --limit 50 # 历史
python samples.py --slug eth-updown-5m-1790401800 --tail 1   # 原始样本
客户端把 beat_trusted、meta.credits、Retry-After 都当作一等公民处理 —— 尤其 beat_trusted=false 时会明确提示 「这个窗口不适合用来定方向」,不会静默吞掉。

七、下一步