將 Narwhal 資料匯入 Postgres

你可以把 Narwhal 的國定假日、發布日期、經濟資料、大宗商品現貨價格、匯率和預測市場賠率匯入 Postgres。用 curl 取得 JSON,用 jq 轉成 CSV,再用 psql 載入暫存表並 upsert 資料列。

你將完成的設定

在這個工作流程中,Postgres 是資料的目的地,最後你會得到每個資料領域各自的 CSV 檔案,以及一張支援重複匯入的國定假日資料表。Postgres 本身無法擷取 HTTP 內容,所以請求要在匯入資料庫之前於 shell 中完成。你需要 curl、jq 和 psql。擷取指令共用一個輔助函式來處理 API URL 和授權標頭;資料庫範例會先使用暫存表,再寫入國定假日資料表。匯出時,國定假日、發布日期、CPI、大宗商品價格、匯率和政策利率路徑賠率分別存成獨立的檔案,並為每個領域挑選對應的回應欄位。

設定你的 API 金鑰

  1. 建立免費金鑰 在 Narwhal 註冊頁 建立你的免費金鑰。Narwhal 用同一個帳號和同一把 API 金鑰涵蓋國定假日、經濟日曆、經濟資料、大宗商品現貨價格、匯率和預測市場賠率。
  2. 把金鑰存入環境變數 在執行擷取指令的 shell 中,把金鑰存放在名為 NARWHAL_API_KEY 的環境變數裡。輔助函式每次傳送請求時都會讀取這個變數,所以同一把金鑰適用於所有 CSV 匯出。
  3. 使用共用的請求輔助函式 這些指令透過 Authorization: Bearer YOUR_KEY 標頭,把金鑰傳送到 https://api.narwhalapi.com。REST 和 MCP 共用同一把金鑰。對於這個 Postgres 工作流程,請先在 shell 輔助函式中使用 REST 請求,再透過 psql 載入產生的檔案。

用程式碼取得資料

  1. 把每個領域擷取成 CSV 執行 shell 指令請求各個領域,並用 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 會去掉同一次匯入中重複的日期。如果目的資料表中已有某個日期,ON CONFLICT 會更新它的名稱。其他 CSV 檔案也可以使用同樣的匯入模式,只要採用與其欄位相符的資料表和主鍵。國定假日目的資料表有一個型別為 date 的 date 欄和一個型別為 text 的 name 欄。它的暫存表與 CSV 的欄位順序相同。
    第 2 步,用暫存表和 upsert 匯入國定假日
    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。由於匯入使用 upsert,重新執行是安全的:已有的國定假日日期會更新名稱。對於其他檔案,請使用各自的主鍵,而不是原樣照搬國定假日的主鍵。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 當作目的資料表的主鍵。數值以十進位字串的形式回傳,所以匯入 Postgres 時請使用 numeric 欄。period 欄用來辨識 upsert 要更新的觀測值。

取得 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 一起當作主鍵,並把十進位匯率存入 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 中的預測市場賠率

請求美國聯準會政策利率路徑並讀取 meetings。CSV 的每一列保留某次會議的 resolves_at、p_cut、p_hold 和 p_hike。輸出寫入 fed.csv。把這個匯入改成預測市場賠率資料表時,請依同樣的順序定義暫存欄,並對十進位數值使用 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 遇到重複的鍵會失敗。暫存表會先接收這些資料列,再由插入陳述式處理重複。在國定假日範例中,如果單一檔案裡有重複的日期,日期和名稱的排序決定了保留哪個名稱。之後,upsert 會處理目的資料表中已有的日期。

價格應該怎麼儲存?

十進位數以字串形式回傳。把價格匯入 Postgres 時,請將其轉型為 numeric。CSV 只是傳輸格式;價格在資料庫中如何儲存,由目的欄位決定。這些匯出中的 CPI 數值和匯率也請採用同樣的十進位欄位做法。

發布於 。

後續步驟