结算日工作日怎么算:两国假日不同的跨境交易

在两个国家之间结算交易的券商后台,必须把结算日放在两国都营业的一天,所以每种货币对应国家的节假日都会让日期顺延。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 不会给出,所以请核对产品的惯例。

发布于。

后续步骤