mcpField
E
exchange-session-detector

exchange-session-detector

github.com/terrylica数据与数据库165 次安装今天更新
代码仓库

关于 exchange-session-detector

用于在时间序列数据中准确识别交易时段和节假日的 Skill,面向需要替换简单小时范围判断的开发者,涵盖夏令时、午休和提前收市。

主要功能

  1. 0110 个交易所 MIC 注册表
  2. 02支持夏令时的时段识别
  3. 03处理节假日与午休
  4. 04预计算分钟并查找
  5. 05ClickHouse 时段 SQL 模式

适用场景

  1. 01为 DataFrame 添加交易时段标记
  2. 02识别交易所节假日
  3. 03在 ClickHouse 中分类时段
  4. 04升级固定小时范围判断

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/terrylica/cc-skills --skill exchange-session-detector

安装后在 Claude Code 中输入/exchange-session-detector确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

evals/
evals.json
references/
clickhouse-session-sql.md
exchange-registry.md
session-detector-pattern.md

详细介绍

交易时段检测器

用于检测交易所交易时段的生产级模式,完整支持夏令时、节假日和午休时段。已在 exness-data-preprocess 中通过 10 家全球交易所的验证。

自我演进技能:此技能会在使用过程中不断改进。如果说明有误、参数发生偏移,或需要采用变通方案,请立即修复此文件,不要拖延。仅针对真实且可复现的问题进行更新。

适用场景

  • 为时间序列 DataFrame 添加时段标记(is_nyse_session、is_lse_session 等)
  • 检测时间戳是否处于任意主要交易所的交易时段内
  • 检查节假日(NYSE、LSE,或两者均休市时的“主要节假日”)
  • 处理亚洲交易所的午休时段(Tokyo、Hong Kong、Singapore)
  • 将简单的小时范围检查升级为生产级准确度
  • 为时段分类构建 ClickHouse 物化列

架构概览

ExchangeConfig registry (exchanges.py)     SessionDetector (session_detector.py)
┌──────────────────────────────────┐      ┌──────────────────────────────────────┐
│ 10 frozen dataclasses            │      │ Wraps exchange_calendars library     │
│ ISO 10383 MIC codes              │─────▶│ Pre-computes trading minutes (sets)  │
│ IANA timezones for DST           │      │ Vectorized .isin() lookup (2.2x)    │
│ Local open/close hours           │      │ Holiday detection (NYSE + LSE)       │
└──────────────────────────────────┘      └──────────────────────────────────────┘

快速入门

import exchange_calendars as xcals
import pandas as pd

# Single-exchange check
cal = xcals.get_calendar("XNYS")  # NYSE via ISO 10383 MIC
cal.is_open_on_minute(pd.Timestamp("2024-07-04 14:30", tz="UTC"))  # False (July 4th)
cal.is_open_on_minute(pd.Timestamp("2024-07-05 14:30", tz="UTC"))  # True

# Full session detection across 10 exchanges
from session_detector import SessionDetector
detector = SessionDetector()
df = detector.detect_sessions_and_holidays(dates_df)
# Adds: is_us_holiday, is_uk_holiday, is_major_holiday, is_{exchange}_session

时段检测的两个层级

第 1 层:简单的小时范围(大多数项目的起点)
# Pattern from opendeviationbar/ouroboros.py
EXCHANGE_SESSION_HOURS = {
    "sydney":  {"tz": "Australia/Sydney",   "start": 10, "end": 16},
    "tokyo":   {"tz": "Asia/Tokyo",         "start":  9, "end": 15},
    "london":  {"tz": "Europe/London",      "start":  8, "end": 17},
    "newyork": {"tz": "America/New_York",   "start": 10, "end": 16},
}

def is_in_session(session_name, timestamp_utc):
    info = EXCHANGE_SESSION_HOURS[session_name]
    tz = zoneinfo.ZoneInfo(info["tz"])
    local_time = timestamp_utc.astimezone(tz)
    if local_time.weekday() >= 5:
        return False
    return info["start"] <= local_time.hour < info["end"]

可正确处理:通过 zoneinfo 转换夏令时,并排除周末。

无法处理:

  • 节假日(圣诞节、感恩节、银行假日)
  • 午休时段(Tokyo 11:30-12:30、HK 12:00-13:00、SGX 12:00-13:00)
  • 半日交易/提前收市时段
  • 小时以下的精度(NYSE 在 9:30 开市,而非 10:00;LSE 在 16:30 收市,而非 17:00)
  • 交易所交易时间变更(Tokyo 于 2024 年 11 月 5 日延长至 15:30)
第 2 层:exchange_calendars(生产级)

exchange_calendars 库(持续维护,可通过 pip 安装,支持 50 多家交易所)会通过 is_open_on_minute() 自动处理以上所有情况。该库内部使用 IANA 时区数据,因此无需任何手动逻辑即可正确处理夏令时转换。

阅读 references/exchange-registry.md,了解包含 MIC 代码、时区和开市/收市时间的完整 10 家交易所注册表。

阅读 references/session-detector-pattern.md,了解完整的 SessionDetector 实现模式,其中包含预计算交易分钟和向量化查找。

交易所注册表

通过 ISO 10383 MIC 代码支持 10 家交易所:

交易所MIC 代码时区交易时间(当地)午休时段
NYSEXNYSAmerica/New_York09:30 - 16:00-
LSEXLONEurope/London08:00 - 16:30-
SIXXSWXEurope/Zurich09:00 - 17:30-
FWBXFRAEurope/Berlin09:00 - 17:30-
TSXXTSEAmerica/Toronto09:30 - 16:00-
NZXXNZEPacific/Auckland10:00 - 16:45-
JPXXTKSAsia/Tokyo09:00 - 15:0011:30 - 12:30 JST
ASXXASXAustralia/Sydney10:00 - 16:00-
HKEXXHKGAsia/Hong_Kong09:30 - 16:0012:00 - 13:00 HKT
SGXXSESAsia/Singapore09:00 - 17:0012:00 - 13:00 SGT

新增交易所只需进行一项更改:向注册表字典添加一个 ExchangeConfig 条目。SessionDetector、架构生成和列命名都会自动同步更新。

性能:预计算交易分钟

朴素做法是针对每个时间戳和每家交易所调用一次 calendar.is_open_on_minute(),复杂度为 O(N * E),且常数因子较高。经过验证的模式会将所有交易分钟预先计算到集合中,以实现 O(1) 查找:

# Pre-compute once (startup cost, amortized over millions of lookups)
trading_minutes = detector._precompute_trading_minutes(start_date, end_date)
# Returns: {"nyse": {ts1, ts2, ...}, "lse": {ts1, ts2, ...}, ...}

# Vectorized lookup via pandas .isin() — 2.2x faster than per-row .apply()
df["is_nyse_session"] = df["ts"].isin(trading_minutes["nyse"]).astype(int)

预计算过程本身会在内部使用 is_open_on_minute(),因此午休时段、节假日和交易时间变更都会得到正确处理。

节假日检测

# NYSE holidays (excludes weekends — only official closures)
nyse_holidays = {
    pd.to_datetime(h).date()
    for h in calendar.regular_holidays.holidays(start=start, end=end, return_name=False)
}

# Major holiday = both NYSE AND LSE closed
df["is_major_holiday"] = ((df["is_us_holiday"] == 1) & (df["is_uk_holiday"] == 1)).astype(int)

ClickHouse 集成

对于服务端会话检测(例如物化列),使用 IANA 时区名称时,ClickHouse 的 toTimezone() 会自动处理夏令时:

-- DST-aware hour extraction (matches Python zoneinfo behavior)
ALTER TABLE my_table
UPDATE is_nyse_session = if(
    toHour(toTimezone(toDateTime(intDiv(close_time_ms, 1000)), 'America/New_York')) >= 9
    AND toHour(toTimezone(toDateTime(intDiv(close_time_ms, 1000)), 'America/New_York')) < 16
    AND toDayOfWeek(toTimezone(toDateTime(intDiv(close_time_ms, 1000)), 'America/New_York')) <= 5,
    1, 0
) WHERE 1 = 1

限制:ClickHouse 的 toTimezone() 可以处理夏令时,但无法处理节假日或午休时间。对于这些情况,请在 Python 中计算并将标记写回,或在 ClickHouse 中维护节假日日历表。

升级路径:从 Hour-Range 升级到 exchange_calendars

  1. pip install exchange_calendars(或添加到 pyproject.toml)
  2. 将固定小时数字典替换为 ExchangeConfig 注册表(参见 references/exchange-registry.md)
  3. 将 zoneinfo 小时检查替换为 SessionDetector.detect_sessions_and_holidays()
  4. 更新测试,覆盖:节假日、午休时间、夏令时切换、提前收盘

exchange_calendars 库安装后约占 10MB,除 pandas 和 numpy 外没有重型依赖。日历数据已打包(运行时不会发起网络请求)。

参考资料

文件内容
exchange-registry.md完整的 ExchangeConfig 注册表,采用 frozen dataclass 模式
session-detector-pattern.md完整的 SessionDetector 类,包含预计算分钟数
clickhouse-session-sql.md用于服务端会话检测的 ClickHouse SQL 模式

来源

经过验证的实现:~/eon/exness-data-preprocess/src/exness_data_preprocess/session_detector.py + exchanges.py

简化版前身:<project>/python/<package>/ouroboros.py(仅 Tier 1)

执行后复盘

此技能完成后,在结束前检查:

  1. 命令是否成功? — 如果没有,请修复导致失败的指令或错误表。
  2. 参数或输出是否发生变化? — 如果底层工具的接口发生变化,请更新 Usage 示例和 Parameters 表,使其保持一致。
  3. 是否需要变通方案? — 如果你不得不临时调整(更换标志、增加步骤),请更新此 SKILL.md,以免下次调用时重复采用相同的变通方案。

只有在问题真实且可复现时才更新,不要基于推测进行更新。

评论

支持 Markdown