DOCS
stock-analyzer · 数据异常报告
← 返回文档中心 · 来源:Languangxun/stock-analyzer · 同步于 2026-09-27
范围:stock_cache.db 日K(7624 只代码 / 约 1240 万根)与 data_clean.py 清洗链。
本报告为只读诊断 + 已实施修复的记录;第三节是仍需决策的数据层问题。
一、已修复:浅迁移截断(数据丢失 28.2 万根)
现象:data_clean.py 旧版 _fetch_tx_kline 固定翻 2 页(腾讯 800/根/页 → 上限
1600 根)。热修⑩给 --fix 加 force=True 后,被扫描判定(含大量误报)的 664 只
代码整只重拉,其中约 370 只长历史股被截断:
- 全库日K:12,685,971 → 12,403,617(-282,354 根);
- 664 只中有 369 只现为 1600/1601 根且首根早于 2020-02-26(截断签名),
例:创业板指
sz3990061600 根(起点 2020-02-26),同批指数/老股原为 2400 根 (起点 2016-11-11)。
已修:
- 迁移深度改为
max(库内根数, --depth=2400),按需翻页(最多 6 页/4800 根); - 新增防缩水守卫:新序列首根变晚且不更长(
keep_head)或末根变旧(keep_tail) 时保留库内原数据,--allow-shrink才可覆盖; - 新增
--repair(GUI 数据工具「截断修复」):重拉「根数<2400 且首根早于 2021-01-01」的 1972 只代码补齐 2016–2020 深历史。实测单只sz3990061600→2400 根、起点回到 2016-11-11。 (注:截断修复跑到 600/1972 时,第三节口径问题确认,改为全库--all-adj --force重迁——该重迁同时补齐深度,修复模式保留供后续使用。)
二、已修复:扫描误报与噪声(同一规则还被 GUI 清洗沿用)
扫描判定原先未复用 stock_gui._bars_anomalous 的误报豁免,导致大量健康数据
被反复”整只重拉”(即第一节截断的触发源)。现 data_clean 与 GUI 共用同一
规则(新股前 10 根 / 相邻>30 天停牌复牌 / 现名回溯 ST 放宽到 10% / ETF 折算
孤立跳变放行 / 指数与退市整理豁免)。修复前后全库扫描对比:
| 项 | 修复前 | 修复后 | 说明 |
|---|---|---|---|
| 涨跌幅越界 | 779 只 | 59 只 | 北交所源停更 84 只单独忽略 |
残留 59 只多数正是第三节仿射失真的表现(收益被放大
s>1后,真实 10% 涨停在 hfq 里显示 >13%);对它们重拉腾讯 hfq 无济于事(_validate会拒绝同源失真数据),须等第三节省口径决策后统一处理。 | 末价<0.5「失真」 | 40 只 | 0 | ETF/退市真实低价不再误报 | | 长停牌缺口 | 1316 只 | 41 只 | 只报近一年(陈年停牌属正常) | | 落后市场最新日>10天 | 370 只 | 33 只 | 北交所停更 336 只单独统计 | | 孤立代码(有K线无代码表) | 未检 | 新增统计 | 如错误前缀sz688012| | 扫描耗时(全库) | 238s | 40s | 日期解析改date.fromisoformat|
stock_gui.clean_daily_db 同步安全化:判定走 _bars_anomalous,整只重拉
target=max(库内根数, 2400) 并加丢头/丢尾守卫(不满足则保留原数据)。
三、待决策:腾讯 hfq 是仿射变换,日收益率被逐股缩放(严重)
结论:库内主口径(热修⑩起统一为腾讯「后复权 hfq」)不是乘法后复权。
实测腾讯 hfqday 在不含除权的区间内严格满足
hfq(t) ≈ a × 不复权价(t) + b (段内 a、b 恒定)
于是整段日收益率被缩放为 s = a·P / (a·P + b) ≈ 中位(hfq日收益 / 不复权日收益);
该缩放随每次除权除息跳变,且每一根 bar 都受影响(不是只在除权日)。
证据(近 120 根拟合,配对同一交易日):
| 代码 | 名称 | 拟合 R² | 收益缩放 s | 备注 |
|---|---|---|---|---|
| sh600000 | 浦发银行 | 0.96 | 0.63 | 日收益被缩小 37% |
| sh601318 | 中国平安 | 0.98 | 0.72 | |
| sh600519 | 贵州茅台 | 0.98 | 0.82 | |
| sz000725 | 京东方A | 0.9998 | 0.87 | |
| sz300750 | 宁德时代 | 0.99 | 0.95 | |
| sz000005 | ST星源 | 1.0000 | 1.75 | 日收益被放大 75% |
| sh600653 | 申华控股 | 1.0000 | 1.75 |
单日对照(sh600653 2018-08-01,涨跌停 ±10% 的主板股):
不复权 1.98→2.18 = +10.10%(涨停);腾讯 qfq +10.1%(正确);
腾讯 hfq +16.35%(失真)。sh600595 2014-07-22/23 两天连续涨停,
不复权 +10.10%/+10.07%,hfq 报 +15.24%/+14.52%。
影响面(抽样 8 只,5 只 |s-1|>2%):失真既非个别股票也非小量级; v6.1.5 起(热修⑩/全库迁移后的)回测、因子、形态匹配所用收益率均带逐股 缩放,且缩放系数随时间(除权)变化。热修⑩的”重叠日偏差 0.0000%”验证是 循环验证(库内与源同为腾讯 hfq),未检出该问题。
可复现体检(新增,只读):
python3 data_clean.py --check-adj --sample 300 # 报告 reports/复权体检_*.md
# GUI:工具 → 数据工具 → 模式选「复权失真体检」
处置(2026-09-27 已确认并实施,全链切换):
用新浪复权因子 finance.sina.com.cn/realstock/company/<code>/hfq.js
× 腾讯不复权日K 重建真乘法后复权,已落到全部数据路径:
| 路径 | 改动 |
|---|---|
data_clean.py 迁移 |
_hfq_mul 为第一候选源(sina > tx hfq > em),K=1/f_last 顺带算出 |
stock_gui.py 在线拉取 |
新增 _fetch_tencent_mul,_fetch_remote_rows 四个腾讯源全部改走它 |
stock_gui.py 深历史 |
_bf_tx_pages(不复权可翻页)+ _to_hfq_mul,_bf_fetch_one 重写 |
backfill_full.py |
_fetch_one 统一委托 sg._bf_fetch_one,不再直存腾讯 hfq |
sync_adjust.py |
基期漂移比对改 fetch_hfq_correct(同口径),不再与仿射 hfq 比 |
验证:sh600000 / sh600653 / sh600595 重建后收益比中位 1.0000、
涨跌停越界 0 处(同股腾讯 hfq 越界 70~167 处);抽样 30 只 ETF/LOF
用腾讯 qfq,越界 0;深度 2400 根。全库 --all-adj --force 重迁已完成
(7103/7105 成功,2 只防缩水保留原数据,约 2 小时;日志
/tmp/opencode/migrate_basis4.log)。
四、完工复核(2026-09-27 14:35)
--check-adj --sample 300:有效 297、低波动不判 3、失真 0(s 中位 P10/P90 全为 1.000);- 全库清洗扫描(38s):结构异常 0(修复前 107/10)、负价 0、 涨跌幅越界 10 只(修复前 779,余者为 PT水仙/PT金田A/吉林化工等 退市老股的真实历史事件)、末价失真 0、价格粘性 0;
- 全库 12,714,846 根(受损后 12,403,617、受损前 12,685,971),
截断丢失的深度全部补齐且更深:
sz3990061600→2400(2016-11 起)、sh600000/sh600519/sz002241/sh510050均 2400 根;≥2400 根代码 3127 只; - 旧策略缓存
meta表strategy:*7178 条已清空(按需重算)。
待办:重跑 v6.1.5 回测 / factor_lab 面板(旧口径结果作废)。
备选/后续:
- 等东财恢复后验证
fqt=2收益率保真度,作为新浪因子的交叉校验/容灾; - 若两源都不可用:改存不复权价 + 除权事件表,读取层自行复权;
- 过渡方案:研究/回测前用体检的
s还原(不推荐,s随除权变化)。
生成:v6.1.5 热修⑪(2026-09-27)。不构成投资建议。