Skip to content

Date 模块设计决策

目录

  1. 设计目标
  2. 架构决策
  3. 性能决策
  4. 兼容性决策
  5. 市场支持决策

1. 设计目标

1.1 核心目标

Date 模块旨在为量化交易系统提供:

  • 精确性:时间戳和日期计算零误差
  • 可靠性:交易日历与交易所同步
  • 易用性:简洁的函数接口
  • 性能:高效的批量处理能力

1.2 非目标

  • 不提供历史行情复权功能(由数据层处理)
  • 不提供时间序列索引(由DataFrame处理)
  • 不提供时区转换的完整支持(仅默认北京时间)

2. 架构决策

2.1 分离 timestamp 和 trade 模块

决策:将时间戳处理和交易日算法分离为两个独立子模块

原因

  1. 职责分离:timestamp 处理通用时间转换,trade 处理业务相关的交易日计算
  2. 依赖分离:timestamp 仅依赖标准库和numpy,trade 依赖 pandas 和业务常量
  3. 可维护性:两个领域独立演进,互不影响

权衡

  • 跨模块调用稍显繁琐(如需要同时导入)
  • 但避免了单一模块过大

2.2 预加载交易日数据

决策:使用 trade_dates_data.py 预生成完整的 TRADE_DATE_SSE 列表

替代方案考虑

方案优点缺点
预生成列表O(1)查询、无网络依赖占用内存、需手动更新
实时API查询数据实时依赖网络、有延迟
算法计算零存储无法处理复杂节假日

最终选择:预生成列表,平衡查询性能和实现复杂度

2.3 函数命名规范

决策:采用 util_ 前缀统一命名

原因

  1. 避免与标准库命名冲突
  2. 明确标识为工具函数
  3. 保持与原 FQData 的一致性

3. 性能决策

3.1 二分查找优化

决策util_get_real_date() 使用 bisect.bisect_left() 实现 O(log n) 查找

python
pos = bisect.bisect_left(trade_list, date_str)

原因

  • 交易日列表长度随年份增长(已超过9000条)
  • 线性搜索 O(n) 在频繁调用时成为瓶颈
  • 二分查找 O(log n) 性能提升显著

权衡

  • trade_date_sse 必须有序(预生成列表保证)
  • 代码复杂度略有增加

3.2 util_if_trade 的 O(1) 查询

决策:使用 in 操作符直接查询列表

python
return normalized in trade_date_sse

原因

  • Python 列表的 in 操作在短列表上性能优秀
  • 预加载数据保证列表在内存中
  • 避免函数调用开销

注意:当 trade_date_sse 列表非常大时,可考虑转换为 set 优化:

python
trade_date_set = set(trade_date_sse)  # O(1) 但增加内存

3.3 时间戳自动精度识别

决策util_stamp2datetime() 自动识别多种时间戳精度

python
try:
    return datetime.fromtimestamp(timestamp)
except OSError:
    try:
        return datetime.fromtimestamp(timestamp / 1000)  # 毫秒
    ...

原因

  • 不同数据源使用不同精度的时间戳
  • 自动识别避免用户手动转换
  • 向后兼容各种历史数据格式

4. 兼容性决策

4.1 迁移自 FQData

决策:保持函数签名和命名与原 FQData.QAUtil.QADate 一致

原因

  • 减少现有代码的迁移成本
  • 降低用户学习成本
  • 保持 FQBase 的"即插即用"特性

实现

  • 复制原有函数逻辑
  • 更新模块路径导入
  • 保持 __all__ 导出列表一致

4.2 多种日期格式支持

决策util_format_date2str() 支持多种输入格式

python
def util_format_date2str(cursor_date):
    # 支持: str, int, datetime, datetime.date, pd.Timestamp

原因

  • 量化数据源格式不统一
  • 用户代码中日期格式各异
  • 统一格式化简化数据处理流程

4.3 默认北京时间

决策:所有时间转换默认使用北京时间(UTC+8)

python
QATZInfo_CN = 'Asia/Shanghai'
local_tz = timezone(timedelta(hours=8))

原因

  • 中国量化交易主要市场为A股和国内期货
  • 避免时区混淆导致的交易事故
  • 简化国内交易系统的开发

注意:跨境外市场数据需显式处理时区


5. 市场支持决策

5.1 A股支持

决策:内置上证所交易日历 trade_date_sse

范围:1990-12-19(上证成立)至今

维护:每年初更新,重大节假日调整后同步

5.2 期货支持

决策util_if_tradetime() 支持国内期货交易时间

覆盖品种

  • 商品期货(9:00-10:15, 10:30-11:30, 13:30-15:00)
  • 金融期货 IH/IF/IC(9:30-11:30, 13:00-15:00)
  • 国债期货 T/TF(9:15-11:30, 13:00-15:15)

夜盘支持

  • AU/AG/SC(贵金属/原油):21:00-02:30
  • CU/AL/ZN/PB/SN/NI(基本金属):21:00-01:00
  • RU/RB/HC/BU/FU/SP(黑色/化工):21:00-23:00

5.3 市场类型常量

决策:使用 MARKET_TYPE 枚举区分市场

python
from FQBase.Config.business.constants import MARKET_TYPE

MARKET_TYPE.STOCK_CN   # A股
MARKET_TYPE.FUTURE_CN  # 国内期货

原因

  • 避免字符串硬编码
  • IDE 自动补全支持
  • 类型检查支持

6. 未来演进方向

6.1 可能的变化

变化触发条件
交易所改用T+0交易政策重大调整
增加港股/美股支持业务国际化
引入缓存机制性能瓶颈显现
时间序列索引复杂时间框架需求

6.2 不纳入的设计

以下功能不属于 Date 模块职责:

  • K线合成(如1分钟转5分钟)
  • 复权数据处理
  • 财务日历(非交易日历)
  • 国际节假日支持