向交易台或值班團隊傳送經濟數據公布提醒

要減碼的交易台、要暫停作業的值班工程師、要向同仁通報狀況的班長,在數據公布前需要的資訊是一樣的:UTC 時間與當地時間、所屬期間以及前值。Narwhal 經濟日曆會回傳這四項,再用一支簡短的排程腳本,就能為每次公布產生一行訊息。

公布前提醒需要包含什麼

在重要數據公布前,交易台要降低風險,值班工程師要暫停批次作業,班長要向同仁通報狀況。三者依據的是同樣的事實:數據何時公布、涵蓋哪個期間、上一次的數值是多少。身處其他城市的同仁還需要自己時區的時間,因為只寫「13:30 UTC」的訊息會讓他們在緊張時還得自己換算。GET /v1/economics/calendar 會回傳這些事實。這個請求取得美國在 11 月 10 日的數據。

curl,某一天的美國數據公布
curl -s -H "Authorization: Bearer $NARWHAL_API_KEY" \
  "https://api.narwhalapi.com/v1/economics/calendar?countries=USA&start_date=2026-11-10&end_date=2026-11-10&limit=100"
回應
{
  "releases": [
    {
      "release_id": "66f7f9f6-0318-4f25-8896-541c428ee07e",
      "revision": 2,
      "country": "USA",
      "series_id": "usa-wages-and-earnings",
      "name": "Wages and earnings",
      "topic": "wages",
      "family": "labour",
      "period": "2026-10",
      "status": "scheduled",
      "at": "2026-11-10T13:30:00Z",
      "timezone": "America/New_York",
      "values": [
        {
          "measure": "real_average_hourly_earnings_mom",
          "concept": "real_average_hourly_earnings",
          "unit": "percent",
          "transformation": "month_over_month",
          "previous": "-0.5"
        },
        {
          "measure": "real_average_hourly_earnings_yoy",
          "concept": "real_average_hourly_earnings",
          "unit": "percent",
          "transformation": "year_over_year",
          "previous": "-0.7"
        }
      ]
    },
    {
      "release_id": "f01e2289-2e17-49b3-9d64-d29118742dee",
      "revision": 3,
      "country": "USA",
      "series_id": "usa-consumer-prices",
      "name": "Consumer prices",
      "topic": "consumer_prices",
      "family": "prices",
      "period": "2026-10",
      "status": "scheduled",
      "at": "2026-11-10T13:30:00Z",
      "timezone": "America/New_York",
      "values": [
        {
          "measure": "core_cpi_yoy",
          "concept": "core_cpi",
          "unit": "percent",
          "transformation": "year_over_year",
          "previous": "2.6",
          "not_seasonally_adjusted": true
        },
        {
          "measure": "cpi_mom",
          "concept": "cpi",
          "unit": "percent",
          "transformation": "month_over_month",
          "previous": "0.6"
        },
        {
          "measure": "cpi_yoy",
          "concept": "cpi",
          "unit": "percent",
          "transformation": "year_over_year",
          "previous": "3.7",
          "not_seasonally_adjusted": true
        }
      ]
    }
  ],
  "next_cursor": null
}

at 是以 UTC 表示的公布時間。period 說明數據所屬的月份,values[].previous 保存每項指標上一次公布的數值及其 unit。回應只列出前值,不含預測值,需要市場共識的交易台可從自己的資料來源補上。在數據公布之前,status 一直是 scheduled。

為每次公布產生一行提醒

下面的腳本適合排程執行,例如每天早上一次,會為未來 24 小時內的每次公布各列印一行。

  1. 設定交易台時區與國家 DESK_TZ 是同仁閱讀訊息所用的時區,COUNTRIES 列出交易台所交易或依賴的經濟體。
  2. 請求帶餘裕的日期視窗 日期篩選依據各公布機構的當地日期,所以腳本請求的範圍是從今天的前一天到後兩天,再依 at 本身篩選。
  3. 只保留尚未到來的公布 保留一次公布的條件是:狀態為 scheduled,有 at 時間,且該時間落在現在到提前量之間。NOW 是選用變數,可用來以固定時鐘進行測試。
  4. 轉換時間並附上前值 astimezone 會把 UTC 時間轉換成交易台的時區,所以任何一邊調整了時鐘,都不需要手動計算偏移。前值來自 values。
    Python,公布前提醒的一行
    import os
    from datetime import datetime, timedelta, timezone
    from zoneinfo import ZoneInfo
    import requests
    
    DESK_TZ = ZoneInfo("Europe/Zurich")
    COUNTRIES = ["USA", "EMU"]
    LEAD = timedelta(hours=24)
    now = datetime.fromisoformat(os.environ["NOW"]) if "NOW" in os.environ else datetime.now(timezone.utc)
    
    r = requests.get(
        "https://api.narwhalapi.com/v1/economics/calendar",
        params={
            "countries": COUNTRIES,
            "start_date": (now - timedelta(days=1)).date().isoformat(),
            "end_date": (now + timedelta(days=2)).date().isoformat(),
            "limit": 100,
        },
        headers={"Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"},
        timeout=10,
    )
    r.raise_for_status()
    
    due = []
    for x in r.json()["releases"]:
        if x["status"] != "scheduled" or "at" not in x:
            continue
        at = datetime.fromisoformat(x["at"].replace("Z", "+00:00"))
        if now <= at < now + LEAD:
            due.append((at, x))
    
    for at, x in sorted(due, key=lambda t: t[0]):
        prev = ", ".join(f"{v['measure']} {v['previous']}" for v in x["values"] if "previous" in v)
        print(f"{at:%H:%M} UTC / {at.astimezone(DESK_TZ):%H:%M} {DESK_TZ.key} | "
              f"{x['country']} {x['name']} {x.get('period', '-')} | previous: {prev or 'none listed'}")

把 NOW 設為 11 月 10 日 09:00 UTC 後,腳本列印了兩行。那天蘇黎世比 UTC 早一小時,所以 13:30 UTC 顯示為 14:30。兩項美國數據的公布時間相同,想只發一則訊息的交易台可以依 at 值把這些行分組。

NOW 設為 2026-11-10T09:00:00+00:00 時的輸出
13:30 UTC / 14:30 Europe/Zurich | USA Wages and earnings 2026-10 | previous: real_average_hourly_earnings_mom -0.5, real_average_hourly_earnings_yoy -0.7
13:30 UTC / 14:30 Europe/Zurich | USA Consumer prices 2026-10 | previous: core_cpi_yoy 2.6, cpi_mom 0.6, cpi_yoy 3.7

讓提醒匹配閱讀它的人

閱讀者公布前的動作提醒需要的內容
交易員減碼或避險UTC 與當地時間、前值
值班工程師在該分鐘前後暫停部署或批次作業確切的 at 時間,以及用來確認仍按計畫進行的 status
班長向同仁通報即將發生的事公布名稱、period 與前值

把這些行傳送到團隊已經在看的管道即可。API 提供事實,傳送則交給你自己的聊天或郵件工具。像排定每日資料擷取那樣用排程器執行腳本,執行頻率至少要和你想要的提前量一樣高。

在公布時間變動時保持提醒正確

發出早間清單之後,公布時間可能會變。每個日曆項目都有一個 revision,詳細資料變動時它會遞增,所以在公布前不久重新讀取日曆的腳本,可以把目前的 revision 與已傳送的 revision 比對。若要用推送方式,Webhook 會回報 release.scheduled、release.rescheduled 與 release.cancelled,請見接收 Webhook。Webhook 在時程變動時送達,不帶倒數計時,所以提前量仍由你自己的計時器決定。

只想要手機提醒的同仁,可以讓日曆 App 訂閱透過 POST /v1/calendars/subscriptions 建立的訂閱源。請求需要 countries、start_date 與 end_date,回應裡的 url 只回傳一次,請當作金鑰保存。這個呼叫會建立資源,所以本頁只做說明而不執行。完整請求見日曆訂閱文件。

如果公布還沒有確切時間怎麼辦?

有些公布帶的是 date、between 或 by,而不是 at。腳本無法把它們放到具體的鐘點上,所以會跳過。可以把它們列在單獨的早間備註裡,讓交易台知道有的公布可能沒有固定的分鐘。

API 能自己傳送提醒嗎?

沒有任何端點會依時間傳送提醒。提醒來自日曆 App、你自己的排程腳本,或是一個會啟動自有計時器的 Webhook 接收端。

為什麼腳本要請求今天前後的日期?

日期視窗依據公布機構的當地日期。東京或雪梨的公布,其日曆日期可能與 UTC 時間不同,所以請求時要放寬範圍,由 at 決定哪些公布到期。

發布於 。

後續步驟