更新日志
下列条目全部摘自项目内的 reports/CHANGES.md(73 KB),
按「最新阶段在前」原序摘录,每条保留原日期与当时的版本号。
当前发布版本 APP_VERSION = 1.1.0。
先读这条。2026-10-30 那一条自己写明:交付的二进制 (安装包与绿色版 EXE,构建于 2026-10-29 20:43–20:47)不包含 2026-10-30 的源码改动, 交付前必须在停机后重建并重新浸泡 24 小时。也就是说,下载页的 1.1.0 安装包对应的是 2026-10-29 构建,不是整改后的最终产物。
变更条目
-
2026-10-30 APP 1.1.0 上市审查整改(U/P/D 类收尾)
- U-10 页面截图:新增
scripts/capture_ui_pages.py,用真实 Qt 控件 + 进程内桩 API、零网络生成 6 张页面截图与capture.json(尺寸、字节数、SHA-256、api_calls)。边界:合成数据,不是真实服务端端到端。 - 重复详情请求:
MatchesView._select_by_id与ReplayView._select在setCurrentIndex前先写_selected_id。根因是QListView.blockSignals()不阻断selectionModel().currentRowChanged;capture.json的api_calls从 10 条降为 6 条。 - U-06 非文本对比度:赛事行描边改
#4a7099,QProgressBar轨道改#54759a;现共 45 组配对,正文最低 4.91:1、非文本最低 3.38:1,scripts/check_ui_contrast.py0 失败。 - D-10 / D-11:
beta_usage按 90 天分批删除(每批 5000);僵尸ingest_runs标记为interrupted并补finished_at。 - walk_forward 重算:排除
split=test行、proxy_scale每 origin 重新拟合后,origin 由 11 个变为 9 个(2016–2024),market 均值 0.199323、factor_full 均值 0.206532、仍 0/9 优于市场。 - 验证:
331 passed;check_claims.py116 指标 / 49 文件通过(report_sha256 = 6f6d8095…);check_test_freeze.py仍为 4 次。
- U-10 页面截图:新增
-
2026-10-29 test_runs = 4 测试集硬冻结与生成报告更正
- 硬冻结:
backtest/pipeline.py新增TEST_FREEZE_RUNS = 4与decide_test_lock/decide_multi_test_lock。锁中test_runs = 4且预测哈希变化时,即使传--force-test也返回退出码 7;同哈希重跑只复现已冻结的预测。 - 报告更正:
reports/baseline.md、MULTI_MARKET.md、WALK_FORWARD.md、test_once.md及生成器删除「测试集只评估一次」的旧表述,改为「已评估 4 次并冻结,只能作历史披露」。 - 政策文档:
docs/ROADMAP.md、MODEL_SELECTION.md、ACCURACY.md、LOAD_TEST.md同步;LOAD_TEST.md明确压测数字属于 1.0.0,1.1.0 未重跑压测。 - 验证:
307 passed;check_claims.py116 指标 / 49 文件通过;gate_test_freeze_runtime.py9 个用例通过。
- 硬冻结:
-
2026-10-29 APP 1.1.0 深度矩阵事件行重叠与训练提示修复
- 现象:深度矩阵「比赛事件」卡片中,分钟、球队、事件类型与事件文字相互覆盖。
- 根因:
ElidedLabel把水平策略设为QSizePolicy.Ignored,QBoxLayout因此按 0 宽给后续控件定位。 - 修复:改为
Preferred策略,minimumSizeHint宽度保持 0,sizeHint以minimum_cap封顶;新增test_detail_event_rows_do_not_overlap。 - 训练提示:安装包不含源码与历史数据,本来就不能自动训练;错误文案改为指向源码目录运行
python run_server.py。
-
2026-10-29 factor-prematch-1.2.0 S9 整改全量执行 · Wave 1 收尾 + Wave 2–4
- 测试集状态:按
factor-prematch-1.2.0契约评估,test_runs = 4,n_test = 6498,input_sha256 = aef82faa…。这是第 4 次评估,自此冻结,不再做第 5 次。 - D-03 缺失不补 0:统计字段区分
None与0,控球率不再默认 50/50;缺失输入走FactorMissing,因子日志标记degraded。 - M-10 去水方法:默认改用 Shin,保留 proportional / power 并记录方法名。
- M-21 投注模拟:新增
backtest/stakes.py与reports/STAKING.md;测试集资金曲线归零(ROI −100.00%),作为负面结果原样披露。 - 公开指标:测试集市场基线 RPS
0.200312,因子链赛前分支0.205762,差值+0.005449(95% CI 0.004073–0.006686)——因子模型未击败市场。 - E-06 大文件拆分:
server/api/admin.py、backtest/run.py(拆为 49 行 + 多个模块)、server/scheduler/engine.py均已拆分;未拆client/views/match_detail.py(1283 行)与server/static/admin/app.js(3449 行)。
- 测试集状态:按
-
2026-10-29 metrics-2.0.0 S8 整改 Wave 1 · 模型与评估可信度
- M-01 泊松防守基准:主队防守改为除以联赛客场均值,客队防守除以联赛主场均值。旧实现两侧都用主场均值,主队防守被系统性高估。
- M-03 多分类 Brier:从「三类平方误差之和」改为「三类平方误差均值」,指标版本升级为
metrics-2.0.0;旧报告 Brier 约为当前值的 3 倍,不可直接比较。 - M-05 切分防泄漏:新增
assign_splits_by_date(),先按日历日期分组再放置边界,两个边界日期整体剔除;本次剔除 32 场(训练 19492 / 验证 6469 / 测试 6498)。 - M-30 版本单一来源:新增
common/version.py,打包脚本的版本号也改为解析该文件,不再手写。 - E-01 / M-02:新增
scripts/render_reports.py生成docs/ACCURACY.md;scripts/check_claims.py三类硬校验,任一不符构建直接失败。
-
2026-10-29 Wave 0 S7 整改 Wave 0 · 止血
- D-01 终局帧落库:
_mark_finished()自己执行_upsert_one(force=True)并submit_snapshot(),不再依赖调用方。 - D-02 不再伪造完赛:终局状态保留上游真实状态(
abandoned/cancelled/awarded不再被改写成finished),不再强制minute = max(90, …)。 - 中止/腰斩不计训练真值:
_backfill_factor_outcome()只对SETTLED_STATUSES写 real result;中止写{"result":"void"}。 - C-01 / C-02 客户端稳定性:
TaskRunner.shutdown()不再提前清空在途任务;MainWindow._stop_stream()不再在 GUI 线程wait(5000)。 - 测试集状态:未评估、未改动
test_once.lock.json、未改动任何准确率数字。
- D-01 终局帧落库:
-
2026-10-29 MODEL 8.2.0 S6 远程部署边界与管理员监听隔离
- 交付配置仍是
[server] host = 127.0.0.1、[network] lan_enabled = 0;未显式开启时任何非回环来源返回403 loopback_only。 - 新增
server/network.py纯函数(client_ip_allowed、host_allowed、origin_allowed等)供中间件与测试共用。 Settings.validate_network()在 socket 打开前拒绝:非回环但未开 LAN、0.0.0.0/公网绑定、TLS 缺证书、白名单缺失、管理端口与用户端口相同等。反向代理模式允许,但应用不信任X-Forwarded-For。- 新增
[network]/[client]一批配置项;TLS 启用时非 HTTPS 返回403 tls_required,HTTPS 响应加 HSTS。 - 新增
scripts/make_tls_cert.py:生成 ECDSA P-256 本地 CA 与叶证书,SAN 固定含localhost/127.0.0.1/::1。
- 交付配置仍是
-
2026-10-29 MODEL 8.2.0 S5 深色终端配色与表格体验
client/theme.py的COLORS重映射为深海蓝终端色板:背景#0a1628、侧栏#081426、卡片#102138、正文#eaf3fc;QSS 中 43 个旧色值同步替换。- 统计数字、比分、价格用
Cascadia Mono/Consolas/monospace;正文仍用微软雅黑。 - 新增
client/theme_contrast.py(WCAG 2.1 对比度)与scripts/check_ui_contrast.py;本次 34 组全部通过,最低 4.65:1。 - 赛事列表虚拟化:删除
MatchRow+QListWidget,改为MatchListModel(QAbstractTableModel)+MatchDelegate,update_match/row_for均为 O(1)。
-
2026-10-29 MODEL 8.2.0 S4 安全边界(客户端脱敏 / 心跳容忍 / SSE 上限)
- 新增
server/services/redact.py,文件头写SECURITY-BOUNDARY: do not relax;CLIENT_ALLOWED是唯一客户端字段白名单。 redact_prediction(prediction, tier):三档会员只改变允许展示的字段集合,任何档位都不是内部对象直通;none返回None。- 因子只返回
name/side/direction;impact、weight、detail全部丢弃。预测不再下发model_version、factor_log、任何lambda_*字段;推荐不再下发edge、kelly_fraction。 - 赛事状态不再下发
source、home_elo/away_elo、近期战绩、休息天数、联赛均值;data_quality.source中的数据源品牌词被移除。
- 新增
-
2026-10-29 MODEL 8.2.0 每日训练闭环、公测压测与后台反馈 / 模型页
- 新增
server/services/daily_training.py:由BeatClock每 60 秒检查一次、按 UTC 小时触发;单飞、子进程隔离、超时杀进程、stdout/stderr 落盘、运行记录写daily_training_runs。 - 默认只使用缓存的 football-data.co.uk CSV;
model.daily_train_refresh_data=1时才加--refresh-data。 - 新增
GET /api/admin/train/runs、POST /api/admin/train/run;忙碌返回409 training_busy,触发写审计日志。 - 新增
tests/test_daily_training.py:到期判断、单飞、成功落库与回调、脚本缺失失败关闭、门槛拒绝退出码、忙碌 409。
- 新增
-
2026-10-28 预注册 · 未采用 A2 GBDT 对比实验(预注册,未采用)
- 新增
docs/GBDT_PREREG.md:在运行实验前写定特征(12 个赛前字段)、超参数(60 轮 / 深度 2 / 学习率 0.10 / L2 1.0 / 最小叶样本 200 / 32 分箱 / 行采样 0.8 / 种子 42)、评价指标与采用规则。 - 新增
backtest/gbdt.py:纯 Python 直方图 GBDT(softmax 三分类、二阶叶值、分位分箱),无第三方依赖,不接入server/或client/。 - 新增
scripts/experiment_gbdt.py:只读训练集与验证集,测试集不参与;连续两次运行输出逐位一致(SHA-256 相同)。 docs/MODEL_SELECTION.md的 GBDT 章节由「未执行」更新为「已执行、不采用」。11 特征验证集 RPS:GBDT0.203774、factor_full0.205477、market0.200346—— 仍落后市场。
- 新增
-
2026-10-28 MODEL 8.2.0 A1 进球校准修正(算法优先阶段)
- 背景:S3 的
reports/GOALS.md记录总进球系统性偏高 —— 验证集 λ 均值 3.5350 vs 实际 2.7942,测试集 3.5430 vs 2.8138。两个来源:射门代理水平偏高(每队 1.614 vs 实际 1.388,+16.3%)、休息因子把「休息充分」当成加分项。 backtest/features.py新增_fit_proxy_scale(),只用训练集前 60% 且含技术统计的场次拟合,本次proxy_scale = 0.853472(截断 0.5–1.5);权重不变(0.08 / 0.12 / 0.02)。factors/layers.py休息因子改为拥堵惩罚1.0 − 0.025 × max(0, 4 − rest),截断 [0.9, 1.0];4 天及以上正常休息不再获得加成。backtest/run.py新增--val-only:只评估验证集,不计算测试预测、不读写test_once.lock.json、不写任何报告。
- 背景:S3 的
-
2026-10-28 MODEL 8.1.0 S3 多市场回测与结论标注
backtest/clean.py解析 B365 两路大小球 2.5 与 B365 收盘亚盘。2015–2018 的 Betbrain 列没有被替换成市场基准 —— 市场对比必须始终是同一家博彩公司。backtest/config.py固定OU_LINES=(1.5, 2.5, 3.5)、AH_LINES=(−1.0 … +1.0,0.25 步长)。- 新增
binary_metrics()(Brier / LogLoss / ECE / 方向命中率 / Wilson 95% CI);走水从命中率分母剔除并单列push_rate;亚盘四分之一线按 0.25 / 0.75 分数结算。 - 服务端
server/model/engine.py新增MARKET_REFERENCE,随预测下发market_reference;客户端只逐字渲染服务端结论,不自行计算任何统计判定。
-
2026-10-28 MODEL 8.1.0 · factor-1.1.0 S2 指标可信变更记录
confidence→data_quality/data_quality_label/data_quality_breakdown,对外统一显示「数据完整度」,不再暗示命中率。- 数据库
match_predictions.confidence迁移为data_quality,保留历史数值;没有删表、没有重算历史行。 - 实时 xG 可用时禁用射门代理,消除双重计数;xG 强度按
minute / (minute + 30)做时间收缩。 - 实时客队 Elo 系数改为
clamp(2.0 − elo_factor, 0.7, 1.6);赛前冻结映射保留,避免测试集二次评估。 - 删除
server/model/engine.py内重复的_poisson_pmf/_score_matrix/_asian_handicap,统一从factors.probability导入;因子链失败直接抛RuntimeError,不再用启发式兜底。
版本号对照
条目里出现的版本号是当时的版本,不是当前版本。当前版本以
common/version.py 为准:
| 常量 | 当前值 | 说明 |
|---|---|---|
| APP_VERSION | 1.1.0 | 本页下载的安装包版本 |
| MODEL_VERSION | 8.3.0-dc-elo-live | S6–A2 阶段为 8.2.0,S3/S2 阶段为 8.1.0 |
| LIVE_FACTOR_MODEL_VERSION | factor-1.3.0 | S4–S6 阶段为 factor-1.2.0,S2 阶段为 factor-1.1.0 |
| PREMATCH_MODEL_VERSION | factor-prematch-1.2.0 | S4–S6 阶段为 factor-prematch-1.1.0 |
| METRICS_VERSION | metrics-2.0.0 | S8 阶段引入;此前的 Brier 不可比 |
读这份日志要注意的三件事
测试集不是干净的留出集
测试集已被评估 4 次并冻结,不再具备「一次性留出集」的统计含义。 测试集数字只能作为历史披露,不能用于选模型或调参。
Brier 口径换过
metrics-2.0.0 把多分类 Brier 从「三类平方误差之和」改成「均值」。
旧报告里的 Brier 约为现在的 3 倍,不能跨版本直接比较。
有些验收没真跑
项目自己写明:G3 真实比赛日跑满一天后的数据库检查未执行; G6 真实断网 30 分钟未执行;G7 真实收款链未执行。 「不要把自检/仿真写成真实长跑结论」。