حساب أيام التسوية بين دولتين عند اختلاف العطل

يجب على المكتب الخلفي لشركة وساطة تُسوّي صفقة بين بلدين أن يختار يومًا يكون فيه البلدان مفتوحين، لذا تُزيح عطل كل عملة التاريخ. يعيد Narwhal العطل الرسمية لكل بلد مع نطاقها ومناطقها الفرعية، ويستطيع سكربت قصير تمرير سجل صفقات كامل على التقويمين وتمييز كل صفقة يختلف تاريخها عن العدّ بأيام الأسبوع فقط.

لماذا تحتاج الصفقة العابرة للحدود إلى تقويمين للعطل

يحتاج المكتب الخلفي لشركة وساطة تُسوّي صفقة USD/JPY إلى يوم يكون فيه البلدان اليابان والولايات المتحدة مفتوحين. يكون العدّ بأيام الأسبوع فقط خاطئًا كلما وقعت عطلة لأي من البلدين داخل المدة، وتعليمات التسوية المنحرفة بيوم واحد تفشل أو تصل متأخرة. تجيب نقاط نهاية العطل عن بلد واحد في كل مرة، لذا يسأل المكتب الخلفي عن كل طرف ثم يدمج النتائج. يسأل هذا الطلب هل لدى اليابان عطلة في 23 نوفمبر 2026.

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 الفارغة أنه ينطبق على البلد كله. ويعيد الطلب نفسه للولايات المتحدة في 26 نوفمبر Thanksgiving Day بنطاق federal_government. لكل بلد قائمته ونطاقها الخاص، لذا يسجّل المكتب الخلفي أي قائمة يعتمد عليها. أما العدّ بأيام الأسبوع وحده فيظل يعدّ يوم الاثنين 23 نوفمبر يوم تسوية.

تمرير سجل الصفقات على التقويمين

يُسوّي السكربت كل صفقة في سجل الصفقات وفق بلدي عملتيها، ويعرض التاريخ الذي كان سيعطيه العدّ بأيام الأسبوع فقط بجانب التاريخ الفعلي. وتوسَم الصفقة التي يختلف فيها التاريخان بـ CHECK، وهذه هي القائمة التي يراجعها مسؤول العمليات.

  1. تحديد بلدي كل طرف تُدرج JPY اليابان والولايات المتحدة، وتُدرج GBP المملكة المتحدة مع المنطقة الفرعية لمكتب التداول GB-ENG والولايات المتحدة.
  2. تحميل كل سنة مرة واحدة تجلب holidays قائمة بلد ما لسنة معينة وتحتفظ بها، فيحتاج سجل من مئات الصفقات إلى عدد قليل من الطلبات. وتحمّل الصفقة القريبة من 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

الصفقة الأولى يوم الجمعة 20 نوفمبر، وكانت ستُسوّى يوم الثلاثاء 24 نوفمبر بأيام الأسبوع وحدها. اليابان مغلقة يوم الاثنين 23 نوفمبر، فينتقل اليوم الثاني إلى الأربعاء 25 نوفمبر. وتتأخر الصفقة الثانية بسبب Thanksgiving Day الأمريكي، وتتأخر الثالثة بسبب Christmas Day في البلدين وBoxing Day في المملكة المتحدة إلى الاثنين 28 ديسمبر. كل سطر في هذا السجل يختلف عن العدّ بأيام الأسبوع.

ما يزال المكتب الخلفي يراجعه يدويًا

تحقّقالمصدر
عطلة نهاية الأسبوعالحلقة التي تتخطى السبت والأحد
العطل الرسمية لبلد كل عملةنقاط نهاية العطل، بلد واحد لكل طرف
عطلة إقليمية في مكتب الحجزمقارنة subdivision_codes بالمنطقة الفرعية للمكتب
إغلاقات البورصة أو نظام الدفعقائمة المنصة نفسها، تُضاف إلى المجموعة التي تفحصها الحلقة
عدد الأيام، T+1 أو T+2قواعد المنتج والمنصة، وهي مما لا تحدده الـ API

يبقى الصفان الأخيران على عاتق المكتب الخلفي، لأن قائمة العطل تخص بلدًا وليس منصة.

تنبيه المتداول عند وجود إغلاق قرب الصفقة

يعيد GET /v1/calendars/holidays/{country}/next?from_date=2026-11-20 أول عطلة في ذلك التاريخ أو بعده داخل كائن holiday. وأعاد لليابان 23 نوفمبر وللولايات المتحدة 26 نوفمبر، وكلاهما داخل نافذة T+2. شغّله لكل طرف عند حجز الصفقة وأخبر المتداول بأن إغلاقًا قادم. واستخدم قائمة السنة للتحقق من التاريخ نفسه.

هل تطابق القائمة تقويم البورصة أو نظام الدفع؟

تسرد القائمة العطل الرسمية لبلد ما مع نطاقها ومناطقها الفرعية، ولا يظهر فيها إغلاق لا يوجد إلا في بورصة أو نظام دفع. تضم قائمة الولايات المتحدة لعام 2026 ما مجموعه 11 إدخالًا ولا تشمل Good Friday في 3 أبريل، وهو يوم تغلق فيه بعض البورصات. أضف إغلاقات المنصة إلى المجموعة التي تفحصها الحلقة.

ماذا يحدث إذا لم يكن لبلد ما تقويم لتلك السنة؟

تعيد الـ API استجابة مشكلة 404 بالرمز calendar_not_published، وهذا ما حدث مع طلب المملكة المتحدة لعام 2028. يوقف raise_for_status() السكربت، وهذا سلوك آمن لتعليمات لا يجوز أن تخرج خاطئة. قرّر هل تعود إلى أيام الأسبوع مع وسم التاريخ، أم تنتظر.

ما الأيام التي يجب أن يتخطاها زوج العملات؟

يُتخطى اليوم إذا كان أي من البلدين مغلقًا. تنتظر صفقة USD/JPY يومًا يكون فيه كل من طوكيو والولايات المتحدة مفتوحًا. تحقق من عُرف المنتج، لأن T+1 أو T+2 وأي استثناء لليوم الوسيط يأتيان من قواعد السوق التي لا تذكرها الـ API.

نُشر في .

الخطوات التالية