Files
etf/docs/data_logic_analysis.md
aszerW 4df3ac4e31 chore(docs): reorganize documentation files into docs/ folder
Moved markdown documentation from root to docs/ directory to improve project structure.
2026-04-30 01:06:25 +08:00

4.9 KiB
Raw Blame History

跨市场数据时间对齐逻辑分析

一、各市场交易时间(北京时间)

市场 交易时间 数据代码 数据源 数据标记
A股 T日 09:30-15:00 000300.SH 等 Tushare T日 OHLC
港股 T日 09:30-16:00 HSTECH.HK (3033.HK) YFinance T日 OHLC
美股 T日 21:30-次日04:00 NDX YFinance T日 OHLC
加密货币 T日 08:00-次日08:00 (UTC) BTC/ETH CCXT/OKX T日 OHLC
黄金期货 T日 09:00-15:30, 21:00-次日02:30 AU.SHF Tushare T日 OHLC

二、数据就绪时间点

假设当前是 T+1日 09:00(信号计算时间):

市场 T日数据就绪时间 T+1日09:00时最新数据
A股 T日 15:00 T日数据 ✓
港股 T日 16:00 T日数据 ✓
美股 T+1日 05:00 T日数据 ✓
加密货币 T+1日 08:00 T+1日数据 ✓ (UTC 00:00)
黄金期货 T+1日 02:30 T+1日数据 ✓ (夜盘结束)

三、关键问题分析

问题1数据标记与实际交易时间的不一致

黄金期货 (AU.SHF)

  • 交易时间T日 09:00-15:30日盘+ T日 21:00-T+1日 02:30夜盘
  • Tushare 数据标记T+1日 OHLC因为夜盘结束是T+1日凌晨
  • 实际对应T日日盘 + T日夜盘 = 标记为 T+1日

加密货币 (BTC/ETH)

  • 交易时间T日 08:00UTC 00:00- T+1日 08:00UTC 00:00
  • CCXT 数据标记T+1日 OHLCUTC 00:00 为日线分界)
  • 实际对应T日08:00到T+1日08:00 = 标记为 T+1日

问题2当前代码逻辑

# hybrid_source.py 中的数据对齐逻辑
# 以A股交易日为基准对齐所有数据
a_share_dates = 获取A股交易日历(start_date, end_date)
index_data = index_data.reindex(a_share_dates)

# 非A股标的处理
# 港股/美股ffill() - 使用T日数据
# 加密货币/期货bfill() - 使用T+1日数据

问题3当前存在的问题

场景3月26日 00:17 运行代码

期望 实际
获取3月25日所有市场数据 可能只获取到3月24日数据
信号日期3月26日 信号日期3月25日
数据基准3月25日 数据基准3月24日

原因分析

  1. end_date 默认是 datetime.now().strftime('%Y-%m-%d') = "2026-03-26"
  2. 但 A股3月26日还没开盘Tushare 获取不到3月26日数据
  3. 数据对齐时使用 index_data.index.max() 作为结束日期变成3月25日
  4. 导致交易日历只到3月25日3月26日被排除

四、正确的数据获取逻辑

4.1 运行时间点与数据获取

运行时间 A股状态 应获取的最新数据
T+1日 00:00-09:00 未开盘 T日数据所有市场
T+1日 09:30-15:00 交易中 T日数据不应获取盘中数据
T+1日 15:00后 已收盘 T+1日数据A股+ T日数据其他

4.2 数据对齐策略

核心原则以A股交易日为基准T+1日09:00计算信号时

  1. A股/港股T日数据已收盘使用 ffill() 填充
  2. 美股T日数据已收盘T+1日05:00使用 ffill() 填充
  3. 加密货币T+1日08:00已收盘使用 T+1日数据bfill()
  4. 黄金期货T+1日02:30已收盘使用 T+1日数据bfill()

4.3 代码修改建议

修改1使用配置的 end_date 获取交易日历

# 原代码(错误)
end_str = index_data.index.max().strftime('%Y%m%d')

# 修改后(正确)
end_str = pd.Timestamp(end_date).strftime('%Y%m%d')

修改2区分不同市场的数据对齐方式

# 港股/美股ffill() - T日数据
# 加密货币/期货bfill() - T+1日数据
yf_codes = [港股, 美股]
crypto_futures_codes = [BTC, ETH, AU.SHF]

修改3信号日期计算

# 当前代码(错误)
signal_date = backtest_result.index[-1]  # 取数据最后一天
data_base_date = signal_date - 1  # 假设是前一天

# 应该根据当前时间判断
if 当前时间 < T+1日09:00:
    signal_date = T日
    data_base_date = T-1
else:
    signal_date = T+1
    data_base_date = T日

五、当前已做的修改

  1. hybrid_source.py 使用配置的 end_date 获取交易日历
  2. hybrid_source.py 区分 yf_codes 和 crypto_futures_codes 的不同填充方式
  3. hybrid_source.py YFinance 添加 auto_adjust=Falseend_date+1天
  4. rotation.yaml 黄金改为 AU.SHF恒生科技改为 HSTECH.HK

六、仍需确认的问题

  1. 信号日期显示:当前显示 "2026-03-25 (基于 2026-03-24 收盘数据)" 是否正确?

    • 如果今天是3月26日00:17应该显示 "2026-03-26 (基于 2026-03-25 收盘数据)"
  2. 数据基准日期计算report.py 中的 data_base_date = signal_date - 1 逻辑是否需要修改?

  3. 加密货币/黄金的数据标记CCXT/Tushare 返回的数据日期是否已经是 T+1日标记