在 Python 中获取实时金价,可使用 requests 向 api.goldprice.dev/v1/spot/XAU-USD-SPOT 发送 GET 请求,并通过 X-API-Key 请求头传入 API 密钥。用 cachetools.TTLCache 将结果缓存 60 秒,价格运算使用 Decimal。免费套餐每月提供 5,000 次调用,无需信用卡。测试时间为 2026 年 10 月,环境为 Python 3.15 + requests 2.34。
获取 goldprice.dev API 密钥
前往 goldprice.dev/onboarding 注册免费账户。验证邮箱后,控制台会显示以 ga_live_ 开头的密钥。将其设为环境变量:
export GOLDPRICE_API_KEY=ga_live_replace_with_your_key_here免费套餐每月提供 5,000 次调用,支持以 31 种货币计价的黄金现货。无需信用卡。
安装依赖
需要三个包:requests 用于 HTTP 请求,cachetools 用于进程内 TTL 缓存,tenacity 用于 429 重试。使用 pip 或 uv 安装:
# pippip install requests cachetools tenacity# or uv (recommended)uv add requests cachetools tenacity编写 goldprice 客户端
将代码保存为 goldprice.py。spot() 按品种代码缓存 60 秒,遇到 429 时采用指数退避,最多重试 3 次,并以 Decimal 返回价格,避免后续运算因浮点精度产生偏差。
# python: goldprice.py# curl-equivalent: https://api.goldprice.dev/v1/spot/XAU-USD-SPOTimport osfrom decimal import Decimalfrom typing import TypedDictimport requestsfrom cachetools import TTLCache, cachedfrom tenacity import ( retry, retry_if_exception_type, stop_after_attempt, wait_exponential,)API_BASE = "https://api.goldprice.dev"API_KEY = os.environ["GOLDPRICE_API_KEY"]TIMEOUT = 5 # secondsclass SpotResponse(TypedDict): symbol: str quote_currency: str price: Decimal bid: Decimal | None # only on plans that include bid and ask ask: Decimal | None is_stale: bool computed_at: strclass RateLimited(Exception): """Raised on HTTP 429 so tenacity retries with backoff."""@cached(cache=TTLCache(maxsize=128, ttl=60))@retry( retry=retry_if_exception_type(RateLimited), wait=wait_exponential(multiplier=1, min=2, max=30), stop=stop_after_attempt(3), reraise=True,)def spot(symbol: str = "XAU-USD-SPOT") -> SpotResponse: """Fetch live spot price. Cached 60s per symbol, retries 3x on 429.""" resp = requests.get( f"{API_BASE}/v1/spot/{symbol}", headers={"X-API-Key": API_KEY}, timeout=TIMEOUT, ) if resp.status_code == 429: raise RateLimited(resp.text) resp.raise_for_status() data = resp.json() return { "symbol": data["symbol"], "quote_currency": data["quote_currency"], "price": Decimal(data["price"]), "bid": Decimal(data["bid"]) if data.get("bid") else None, "ask": Decimal(data["ask"]) if data.get("ask") else None, "is_stale": data["is_stale"], "computed_at": data["computed_at"], }if __name__ == "__main__": r = spot("XAU-USD-SPOT") print(f"{r['symbol']}-{r['quote_currency']}: {r['price']} (computed {r['computed_at']})")运行代码
在设置 GOLDPRICE_API_KEY 的同一个 shell 中运行文件。首次调用会请求 API;60 秒内的后续调用直接返回缓存值。缓存仅存在于当前进程,新进程运行时无法命中;如需跨进程缓存,可将结果保存到 Redis。
python goldprice.py# XAU-USD: 4012.75 (computed 2026-10-23T07:00:18.221118+00:00)切换币种或金属
品种代码采用 METAL-CURRENCY-SPOT 格式。可向 spot() 传入使用任意一种受支持现货币种的代码,共支持 31 种。每个品种在 TTLCache 中独立缓存。因此,多币种仪表板按 60s 间隔轮询 5 个品种时,未命中缓存每分钟产生 5 次 API 调用,命中缓存则为 0 次。
# USD spot, defaultspot("XAU-USD-SPOT")spot("XAU-INR-SPOT")spot("XAU-EUR-SPOT")# Silver in USDspot("XAG-USD-SPOT")预期输出
{ "symbol": "XAU", "quote_currency": "USD", "unit": "troy_ounce", "contract_type": "spot", "price": "4012.75", "is_stale": false, "computed_at": "2026-10-23T07:00:18.221118+00:00"}标准输出显示一行:symbol、quote_currency、Decimal 格式的 price,以及 ISO 8601 格式的 computed_at 时间戳。后续代码使用 TypedDict 响应。
常见错误
| 代码 | 现象 | 解决方法 |
|---|---|---|
| 401 | requests.exceptions.HTTPError: 401 Client Error | API 密钥缺失或无效。确认已设置 GOLDPRICE_API_KEY:echo $GOLDPRICE_API_KEY。如果为空,请从控制台获取密钥并重新设置环境变量。客户端在导入时检查环境变量,因此缺失时会在首次执行 import goldprice 时报错,无需等到调用函数。 |
| 429 | RateLimited 经过三次退避重试仍失败,随后向外抛出异常 | 已达到每分钟请求上限。60 秒缓存可避免稳定轮询触发此问题;如果同时请求大量不同品种,请调大 TTLCache.maxsize 或错开调用。持续高频使用可查看 /pricing 中的付费套餐。 |
| N/A | 累加大量价格时,浮点误差不断积累 | 运算全程使用 Decimal,不要转成 float。客户端以 Decimal 返回价格;进行 JSON 序列化时,请用 str(price),避免转为浮点数,以保留传输精度。 |
进阶用法
- 跨进程保存缓存:将
TTLCache替换为 Redis 缓存,让多个工作进程共享同一份内存价格数据 - 为
/v1/bars?symbol=XAU-USD-SPOT&interval=1d&from=...&to=...添加bars()封装,并转换为 pandas DataFrame 用于回测 - 如果服务使用异步处理,可将
requests替换为httpx.AsyncClient,响应结构相同 - 将客户端接入 FastAPI 端点,为非 Python 服务提供内部访问
- 通过 Prometheus 监测缓存命中率、p50/p95 延迟和 429 重试次数