Commit Graph

15 Commits

Author SHA1 Message Date
claude_dev 9fa2f933ee refactor(data): 5m回灌改每日分片——用户拍板2026-08-20'每天固定下一些',废弃--full一趟灌满——①每日一跑=回灌片(若有)+每日增量(回灌期也跑,近端7天始终新鲜)②片=半年窗口newest-first(近端先到先可用,回测最常用的近期数据第一天就有),state(bs_5m_state.json next_end)逐片向2020-01-03推进;整片扫完才推进,断点/达限次日重拉同片(OR REPLACE幂等)③全程~14片≈两周补完,每片~5.5k query/~3200万行/3-4h;片+增量每日~11k query,NAS IP独立48k配额内④DAILY_LIMIT守卫改跨窗口累计计数(swept);删FULL_TIMEOUT(半年片5.8k行/股,60s超时足够);+3测试(首片=最近半年/逐片向2020走+完结盖章/损坏state重头),main测试改双sweep断言(片+增量4调用/完结后单sweep2调用);data_platform 158绿 [nas]
CI/CD / test (push) Successful in 18s
CI/CD / nas-deploy (push) Successful in 36s
CI/CD / nas-verify (push) Successful in 17s
2026-08-20 10:42:34 +08:00
claude_dev 20ff70e85d refactor(data): 5m改同库设计——用户二次拍板2026-08-20:放弃独立库,5m直接写NAS副本主库dbbardata表(interval='5m'与镜像行d/15m唯一键正交=结构性互不干扰)——①bs_5m_eod缺省库改/volume1/stock/sanguo_vnpy_v2/data_backup/quant_trading.db(=同步目标=NAS回测provider读的库portfolio_worker.py:180),NAS就地5m回测/回放reader零改动,未来VPS扩容导interval='5m'反向merge一次迁移②同库安全性实证:同步链export不带id列+NAS侧INSERT OR IGNORE按UNIQUE去重→键永不相交双向碰不到;纯merge无文件覆盖NAS本地行不会被删;id由NAS AUTOINCREMENT自分配无跨库冲突③ensure_schema防重复索引:PRAGMA index_list/index_info识别已有同列唯一索引(NAS侧uq_dbbardata)跳过,免数GB无谓开销+双倍写放大④merge_increment补busy_timeout=60000(副本库从此有第二个写者,无它撞写锁当场locked失败,60s与5m侧对齐)⑤写锁竞争说明:双写者WAL+busy_timeout串行化,与每日增量merge(秒级)重叠单股失败次日LOOKBACK=7自愈;+2测试(缺省库契约钉死/副本已有索引不重复建);40+153绿(data_platform 155) [nas]
CI/CD / test (push) Successful in 15s
CI/CD / nas-deploy (push) Successful in 34s
CI/CD / nas-verify (push) Successful in 15s
2026-08-20 10:10:04 +08:00
claude_dev a6f924e950 feat(data): NAS独立5分钟线备份——bs_5m_eod新脚本(NAS专属,VPS永不跑)——用户拍板2026-08-20:NAS既有数据全是VPS同步镜像(nas_sync零接触),5m是NAS唯一自主从baostock下载数据,落独立库BS_5M_DB(缺省/volume1/stock/sanguo_5m/dbbardata_5m.db容器内外同路径),绝不写同步目标data_backup/quant_trading.db;①首次自建schema+唯一索引(REPLACE去重)②缺省每日增量LOOKBACK=7(DSM任务计划~19:05);--full一次性回灌2020-01-03+(baostock分钟固定起点非滚动;全区间每股恰1次调用=~5.5k query一趟≈3.6亿行,数小时级,per-stock短事务断点续跑幂等;FULL_TIMEOUT=300s防大payload误杀)③配额:NAS出口IP独立核算48k/天与VPS互不相干,DAILY_LIMIT守卫保留④单实例锁bs_5m.lock(pid活性检测,死锁自动覆盖/PermissionError按在跑)防DSM定时与--full长跑撞车=同IP双baostock连接红线⑤复用bs_eod四件套+datetime拼接/数值口径与15m完全同款;+13测试(schema/REPLACE不双行/per-stock原子/full vs daily窗口/锁三态/main四条);data_platform 153绿 [nas]
CI/CD / test (push) Successful in 14s
CI/CD / nas-deploy (push) Successful in 36s
CI/CD / nas-verify (push) Successful in 16s
2026-08-20 09:58:00 +08:00
claude_dev d0a538ced3 feat(data): P1+P2+P3季频财务+业绩报告——bs_fundamentals新脚本(sanguo-bs-fund schtask 23:05,VPS)——①P2回灌:profit利润+dupont杜邦2015Q1+按季分片,state文件推进日预算自适应续跑(约2季/天≈3周自动跑完;预算不够整季不拉半季,半段落库也幂等)②P1增量:回灌完成后拉当季+上一季(兜住8-31晚披季报)③P3业绩报告:forecast预告2003+/express快报,每股一次调用与区间无关→月首周日全区间恒定2N query幂等拉齐(--reports-now冒烟)④落parquet data/fundamentals_baostock/保留pubDate列(读侧pubDate<=date过滤防前视,同fundamentals-lookahead-bias-fix模式);去重(code,pubDate,statDate)restated后写者胜,键不足2列退全列绝不按单列丢历史⑤预算铁律(48000/天):bs_eod~11k+本脚本DAILY_CAP=30000串行=≤41k,月首周日叠reports 44.3k<48k余3.7k;开跑前schtasks探sanguo-bs-eod(极端尾22:41)在跑则exit0次日幂等补——同IP永不双连接⑥复用bs_eod四件套(login_with_retry/relogin/_with_timeout/全A清单)+周期relogin+失败relogin兜底;字段名读rs.fields不硬编码;+14测试(季度边界/parquet幂等+防呆/state损坏重头/动态字段+计数/回灌2季cap推进/state超前零拉/增量当季+上季/报告月首周日窗口/守卫文本/main跳过+exit2);data_platform 140绿 [vps] 2026-08-20 09:53:33 +08:00
claude_dev dbb5ed5aa8 feat(data): P0指数日K双源——bs_eod主循环后追加baostock指数段(2006+全量REPLACE)——治指数点位单源停更史(000300曾停7-16/000938停2023/932000三源无):①INDEX_CODES 15只=探针实证有数(300/500/1000/上证50/中证100/上证综指/深成/创业板+399303国证2000替932000+中证行业6只928/931-935;932000/000938/000985/929/930/936/937 baostock无→不进列表免每日warning刷屏)②同PK(symbol,exchange,datetime,interval)唯一索引INSERT OR REPLACE,与sina idx-eod存量行互备后写者胜,datetime归一纯日期同格式③段在主循环后:query达限跳过守DAILY_LIMIT预算;段内单指数fetch/upsert异常只log不外抛,退出码语义不变(schtask结果码可见)④fetch复用fetch_k_with_timeout(计QUERY_COUNT约15query/天可忽略)+relogin兜底;+10测试(sh/sz映射/REPLACE不双行/空行跳过/容错续跑/代码表卫生/达限跳过/正常跑调用);relogin计数3测试补run_index_eod隔离mock(指数段自身relogin是预期新行为);data_platform 126绿 [vps] 2026-08-20 09:49:13 +08:00
claude_dev 95bdf8a27d fix(data): bs_eod启动登录重试——治08-18型瞬断整天缺口——main()登录失败不再当场exit2,改login_with_retry串行重试(1+2轮,间隔120s/300s,无并发不触封禁红线;用户拍板2026-08-20:优先自身健壮性,实测无频繁重连/超48k配额);瞬时闪断(10054/10002007)秒~分钟级恢复,2/5分钟两轮覆盖;仍失败才exit2,次日18:05例行LOOKBACK=7自愈(自愈机制本就完好,重试只是把'当晚瞬断'消掉);+4测试(首试成功不等待/第2次恢复/3次全败False/集成exit2契约保持);data_platform 116绿 [vps]
CI/CD / test (push) Successful in 13s
CI/CD / nas-deploy (push) Successful in 41s
CI/CD / nas-verify (push) Successful in 16s
2026-08-20 08:49:53 +08:00
claude_dev 384bcc56d7 fix(data): 修三环境 session 反馈的 3 个数据层问题
D1: 删 test_circuit_breaker.py(测已归档 raw_redownload.check_circuit_breaker 死代码,全仓零活跃引用,致 data_platform 套件 collection error)
D2: datareader.py read_db_daily/read_index_daily 两处 vnpy_db 硬访问→.get()+清晰报错防崩溃(根治切 dbbardata 读指数列待办)
D3: high_limit/low_limit close±10% 兜底是有意设计非 bug(填 NaN 会复活 bullet_trade 误判停牌)—get_price 加 round(.,2) 对齐 get_current_tick 口径;测试期望从 NaN 改兜底估算
2026-07-29 21:17:15 +08:00
claude_dev 670498ab01 fix(data): akshare 三表下载鲁棒性 — 原子写 + --repair (G4)
write_parquet_and_marker 改原子写(tmp→os.replace→marker) kill 不产残缺 parquet; 新增 --repair 只重取 missing/empty/corrupt 忽略 marker(周度补漏不必等财报季 --force 全量); is_parquet_healthy 辅助。top_holders 修复无回归, 106 tests。
2026-07-28 20:36:11 +08:00
claude_dev f94a145587 fix(data): bs_eod 卡死根治 — per-stock commit + baostock 超时包装 + 周期 relogin
根因(py-spy dump + netstat CLOSE_WAIT 实证): baostock 服务端关长连接→CLOSE_WAIT, send_msg 静默阻塞不抛异常, socket.setdefaulttimeout 不被 baostock 自己 socket 遵守, relogin 只在 error_code≠0 救不了; 一把大事务全程持 WAL 锁阻断全库。修复: per-stock commit 去大事务 + _with_timeout 线程超时包 fetch_k 打破静默 hang + 周期 relogin 每500主动刷连接。VPS --limit 3 验证 11s 不 hang。
2026-07-28 20:36:11 +08:00
claude_dev 955c05357a fix(data): ak-stock top_holders KeyError 'sdltgd' 根治(_safe 捕 KeyError+匹配sdltgd,跳北交所920/83/87/43) 2026-07-27 21:08:53 +08:00
claude_dev 8b2693423a feat(data): xt_eod 扩展补全北交所 920xxx 日线(exc_of+universe+import容错,复用×100 normalize)
- exc_of: 920 -> BJSE (3 位前缀优先于 2 位 SSE/SZSE 判断, 防 sym[:2]='92' 落 SZSE)
- universe: 沪深ETF/基金 ∪ 北交所920xxx (从 constituent_unified 932000 取, baostock 不覆盖)
- import xtquant 容错 (mac xd=None 可单测 exc_of, main() 开头 return 2)
- --full-bj: 北交所 backfill start=20240101 (默认 LOOKBACK=30 与 ETF 同窗)
- 复用 normalize_daily_dt + ×100 volume 口径, 不动已有 ETF 写入路径

Tests: tests/data_platform/test_xt_eod_bj.py 14 cases RED -> GREEN (3 位前缀 critical + ETF/沪深/深市 覆盖)
2026-07-27 20:56:16 +08:00
claude_dev 11f383a8e2 fix(data): akshare top_holders Length mismatch bug 根治
bug 根因 (实证 akshare 1.18.x stock_gdfx_em.py:418):
  报告期未披露 (如 sz002673 的 20260630 在 2026-07-26 还未发) 时,
  东财 PageSDLTGD 接口返 sdltgd=[], akshare pd.DataFrame([])+reset_index()
  得 1 列 df, 然后 columns=[12 列] 抛
  ValueError('Length mismatch: Expected axis has 1 elements, new values have 12')

  这是确定性无数据 (非瞬时故障), 但 call_ak_with_retry 当网络错重试 3 次
  (14s 退避) + 噪声 ERROR 日志, 浪费时间且消耗断路器配额。

修复:
  新增 _safe_top_10_em 包装 ak.stock_gdfx_free_top_10_em: 子串匹配
  'Length mismatch' (pandas 错误信息稳定) → 返空 df 带 8 列 schema
  (TOP_HOLDERS_COLUMNS), 不抛; 其他 ValueError/ConnectionError 透传重试。
  fetch_top_holders_one_period 改调此包装。

验证:
  - Mac: sz002673/20260630 从 ~14s (3 重试) 降到 0.04s, 返 0×8 空 df
  - 有效期 sz002673/20251231, sh600519/20250930 正常返 10×8 数据
  - 9/9 新单测通过 (tests/data_platform/test_top_holders_parse.py)
2026-07-26 11:54:19 +08:00
claude_dev b06af336c3 fix(data): bs_eod 15min datetime 格式 bug 根治 + --no-daily 选项
bug 根因(2026-07-25): baostock 15min 实测 date='2026-07-21'(带 -),
time='20260721094500000'(17 位 YYYYMMDDHHMMSSmmm)。原代码假设 date 纯数字 +
time[:6] 取年月, 产乱 datetime 致 dbbardata 15min 全市场停 2026-07-17(8 天
没正确累积), 日线正常(7-24)。

修复:
- 提纯函数 _build_15m_dt(date_series, time_series): date 直连 + 从 17 位 time
  第 8-12 位提取 HHMM, 产出 'YYYY-MM-DD HH:MM:00' (符合 GLOB 清理模式)
- upsert_15m 调用 _build_15m_dt 替代内联拼接
- 新增 --no-daily 选项(只跑 15min, 用于重灌快), 与 --no-15m 对称
- TDD: 8 case 覆盖(09:45/14:30/15:00/13:00/跨日/多行混合/GLOB 格式)
- conftest.py 修补 sibling import 在 pytest 下可用
2026-07-25 21:14:12 +08:00
claude_dev 114a69e997 fix(data): dbbardata 日线双行根治(统一纯日期+helper,留ROWID max去重)
根因: 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 适配兜底 (用户铁律)。
2026-07-23 12:18:41 +08:00
claude_dev e3b688354f fix(data): data_platform硬化(增量merge/verify+raw_redownload/run_daily_update)+测试
merge_increment/verify_increment 增量staging→验证→合并工具; raw_redownload/run_daily_update/import_vnpy_daily 强化; 补 data_platform 与 index_downloader 测试.
2026-07-15 07:12:46 +08:00