マクロイベントの市場オッズを表示するダッシュボードを作る

マクロのオッズ ダッシュボードには、トピック一覧と、タイルごとに1回のイベント読み取りが必要です。Narwhalは、CPI、雇用統計、失業率、景気後退、中央銀行の決定に対する市場オッズを、scalar、binary、timing、extreme という名前の4つの形式で提供します。

ダッシュボードに表示するトピックを一覧する

ダッシュボードの各タイルは1つのトピックに対応します。トピックのエンドポイントがそれらを一覧し、任意の group を受け付けます。マクロのグループは central_banks、us_prices、us_jobs、us_activity、global_activity、global_prices です。このリクエストは us_jobs を指定し、先頭の2つのトピックだけを残します。

curl、米国の雇用に関するトピック
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 を持たないトピックもあり、スクリプトはそれらをスキップします。

イベントを1つ読み取る:景気後退のオッズ

binary のイベントは、はい・いいえで答える問いです。このリクエストは景気後退の市場を読み取ります。レスポンスには、市場ごとのルール文は含まれません。

curl、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が2四半期連続でマイナスの場合のみを数える一方、Polymarket は調査機関による景気後退の判定も数えます。Kalshi の 0.0250 は参考として quotes に残り、代表値の probability は Polymarket の気配値と同じです。as_of は気配値の時刻で、気配値が有効な間は stale が false です。

APIが名付けた4つの形式

形式答える問い読み取るフィールドイベントの例
scalar発表や決定がどの値またはどの範囲に収まるかoutcomes。各要素に key、label、lower、upper、probability があるusa-cpi-yoy-2026-11
binary起こるかどうかprobability と quotesusa-recession-2026
timingいつまでに起こるかsteps。各要素に by、label、probability があるusa-fed-next-cut-to-2028-12-31
extreme系列がどこまで高く、または低くなるかlevel と probability を持つ up と down のリスト、および windowusa-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 の棒グラフで分布の全体を示せます。

ダッシュボードの行を組み立てる

スクリプトは3つのグループを順に処理し、各トピックの次のイベントを、その形式が指すエンドポイントで読み取って、タイルごとに見出しを1行出力します。scalar は最も可能性の高い結果、binary は「はい」のオッズ、timing は最初のステップ、extreme は最初のレベルを表示します。使える気配値がないタイルは、その旨を表示します。

python、トピックごとに見出しを1行
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スカラー使える気配値なし

これらの行は、1回の実行による出力です。オッズは市場とともに動くため、すべてのタイルで as_of を確認し、APIからページを更新してください。

使える気配値がないタイルは何を意味しますか?

イベントのレスポンスは stale: true で、確率のフィールドがありません。emu-ecb-cut-2026 の binary のレスポンスでは quotes のリストが空で、Polymarket の項目に excluded_reason: thin が付いています。レスポンスに表示できる確率がないため、そのようなタイルはゼロではなく「利用不可」として表示してください。

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 を読み取ります。

トピックごとに1件ではなく、今後のイベントを一覧するにはどうしますか?

/v1/predictions/events を topic と status=trading を付けて呼び出します。usa-cpi-yoy では、2026年12月10日 13:30 UTC に決着する2026年11月のイベント usa-cpi-yoy-2026-11 と、2026年12月のイベント usa-cpi-yoy-2026-12 が返ります。各行には question、closes_at、resolves_at、shape があります。市場がすでにある発表のカレンダー表示に使い、各イベントはその形式のエンドポイントで開きます。

同じ一覧は shape、from、to、limit、cursor も受け付けます。status=settled を指定すると、すでに決着したイベントが返ります。

金利決定のタイルはどのように表示しますか?

central_banks グループを使うか、1つの中央銀行の政策パスを呼び出すと、価格が付いているすべての会合について、利下げ・据え置き・利上げのオッズが1つのレスポンスで得られます。連邦準備制度の例は、FRBの金利オッズの読み方で説明しています。

公開。

次のステップ