Narwhal の API データを Postgres に取り込む

Narwhal の祝日、公開日、経済データ、コモディティのスポット価格、為替、予測市場のオッズを Postgres に取り込めます。curl で JSON を取得し、jq で CSV に変換して、psql でステージングテーブルに読み込み、行をアップサートします。

セットアップする内容

このワークフローでは Postgres がデータの保存先で、データ領域ごとの CSV ファイルと、繰り返し読み込みに対応した祝日テーブルができあがります。Postgres 自体は HTTP を取得できないため、リクエストはデータベースへの読み込みの前にシェルで実行します。必要なものは curl、jq、psql です。取得コマンドは API の URL と認可ヘッダーを共通のヘルパーにまとめ、データベースの例では祝日テーブルに書き込む前に一時的なステージングテーブルを使います。エクスポートでは、祝日、公開日、CPI、コモディティ価格、為替、政策金利パスのオッズを別々のファイルに分け、領域ごとにレスポンスのフィールドを選びます。

APIキーを設定

  1. 無料キーを作成する Narwhal のサインアップ で無料のキーを作成してください。Narwhal は、祝日、経済カレンダー、経済データ、コモディティのスポット価格、為替レート、予測市場のオッズのすべてで、1つのアカウントと1つの API キーを使います。
  2. キーを環境に保存する 取得コマンドを実行するシェルでは、キーを NARWHAL_API_KEY という環境変数に保存します。ヘルパーはリクエストのたびにこの変数を読むので、すべての CSV エクスポートで同じキーが使われます。
  3. 共通のリクエストヘルパーを使う コマンドは Authorization: Bearer YOUR_KEY ヘッダーでキーを https://api.narwhalapi.com に送ります。REST と MCP ではキーを共有します。この Postgres のワークフローでは、できあがったファイルを psql で読み込む前に、シェルのヘルパーで REST リクエストを使います。

コードでデータを取得する

  1. 各領域を CSV に取得する シェルコマンドで各領域をリクエストし、jq でレスポンスのフィールドを選びます。ヘルパーは curl -f を使うので、HTTP エラーのステータスで失敗します。各パイプラインは CSV ファイルを書き出し、列の順序は jq 式のフィールドの順序に従います。祝日は日付と名前の列、CPI は期間と値の列になります。ファイルのステージングテーブルを定義するときは、この順序を保ってください。
    手順 1、curl と jq で各領域を CSV に取得
    get() {
      curl -sf -H "Authorization: Bearer $NARWHAL_API_KEY" \
        "https://api.narwhalapi.com$1"
    }
    
    get /v1/calendars/holidays/USA/2026 \
      | jq -r '.holidays[] | [.date, .name] | @csv' \
      > holidays.csv
    get \
      "/v1/economics/calendar?countries=USA&start_date=2026-11-01&end_date=2026-11-30&limit=100" \
      | jq -r '.releases[] | [.at, .period, .topic, .status] | @csv' > releases.csv
    get "/v1/economics/USA/cpi/observations?start=2025-09" \
      | jq -r '.observations[] | [.period, .value] | @csv' \
      > cpi.csv
    get /v1/commodities/spot/BRENT/USD | jq -r '[(now | todate), .price] | @csv' > brent.csv
    get "/v1/fx/rates/USD?currencies=EUR,IDR" \
      | jq -r '.rates[] | [.currency, .rate, .timestamp] | @csv' \
      > fx.csv
    get /v1/predictions/policy-paths/federal-reserve \
      | jq -r '.meetings[] | [.resolves_at, .p_cut, .p_hold, .p_hike] | @csv' \
      > fed.csv
  2. ステージングテーブル経由で祝日を読み込む psql が holidays.csv を読める場所で読み込みコマンドを実行します。必要に応じて保存先テーブルを作成し、CSV を一時テーブルにコピーして、ステージングされた行を挿入します。DISTINCT ON は、1回の読み込み内で重複した日付を取り除きます。保存先に同じ日付がすでにある場合は、ON CONFLICT で名前を更新します。ほかの CSV ファイルも、フィールドに合うテーブルと主キーで同じ読み込みパターンを使えます。祝日の保存先には date 型の date 列と text 型の name 列があります。ステージングテーブルの列の順序は CSV と同じです。
    手順 2、ステージングテーブルとアップサートで祝日を読み込む
    psql <<'SQL'
    CREATE TABLE IF NOT EXISTS holidays (date date PRIMARY KEY, name text);
    CREATE TEMP TABLE staging (date date, name text);
    \copy staging FROM 'holidays.csv' WITH (FORMAT csv)
    INSERT INTO holidays
      SELECT DISTINCT ON (date) date, name FROM staging ORDER BY date, name
      ON CONFLICT (date) DO UPDATE SET name = EXCLUDED.name;
    SQL

スケジュールで実行する

毎日の cron 行でスクリプトを実行します。\copy が読み込むときに CSV が存在するよう、取得手順をデータベースへの読み込みの前に置き、スクリプトから NARWHAL_API_KEY を使えるようにしてください。読み込みはアップサートなので、再実行しても安全で、既存の祝日の日付は名前が更新されます。ほかのファイルでは、祝日のキーをそのまま流用せず、それぞれの主キーを使います。CPI は period、為替は currency と timestamp の組み合わせです。定期読み込みを広げるときは、CSV のフィールド順を各ステージングテーブルに合わせてください。

Postgres の祝日

2026年の USA の祝日をリクエストし、holidays 配列を読みます。各項目に date と name があり、それが holidays.csv の列になります。このファイルはステージングテーブルの例で使います。保存先では祝日の日付を主キーにし、再読み込みするとその日付の名前が更新されます。

祝日の日付と名前を取得する
get() {
  curl -sf -H "Authorization: Bearer $NARWHAL_API_KEY" \
    "https://api.narwhalapi.com$1"
}

get /v1/calendars/holidays/USA/2026 \
  | jq -r '.holidays[] | [.date, .name] | @csv' > holidays.csv

Postgres の公開日

2026年11月の USA の経済カレンダーをリクエストし、releases を読みます。これらが公開日です。データベースに公開時刻とその対象や期間が並ぶように、CSV には at、period、topic、status を残します。リクエストの URL には開始日と終了日が含まれ、出力は releases.csv に書き込まれます。

経済指標の公開日を取得する
get() {
  curl -sf -H "Authorization: Bearer $NARWHAL_API_KEY" \
    "https://api.narwhalapi.com$1"
}

get \
  "/v1/economics/calendar?countries=USA&start_date=2026-11-01&end_date=2026-11-30&limit=100" \
  | jq -r '.releases[] | [.at, .period, .topic, .status] | @csv' > releases.csv

Postgres の経済データ

2025年9月以降の USA の CPI 観測値をリクエストし、observations を読みます。サンプルは各 period と value を cpi.csv に書き込みます。この系列では、保存先の主キーに period を使います。値は10進数の文字列で届くので、Postgres に読み込むときは numeric 列を使ってください。アップサートが更新する観測値は、period 列で特定されます。

CPI の期間と値を取得する
get() {
  curl -sf -H "Authorization: Bearer $NARWHAL_API_KEY" \
    "https://api.narwhalapi.com$1"
}

get "/v1/economics/USA/cpi/observations?start=2025-09" \
  | jq -r '.observations[] | [.period, .value] | @csv' > cpi.csv

Postgres のコモディティのスポット価格

USD での BRENT のスポット価格をリクエストし、price を読みます。CSV の式は jq でタイムスタンプを追加し、brent.csv の価格の前に置きます。このタイムスタンプは式で付けたものです。価格は numeric 列に保存してください。スポットコードには、たとえば XAU、XAG、XPT、XPD、XCU、BRENT、WTI があります。

コモディティのスポット価格を取得する
get() {
  curl -sf -H "Authorization: Bearer $NARWHAL_API_KEY" \
    "https://api.narwhalapi.com$1"
}

get /v1/commodities/spot/BRENT/USD \
  | jq -r '[(now | todate), .price] | @csv' > brent.csv

Postgres の為替

USD を基準通貨として EUR と IDR のレートをリクエストし、rates を読みます。CSV には currency、rate、timestamp がこの順で入ります。保存先テーブルでは、currency と timestamp の組み合わせを主キーにし、10進数のレートを numeric 列に保存します。できあがった fx.csv は、専用のステージングテーブルで読み込みます。

為替レートを取得する
get() {
  curl -sf -H "Authorization: Bearer $NARWHAL_API_KEY" \
    "https://api.narwhalapi.com$1"
}

get "/v1/fx/rates/USD?currencies=EUR,IDR" \
  | jq -r '.rates[] | [.currency, .rate, .timestamp] | @csv' > fx.csv

Postgres の予測市場のオッズ

Federal Reserve の政策金利パスをリクエストし、meetings を読みます。CSV の各行には、会合ごとの resolves_at、p_cut、p_hold、p_hike が入ります。出力は fed.csv に書き込まれます。この読み込みを予測市場のオッズのテーブルに合わせるときは、ステージングの列を同じ順序で定義し、10進数の値には numeric を使います。

政策金利パスの会合ごとのオッズを取得する
get() {
  curl -sf -H "Authorization: Bearer $NARWHAL_API_KEY" \
    "https://api.narwhalapi.com$1"
}

get /v1/predictions/policy-paths/federal-reserve \
  | jq -r '.meetings[] | [.resolves_at, .p_cut, .p_hold, .p_hike] | @csv' > fed.csv

祝日テーブルに直接コピーすると失敗することがあるのはなぜですか。

\copy は、キーが重複すると失敗します。一時的なステージングテーブルなら、挿入で重複を解決する前に行を受け取れます。祝日の例では、1つのファイルに同じ日付が繰り返し含まれる場合、日付と名前の並び順によってどの名前が残るかが決まります。そのあと、アップサートが保存先にすでにある日付を処理します。

価格はどのように保存しますか。

10進数は文字列で届きます。価格を Postgres に読み込むときは、numeric にキャストしてください。CSV は転送用の形式で、価格がデータベースにどう保存されるかは保存先の列で決まります。これらのエクスポートの CPI の値と為替レートにも、同じ10進数列の選び方を使ってください。

公開。

次のステップ