兩國假日不同時,如何計算跨境交易的交割日

在兩個國家之間交割交易的券商後台,必須把交割日放在兩國都營業的一天,所以每種貨幣對應國家的假日都會讓日期順延。Narwhal 會回傳每個國家的國定假日,並附上適用範圍和行政區劃;一個簡短的腳本就能把整份交易清單對照兩套日曆,並標出所有與單純按平日計算結果不同的交易。

跨境交易為什麼需要兩套假日日曆

交割 USD/JPY 交易的券商後台,需要找到日本和美國都營業的一天。只要期間內任一國家有假日,只按平日計數就會出錯,而差一天的交割指示要麼失敗,要麼延遲送達。假日端點一次只回答一個國家,所以後台要對每一條腿分別請求,再合併結果。下面的請求詢問日本在 2026 年 11 月 23 日是否有假日。

curl,查詢某一天的日本假日
curl -s -H "Authorization: Bearer $NARWHAL_API_KEY" \
  "https://api.narwhalapi.com/v1/calendars/holidays/JPN/on/2026-11-23"
回應
{
  "country": "JPN",
  "coverage": [
    {
      "scope": "national_public",
      "subdivision_codes": []
    }
  ],
  "holidays": [
    {
      "date": "2026-11-23",
      "name": "Labor Thanksgiving Day",
      "holiday_key": "labor_thanksgiving_day",
      "local_name": "勤労感謝の日",
      "scope": "national_public",
      "subdivision_codes": []
    }
  ]
}

回傳的項目是 Labor Thanksgiving Day,scope 為 national_public,subdivision_codes 清單為空表示全國適用。對美國 11 月 26 日送出同樣的請求,會回傳 scope 為 federal_government 的 Thanksgiving Day。每個國家的清單都有自己的 scope,所以後台要記錄自己依據的是哪一份清單。只按平日計數的話,11 月 23 日週一仍會被當作交割日。

讓交易清單對照兩套日曆

腳本依每筆交易兩種貨幣所屬國家的日曆來交割,並把僅按平日計數得到的日期與實際日期並排列出。兩者不同的交易會標記為 CHECK,這就是營運主管要覆核的清單。

  1. 指定每條腿所屬的國家 JPY 列出日本和美國,GBP 列出英國(交易台所在的行政區劃為 GB-ENG)和美國。
  2. 每年只載入一次 holidays 取得一個國家某一年的清單並快取起來,所以幾百筆交易的清單也只需送出寥寥幾次請求。臨近 12 月 31 日的交易,在逐日推進到下一年時才會載入下一年的資料。
  3. 跳過週末和任一國家的休市日 closures 回傳落在所列任一國家當天的假日,只有這份清單為空的日子才計入 N 天。帶有行政區劃清單的假日,只有當交易台所在的區劃在清單中時才會讓交易台休市。
    Python,兩個貨幣對的交割交易清單
    import os
    from datetime import date, timedelta
    from functools import cache
    import requests
    
    HEADERS = {"Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"}
    
    
    @cache
    def holidays(country, year):
        r = requests.get(
            f"https://api.narwhalapi.com/v1/calendars/holidays/{country}/{year}",
            headers=HEADERS,
            timeout=10,
        )
        r.raise_for_status()
        return r.json()["holidays"]
    
    
    def closures(day, places):
        out = []
        for country, region in places.items():
            for h in holidays(country, day.year):
                # an empty subdivision list means the holiday applies nationwide
                if h["date"] == day.isoformat() and (not h["subdivision_codes"] or region in h["subdivision_codes"]):
                    out.append(f"{country} {h['name']}")
        return out
    
    
    def settle(trade, n, places):
        day, held = trade, []
        while n > 0:
            day += timedelta(1)
            if day.weekday() >= 5:
                continue
            shut = closures(day, places)
            if shut:
                held.append(f"{day:%d %b} {'; '.join(shut)}")
            else:
                n -= 1
        return day, held
    
    
    JPY = {"USA": None, "JPN": None}
    GBP = {"GBR": "GB-ENG", "USA": None}  # country -> subdivision of the desk
    blotter = [
        ("USD/JPY", date(2026, 11, 20), 2, JPY),
        ("USD/JPY", date(2026, 11, 24), 2, JPY),
        ("GBP/USD", date(2026, 12, 23), 2, GBP),
    ]
    for pair, trade, n, places in blotter:
        day, held = settle(trade, n, places)
        plain, _ = settle(trade, n, {})
        flag = "CHECK" if day != plain else "same"
        print(f"{pair} {trade} T+{n} settles {day}, weekdays only {plain} [{flag}]", "; ".join(held))
腳本輸出
USD/JPY 2026-11-20 T+2 settles 2026-11-25, weekdays only 2026-11-24 [CHECK] 23 Nov JPN Labor Thanksgiving Day
USD/JPY 2026-11-24 T+2 settles 2026-11-27, weekdays only 2026-11-26 [CHECK] 26 Nov USA Thanksgiving Day
GBP/USD 2026-12-23 T+2 settles 2026-12-29, weekdays only 2026-12-25 [CHECK] 25 Dec GBR Christmas Day; USA Christmas Day; 28 Dec GBR Boxing Day

第一筆交易在 11 月 20 日週五,僅按平日計算會在 11 月 24 日週二交割。由於日本 11 月 23 日週一休市,第二天順延到 11 月 25 日週三。第二筆交易被美國的 Thanksgiving Day 順延,第三筆則因兩國的 Christmas Day 以及英國的 Boxing Day 順延到 12 月 28 日週一。這份清單中的每一行都與單純按平日計算的結果不同。

後台仍需人工核對的事項

檢查來源
週末跳過週六和週日的迴圈
各貨幣所屬國家的國定假日假日端點,每條腿查一個國家
交易台所在地區的地區性假日將 subdivision_codes 與交易台的行政區劃比對
交易所或支付系統的休市日把該場所自己的清單加入迴圈檢查的集合
天數,T+1 還是 T+2產品和交易場所的規則,API 不作規定

最後兩行仍由後台負責,因為假日清單屬於國家,而不屬於某個交易場所。

交易日期附近有休市日時提醒交易員

GET /v1/calendars/holidays/{country}/next?from_date=2026-11-20 會在 holiday 物件中回傳該日期當天或之後的第一個假日。日本回傳的是 11 月 23 日,美國回傳的是 11 月 26 日,兩者都落在 T+2 期間內。每次登錄交易時,對每條腿各呼叫一次,並告知交易員即將有休市日。判斷日期本身時,請使用整年的清單。

這份清單與交易所或支付系統的日曆一致嗎?

它列出一個國家的假日,附上適用範圍和行政區劃;只在交易所或支付系統存在的休市日不在其中。2026 年的美國清單有 11 個項目,其中沒有 4 月 3 日的 Good Friday,而部分交易所在這一天休市。請把交易場所的休市日加入迴圈檢查的集合。

某個國家當年沒有日曆時會怎樣?

API 會回傳 404 問題回應,代碼為 calendar_not_published。英國 2028 年的請求就是這樣。raise_for_status() 會讓腳本停下,對於不容出錯的指示,這是安全的行為。請決定是退回到按平日計算並標記該日期,還是等待。

貨幣對應當跳過哪些日子?

任一國家休市的日子都要跳過。USD/JPY 交易要等到東京和美國都營業的一天。T+1 還是 T+2,以及中間那一天有無例外,都由市場規則決定,API 不會給出,所以請核對產品的慣例。

發布於 。

後續步驟