宏观赔率仪表盘需要主题列表,以及每个卡片一次事件读取。Narwhal 以四种命名形态提供 CPI、非农就业、失业率、衰退和央行决议的市场赔率:scalar、binary、timing 和 extreme。
列出为仪表盘提供内容的主题
仪表盘上的每个卡片对应一个主题。主题端点会列出它们,并接受可选的 group 参数。宏观分组有 central_banks、us_prices、us_jobs、us_activity、global_activity 和 global_prices。这个请求指定 us_jobs,并只保留前两个主题。
curl -s -H "Authorization: Bearer $NARWHAL_API_KEY" \
"https://api.narwhalapi.com/v1/predictions/topics?group=us_jobs"{
"topics": [
{
"topic_id": "usa-payrolls",
"group": "us_jobs",
"title": "US nonfarm payrolls change",
"shape": "scalar",
"unit": "jobs",
"unit_key": "job",
"venues": [
"kalshi"
],
"resolution_kind": "release",
"calendar": {
"country": "USA",
"family": "labour"
},
"next_event_id": "usa-payrolls-2026-10"
},
{
"topic_id": "usa-unemployment",
"group": "us_jobs",
"title": "US unemployment rate",
"shape": "scalar",
"unit": "percent",
"unit_key": "percent",
"venues": [
"kalshi",
"polymarket"
],
"resolution_kind": "release",
"calendar": {
"country": "USA",
"family": "labour"
},
"next_event_id": "usa-unemployment-2026-10"
}
]
}shape 告诉你该调用哪个端点:scalar、binary、timing 或 extreme。unit 给出答案的单位,venues 列出背后的市场,resolution_kind 说明该主题如何结算。next_event_id 是当前应展示的事件。有些主题(例如 deu-gdp-yoy)没有 next_event_id,脚本会跳过它们。
读取一个事件:衰退赔率
binary 事件提出的是是非题。这个请求读取衰退市场,响应中不包含各市场的规则文本。
curl -s -H "Authorization: Bearer $NARWHAL_API_KEY" \
"https://api.narwhalapi.com/v1/predictions/binary/usa-recession-2026"{
"event_id": "usa-recession-2026",
"topic_id": "usa-recession-2026",
"question": "US recession by end of 2026?",
"status": "trading",
"closes_at": "2026-12-31T00:00:00Z",
"resolves_at": "2026-12-31T00:00:00Z",
"as_of": "2026-11-03T02:21:00Z",
"stale": false,
"resolution": "Two consecutive negative quarters of US real GDP from Q2 2025 to Q4 2026, or an NBER recession call for 2025 or 2026",
"venues": [
{
"venue": "kalshi",
"url": "https://kalshi.com/markets/kxrecssnber/kxrecssnber-26",
"rules_url": "https://assets.kalshi.com/contract_terms/NBERRECSS.pdf",
"settlement_source": "Bureau of Economic Analysis",
"excluded_reason": "rules",
"match": {
"differences": [
"rules"
],
"note": "Kalshi resolves on two negative GDP quarters only; Polymarket also counts an NBER recession call"
},
"volume_24h_usd": "123.64",
"open_interest_usd": "17994.22"
},
{
"venue": "polymarket",
"url": "https://polymarket.com/event/us-recession-by-end-of-2026",
"settlement_source": "Bureau of Economic Analysis; NBER",
"weight": "1.0000",
"volume_24h_usd": "2090.24"
}
],
"probability": "0.0550",
"quotes": [
{
"venue": "kalshi",
"probability": "0.0250",
"market_ids": [
"KXRECSSNBER-26"
]
},
{
"venue": "polymarket",
"probability": "0.0550",
"market_ids": [
"100379208559626151022751801118534484742123694725746262280150222742563282755057"
]
}
]
}probability 是“是”的市场赔率,这里为 0.0550,quotes 列出各市场的价格。Kalshi 的条目带有 excluded_reason: rules 和一条 match 说明:其规则只计入 GDP 连续两个季度为负,而 Polymarket 还计入研究机构作出的衰退判定。Kalshi 的 0.0250 仍保留在 quotes 中供参考,而顶层的 probability 等于 Polymarket 的报价。as_of 是报价时间,报价有效时 stale 为 false。
API 命名的四种形态
| 形态 | 回答的问题 | 需要读取的字段 | 示例事件 |
|---|---|---|---|
scalar | 某次数据发布或决议会落在哪个数值或区间 | outcomes,每一项包含 key、label、lower、upper、probability | usa-cpi-yoy-2026-11 |
binary | 会不会发生 | probability 和 quotes | usa-recession-2026 |
timing | 会在何时之前发生 | steps,每一项包含 by、label、probability | usa-fed-next-cut-to-2028-12-31 |
extreme | 某个序列会升到多高或降到多低 | 由 level 和 probability 组成的 up 与 down 列表,外加 window | usa-unemployment-peak-2026 |
scalar 事件涵盖宏观仪表盘要展示的各项数据发布:CPI 的 12 个月变化、失业率、非农就业人数以及各央行的利率决议。CPI 或失业率事件的 resolves_with 字段指向用于结算它的 Narwhal 序列,例如 /v1/economics/USA/cpi。因此事件结算后,卡片可以从赔率直接链接到已发布的数字。
scalar 事件还会给区间的边界命名。在一个 outcome 中,lower 和 upper 限定区间范围,边界为 null 表示该侧是开区间,例如表示 3.0% 及以下的 le_3.0 一行。在为本页读取的 CPI、失业率和美联储事件中,各行的 probability 之和为 1,因此用 outcomes 画柱状图就能呈现完整的分布。
生成仪表盘的各行
脚本遍历三个分组,用各主题的形态所指向的端点读取该主题的下一个事件,并为每个卡片打印一行标题。scalar 显示可能性最大的结果,binary 显示“是”的赔率,timing 显示第一个节点,extreme 显示第一个水平。没有可用报价的卡片会如实说明。
import json
import os
import urllib.request
def get(path):
req = urllib.request.Request(
"https://api.narwhalapi.com" + path,
headers={"Authorization": "Bearer " + os.environ["NARWHAL_API_KEY"]},
)
with urllib.request.urlopen(req, timeout=30) as r:
return json.load(r)
def headline(shape, e):
if shape == "binary":
if "probability" not in e:
return "no usable quote"
return f"yes {float(e['probability']):.1%}"
if shape == "scalar":
priced = [o for o in e["outcomes"] if "probability" in o]
if not priced:
return "no usable quote"
top = max(priced, key=lambda o: float(o["probability"]))
return f"{top['label']} {float(top['probability']):.1%}"
if shape == "timing":
step = e["steps"][0]
if "probability" not in step:
return "no usable quote"
return f"by {step['label']} {float(step['probability']):.1%}"
if shape == "extreme":
if not e["up"] or "probability" not in e["up"][0]:
return "no usable quote"
step = e["up"][0]
return f"reach {step['level']} {float(step['probability']):.1%}"
for group in ("us_prices", "us_jobs", "us_activity"):
for topic in get("/v1/predictions/topics?group=" + group)["topics"]:
if not topic.get("next_event_id") or topic["shape"] == "scalar" and topic["unit"] == "count":
continue
e = get(f"/v1/predictions/{topic['shape']}/{topic['next_event_id']}")
print(group, e["event_id"], topic["shape"], headline(topic["shape"], e),
"stale" if e["stale"] else "live")
| 事件 | 形态 | 标题 |
|---|---|---|
usa-cpi-yoy-2026-11 | 标量 | 3.9%, 20.0% |
usa-unemployment-2026-10 | 标量 | 4.2%, 37.1% |
usa-unemployment-peak-2026 | 极值 | 触及 5.0,3.1% |
usa-recession-2026 | 二元 | 是 5.5% |
usa-gdp-2026-q4 | 标量 | 无可用报价 |
这些行是某一次运行的输出。赔率会随市场变动,所以请查看每个卡片上的 as_of,并从 API 刷新页面。
没有可用报价的卡片是什么意思?
事件响应带有 stale: true,且没有概率字段。以 emu-ecb-cut-2026 为例,其 binary 响应的 quotes 列表为空,Polymarket 的条目带有 excluded_reason: thin。响应中没有可显示的概率,所以这类卡片应显示为不可用,而不是 0。
CPI、非农就业和失业率分别在哪些主题里?
usa-cpi-yoy、usa-cpi-mom、usa-core-cpi-yoy 和 usa-core-cpi-mom 在 us_prices 中。usa-payrolls 和 usa-unemployment 在 us_jobs 中。usa-recession-2026 在 us_activity 中,利率决议在 central_banks 中。先查询分组,再读取每个主题的 next_event_id。
如何列出即将到来的事件,而不是每个主题只取一个?
用 topic 和 status=trading 调用 /v1/predictions/events。对 usa-cpi-yoy,它会返回 2026 年 11 月的事件 usa-cpi-yoy-2026-11(在 2026 年 12 月 10 日 13:30 UTC 结算)以及 2026 年 12 月的事件 usa-cpi-yoy-2026-12。每一行都有 question、closes_at、resolves_at 和 shape。可以用它来做已有市场的数据发布日历视图,再用对应形态的端点打开每个事件。
同一个列表还接受 shape、from、to、limit 和 cursor,status=settled 则返回已经结算的事件。
如何展示利率决议卡片?
使用 central_banks 分组,或者调用某家央行的政策路径,即可在一个响应中得到每次已有定价的会议的降息、按兵不动和加息赔率。美联储的例子见如何解读美联储利率赔率。
发布于。