114a69e997
根因: dbbardata UNIQUE(symbol,exchange,interval,datetime) 按字符串字面比较, 多写入路径混用 'YYYY-MM-DD' 与 'YYYY-MM-DD 00:00:00' -> 同一交易日双行, INSERT OR REPLACE 不去重 -> 回测交易日翻倍/pivot duplicate/信号异常。 方案A (统一纯日期, 详见 Main Agent 诊断): - 新增 scripts/data_platform/dbbardata_utils.py: normalize_daily_dt(s) 取前 10 字符, None/短串安全 - 4 个日线写入脚本写入前调 helper: - bs_eod.py (sanguo-bs-eod 个股日线 baostock) - migrate_daily_baostock.py (历史迁移) - xt_eod.py (sanguo-xt-eod ETF/基金 xtata) - import_vnpy_daily_fast.py (NAS 日线 parquet 导入, 加防御) - TDD: tests/data_platform/test_dbbardata_utils.py 9 cases 全过 - 回归: tests/data_platform + tests/portfolio 199 passed 12 skipped peewee DateTimeField formats 含 '%Y-%m-%d' (阶段0 VPS 实测确认), 读纯日期不崩, 方案A 前提成立。 15min 干净, 不动 (分钟必须带时分)。只改日线 interval='d'。 数据层根治, 不在 provider 适配兜底 (用户铁律)。
29 lines
1.1 KiB
Python
29 lines
1.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""dbbardata 日线 datetime 归一化 helper (双行根治方案A)。
|
|
|
|
背景:
|
|
dbbardata (DbBarData) UNIQUE(symbol,exchange,interval,datetime) 按字符串字面比较。
|
|
历史多写入路径混用 "YYYY-MM-DD" 与 "YYYY-MM-DD 00:00:00" 两种格式,
|
|
同一交易日 INSERT OR REPLACE 不去重 -> 双行, 致回测翻倍/pivot duplicate。
|
|
|
|
归一规则:
|
|
日线 (interval='d') 写入前必调 normalize_daily_dt, 统一为纯日期 'YYYY-MM-DD'。
|
|
分钟 (interval='15m' 等) 不要调 — 分钟必须带时分。
|
|
|
|
入口: 所有写 dbbardata interval='d' 的脚本 import 并在 datetime 列写入前调用。
|
|
"""
|
|
from typing import Optional
|
|
|
|
|
|
def normalize_daily_dt(s: Optional[str]) -> Optional[str]:
|
|
"""日线 datetime 归一为纯日期 'YYYY-MM-DD' (取前 10 字符)。
|
|
|
|
- 纯日期 'YYYY-MM-DD' -> no-op
|
|
- 'YYYY-MM-DD 00:00:00' / 'YYYY-MM-DD HH:MM:SS' -> 截断为 'YYYY-MM-DD'
|
|
- None -> None (保留语义不崩溃)
|
|
- 短串/空串 -> 原样返回(前 10 字符)不崩溃
|
|
"""
|
|
if s is None:
|
|
return None
|
|
return str(s)[:10]
|