☰
tf-quant-finance 日期模块中的 WeekendMask:周末掩码定义与假日日历实战指南
2026/10/13 2:09:17 网站建设 项目流程
  • 金融科技
  • 科学计算

【免费下载链接】tf-quant-finance

High-performance TensorFlow library for quantitative finance.

项目地址:https://gitcode.com/gh_mirrors/tf/tf-quant-finance
点击查看免费下载

导读

WeekendMask是 tf-quant-finance 日期模块(tff.datetime)中用于声明"一周内哪些天算作周末"的核心常量类。在构建HolidayCalendar(假日日历)时,通过weekend_mask参数传入掩码即可让工作日计算、日期滚动(roll)与息票/期限日程(schedule)自动跳过周末。读完本文,你将掌握WeekendMask四个预置掩码的确切语义、与WeekDay的索引对齐关系,以及如何在create_holiday_calendar、PeriodicSchedule等场景中组合使用它与自定义掩码。

WeekendMask 是什么

WeekendMask定义于日期模块的常量文件中(tf_quant_finance/datetime/constants.py),其官方 API 文档(api_docs/tf_quant_finance/datetime/WeekendMask.md)给出的描述是:"Provides weekend masks for some of the common weekend patterns."(为一些常见周末模式提供周末掩码)。

在 tf-quant-finance 中,周末被当作一种特殊的节假日处理——抽象基类HolidayCalendar的文档明确指出 "Weekends are treated as holidays"(周末视同节假日)。因此,一个掩码本质上定义了每个日历日是否是"工作日"的基准规则,再叠加法定节假日后,就构成了完整的非交易日集合。

WeekendMask虽然名称像枚举,但其源码实现是一个普通类,四个类属性各是一个长度为 7 的整数元组(0 表示工作日,1 表示休息日),索引 0 对应周一:

类变量掩码值(周一→周日)适用地区(源码注释)语义
SATURDAY_SUNDAY(0, 0, 0, 0, 0, 1, 1)美、英、欧洲等("US/UK/Europe etc.")周六、周日为周末
FRIDAY_SATURDAY(0, 0, 0, 0, 1, 1, 0)中东多数国家("Most countries in the Middle East")周五、周六为周末,周日是工作日
SUNDAY_ONLY(0, 0, 0, 0, 0, 0, 1)印度、尼泊尔("India, Nepal")仅周日为周末
NONE(0, 0, 0, 0, 0, 0, 0)默认值("Default value")无周末,一周七天都是工作日

与 WeekDay 枚举的索引对齐

掩码的索引约定与同文件中的WeekDay枚举完全一致(constants.py):MONDAY = 0、TUESDAY = 1、WEDNESDAY = 2、THURSDAY = 3、FRIDAY = 4、SATURDAY = 5、SUNDAY = 6,即"周一起始、零基编号"。因此FRIDAY_SATURDAY = (0,0,0,0,1,1,0)中位置 4、5 的两个 1 恰好对应周五(FRIDAY)与周六(SATURDAY)。这一约定贯穿整个日期模块,自定义掩码时必须遵循,否则掩码会整体错位。

源码实现:掩码如何进入日历

类定义本体

WeekendMask的完整源码仅一个类、四个元组属性,没有任何方法(constants.py):

class WeekendMask(object): """Provides weekend masks for some of the common weekend patterns.""" # E.g. US/UK/Europe etc. SATURDAY_SUNDAY = (0, 0, 0, 0, 0, 1, 1) # E.g. Most countries in the Middle East. FRIDAY_SATURDAY = (0, 0, 0, 0, 1, 1, 0) # E.g. India, Nepal. SUNDAY_ONLY = (0, 0, 0, 0, 0, 0, 1) # Default value. NONE = (0, 0, 0, 0, 0, 0, 0)

它没有继承enum.Enum,而是普通object子类;取值用 0/1 而非True/False,但下游 API 一律以布尔语义解释(1/True 表示休息日)。这也是为什么它能与用户自定义的[0,0,0,0,1,0,1]这类列表/Tensor 自由混用——create_holiday_calendar的weekend_mask参数接受的正是"任意可转换为 7 元素 Tensor 的对象"。

通过工厂函数进入 HolidayCalendar

掩码的唯一正式入口是create_holiday_calendar(holiday_calendar_factory.py):

def create_holiday_calendar( weekend_mask=None, holidays=None, start_year=None, end_year=None): ...

其中weekend_mask的官方定义为:布尔Tensor,共 7 个元素、每个元素对应一周中的一天,索引 0 为周一;True表示该天是周末,False表示工作日;默认None表示不应用任何周末。

工厂内部(holiday_calendar_factory.py)会根据是否提供了holidays或start_year/end_year边界,选择性能更优的BoundedHolidayCalendar(预计算整张工作日查询表)或更灵活的UnboundedHolidayCalendar。两种实现都会消费weekend_mask:

  • BoundedHolidayCalendar(bounded_holiday_calendar.py):构造时执行tf.convert_to_tensor(weekend_mask or constants.WeekendMask.NONE),即不传掩码时自动落到WeekendMask.NONE;随后在_compute_is_bus_day_table中(bounded_holiday_calendar.py)通过week_days = (ordinals - 1) % 7计算星期并tf.gather(self._weekend_mask, week_days)标记休息日,再以tf.bitwise.bitwise_or叠加法定节假日,最终生成按 ordinal 索引的is_bus_day查询表。

  • UnboundedHolidayCalendar(unbounded_holiday_calendar.py):将掩码tf.cast(..., dtype=tf.bool)后交给holiday_utils.business_day_mappers构造"工作日空间"与 ordinal 空间的互映射(holiday_utils.py),其中用tf.roll(weekend_mask, -_DAYOFWEEK_0, axis=0)调整掩码对齐后做工作日偏移累计。

从源码结构可以推断:掩码直接决定了"工作日空间"的密度与形状——例如FRIDAY_SATURDAY下工作日是 5 天/周但落在周日~周四,SUNDAY_ONLY下工作日是 6 天/周。所有基于日历的日期加减、滚动都在这套空间中进行,因此掩码选错会系统性影响全部计算结果。

实战一:创建不同地区的假日日历

最典型的用法是把掩码作为weekend_mask传入create_holiday_calendar,再配合holidays传入法定节假日列表。参考 holiday_calendar_test.py 的测试模式:

import tf_quant_finance as tff dates = tff.datetime # 美式日历:周六周日为周末,叠加元旦与圣诞节 cal = dates.create_holiday_calendar( weekend_mask=dates.WeekendMask.SATURDAY_SUNDAY, holidays=[(2020, 1, 1), (2020, 12, 25), (2021, 1, 1)]) date_tensor = dates.dates_from_tuples([(2020, 1, 1), (2020, 5, 1), (2020, 12, 25), (2021, 3, 8), (2021, 1, 1)]) cal.is_business_day(date_tensor) # 输出: [False, True, False, True, False] # 元旦 工作日 圣诞 工作日 元旦

若把掩码换成中东模式:

cal_me = dates.create_holiday_calendar( weekend_mask=dates.WeekendMask.FRIDAY_SATURDAY, start_year=2020, end_year=2021)

此时周五、周六被判定为非工作日,而周日反而是工作日——这正是FRIDAY_SATURDAY的核心价值。

自定义掩码:打破"周六周日"假设

仓库测试明确支持自定义掩码(holiday_calendar_test.py):

# 周六上班、周五和周日休息 weekend_mask = [0, 0, 0, 0, 1, 0, 1] cal = dates.create_holiday_calendar( weekend_mask=weekend_mask, start_year=2020, end_year=2021) d = dates.dates_from_tuples([(2020, 1, 2), (2020, 1, 3), # 周四、周五 (2020, 1, 4), (2020, 1, 5), # 周六、周日 (2020, 1, 6), (2020, 5, 1), # 周一、周五 (2020, 5, 2)]) # 周六 cal.is_business_day(d) # 输出: [True, False, True, False, True, False, True]

自定义掩码需满足:长度恰好为 7、索引 0 为周一、1 表示休息日。它可以是 Python 列表、NumPy 数组或tf.Tensor,工厂与两种日历实现都会自动做类型转换。

实战二:与日程生成(Schedule)配合

WeekendMask并不只服务于"判断某天是否营业",它是整个业务日程系统的地基。在 schedules_test.py 中,PeriodicSchedule(周期日程,如付息日序列)正是通过掩码构建日历:

actual_schedule = dates.PeriodicSchedule( start_date=start_dates, end_date=end_dates, tenor=tenors, holiday_calendar=dates.create_holiday_calendar( weekend_mask=dates.WeekendMask.SATURDAY_SUNDAY, start_year=2020, end_year=2028), roll_convention=dates.BusinessDayConvention.MODIFIED_FOLLOWING, backward=backward, end_of_month=end_of_month).dates()

同样,BusinessDaySchedule(纯工作日日程)也接受携带掩码的日历(schedules_test.py)。可见,WeekendMask与BusinessDayConvention(滚动约定,如FOLLOWING、MODIFIED_FOLLOWING)是一对固定搭档:掩码决定"哪些天要滚",约定决定"往哪个方向滚、如何避开跨月"。当掩码改变周末定义时,同一组日期在roll_to_business_day、add_business_days等 API(定义于 holiday_calendar.py 的抽象基类)下的滚动结果会相应变化。

注意事项与最佳实践

  1. NONE是默认兜底值:create_holiday_calendar与BoundedHolidayCalendar在weekend_mask=None时都自动回落到WeekendMask.NONE(bounded_holiday_calendar.py),此时一周七天全是工作日。需要周末过滤时必须显式传掩码。
  2. 索引从周一开始:与 Pythondatetime约定(datetime.weekday():周一=0)一致,但注意WeekDay枚举与 ISO 8601(周日=7)不同,自定义掩码时最容易踩的坑就是按"周日开头"排列 0/1。
  3. 掩码负责周末,holidays负责法定节假日:两者通过tf.bitwise.bitwise_or叠加。官方建议在提供holidays时注意把落在周末的节日人工调整(如 2021-12-25 圣诞落在周六时调整为 12-24),或直接借助 Pandas 的AbstractHolidayCalendar生成(参见 create_holiday_calendar.md 与 holiday_calendar_factory.py 中的示例)。
  4. 提供边界以换取性能:create_holiday_calendar文档明确提示,给出holidays和/或start_year/end_year会得到性能更好的BoundedHolidayCalendar;同时每个日历实例应在单个计算图/tf.function 上下文中使用。
  5. 测试覆盖可靠:holiday_calendar_test.py 中的test_both_impls装饰器保证每个行为在BoundedHolidayCalendar与UnboundedHolidayCalendar两种实现上结果一致,说明掩码语义在两条实现路径上是等价且被持续验证的。

结语

WeekendMask虽小,却是 tf-quant-finance 日期体系中"周末定义"的唯一事实来源。四个预置掩码覆盖了全球主流交易市场的周末结构(六日休、周五六休、仅周日休、无周末),而自定义掩码机制让任意地区的特殊周末安排都能以一行元组表达。理解其索引约定与在HolidayCalendar内部的消费方式,是正确开展业务日计算、付息日程生成与日期滚动的前提。

  • 金融科技
  • 科学计算

【免费下载链接】tf-quant-finance

High-performance TensorFlow library for quantitative finance.

项目地址:https://gitcode.com/gh_mirrors/tf/tf-quant-finance
点击查看免费下载
上一篇:daisyUI 语义颜色(Semantic Colors)完全指南:主题化、CSS 变量与透明度机制深度解析
下一篇:cross与cargo-deadlinks:检查跨平台文档中的无效链接

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询