📋 复盘报告 修复与复盘交付报告-2026-09-10.md
修复与复盘交付报告-2026-09-10.md | 位置:C:\qinglong\ticai\竞彩北单预测\reports\修复与复盘交付报告-2026-09-10.md修复 · 复盘 · 预测 · 串关 —— 整合交付报告
- 日期:2026-09-10
- 范围:保活根治 + 计划任务加固 + 数据质量修复 + 今日全场复盘 + 补预测 + 串关复盘
- 结论:6 项修复全部落地并实测验证;今日预测覆盖 100%;全场复盘 75 场(已比对 17 场,胜平负命中率 76%);串关实验 ROI 转正 +0.4%
一、执行摘要
| 项目 | 结果 | 验证方式 |
|---|---|---|
| --- | --- | --- |
| 保活(根治待机杀进程) | ✅ 已落地 | powercfg /requests SYSTEM 段出现 python 进程 |
| Web 自动恢复(看门狗) | ✅ 已上线 | WB_WebWatchdog LastResult=0,20:25 正常巡检 |
| 计划任务声明式重建 | ✅ 6 个任务 | 全部 StartWhenAvailable=True、允许电池运行 |
| 告警静默修复 | ✅ 双通道 | logs/alerts.log 实测落盘 |
| 赛果重复入库 | ✅ 写入防线 + 清理 55 行 | 150,365 → 150,310 |
| 健康检查口径 | ✅ 九维度全绿 | health_check.py 结论「健康 ✅」 |
| 今日补预测 | ✅ 5 场全部恢复方向 | 占位「—」→ 市场隐含/上游共识 |
| 今日全场复盘 | ✅ 75 场 / 已比对 17 场 | 胜平负 13/17 = 76% |
| 串关复盘 | ✅ 325 条 / 276 已结算 | ROI +0.4%(+12.54 元) |
二、保活:根治"系统待机杀进程"
根因(上一轮已定位)
系统空闲 120 秒进入新型待机(Modern Standby),把无人值守的长任务进程杀掉,
计划任务返回 0x8007042B(ERROR_PROCESS_ABORTED)。09-09 流水线死于 08:35:11,
5 秒后系统进入待机;09-10 同窗口两次待机;09-08 之所以跑满 94 分钟,是因为
当时有人操作、鼠标活动维持了唤醒。
修复(改代码,不动系统电源策略)
新增 core/keepawake.py:调用 Windows SetThreadExecutionState
(ES_CONTINUOUS | ES_SYSTEM_REQUIRED),守护线程每 30 秒续期。
几个刻意的设计选择:
- 不申请
ES_DISPLAY_REQUIRED—— 屏幕可以正常熄灭,只保"系统不被判定空闲",
对笔记本日常使用影响最小;
- 失败只记日志、绝不抛异常 —— 保活是增强项,不能反过来弄挂主流程;
KYGZ_NO_KEEPAWAKE=1可整体关闭 —— 调试/受限环境留出口;- 两侧都接入:
app.py(Web 进程)与automation/run_daily.py(流水线进程)。
原因是 Power Request 按进程生效、不被子进程继承,而流水线通常由 Web 进程内的
daily_scheduler 以子进程拉起 —— 只在一侧声明会漏掉另一侧。
实测:powercfg /requests 的 SYSTEM 段出现 [PROCESS] python.exe ✅
⚠️ 一个必须说明的时序问题
当前正在运行的 Web 进程与流水线都启动于保活代码落盘之前——Python 不会热加载改动的
代码,所以它们体内还没有保活逻辑。也就是说,今天这一轮补跑流水线仍在待机风险下。
已用新增的 scripts/keep_awake_hold.py --until-pid 42788 起了独立保活守护临时覆盖
(目标进程退出即自动释放,已确认登记进 SYSTEM 电源请求)。
下次重启后保活永久生效(明天 08:30 计划任务起来即是新版)。
三、计划任务加固
新增 Web 看门狗
WB_WebApp 原来只有 BootTrigger —— 进程被杀后任务仍是 Ready,不会自愈,端口 5000
就此长期无监听。新增 WB_WebWatchdog(每日 00:00 起每 5 分钟,持续 23h55m):
- 探活
127.0.0.1:5000/,健康时绝不动作(避免打断正在跑的流水线); - "端口有监听但 HTTP 不通"判定为僵死 → 先
/end再/run(否则IgnoreNew会拒绝新实例); - 拉起后复检 3 次,失败与恢复都经
core/alerts落盘(同类 30 分钟内去重)。
声明式安装器
新增 scripts/install_tasks.py,把 6 个 WB_* 任务从代码生成 Task Scheduler XML 注册。
起因是旧的 automation/install_task.bat 任务名写着「体彩每日自动化」、时间是 02:00,
与现网实际在跑的 6 个任务完全不符 —— 照着它装只会装出一个没人知道的野任务。
统一电源策略为 StartWhenAvailable=true + 允许电池运行:掉电或错过时间窗都不再
放弃这一轮(介意电池耗电可传 --conservative-power 改回)。
一个有用的实测结论
担心"重新注册任务会连坐杀掉正在跑的流水线",所以先用一次性探针任务做了实验:
Register-ScheduledTask -Force 不会终止正在运行的实例(改定义前后探针进程都存活、
任务状态仍 Running)。确认后原位同步了 WB_WebApp,流水线与 Web 进程均安然无恙。
install_task.bat
重写为纯 ASCII 转调脚本。原因:cmd.exe 按 OEM 代码页(中文 Windows 为 936/GBK)
解析 .bat,UTF-8 的中文路径会在执行前就被花掉;把逻辑全部放进 Python,.bat 只负责
找到解释器并转发参数。
四、告警与日志
| 问题 | 修复 |
|---|---|
| --- | --- |
alerts.webhook_url 为空 → notify_on_fail: true 形同虚设,两天故障静默 | 新增 core/alerts.py 双通道:本地 logs/alerts.log 永久落盘(无需任何配置)+ 配置 webhook 后推送。异常时也落盘 |
| Web 任务动作无 stdout 重定向,被杀时磁盘零痕迹 | app.py 增加 RotatingFileHandler → logs/app.log(10MB ×5)。进程内落盘比 shell 重定向可靠,不依赖谁以何种方式拉起 |
logs/alerts.log 已实测有内容(看门狗故障模拟)。五、数据质量
赛果重复入库(真实问题)
根因:yucejia 与 qiulaile-HTFT 两条通道对同一场比赛各写一行 ——
一行 match_id 是 yucejia 上游返回的 32 位哈希(直接调其 API 确认,上游本身如此),
另一行是 qiulaile 的数字 ID。match_results 主键是 (source, match_id),
唯一约束拦不住,近 30 天积累 57 组,会被训练配对管线重复计数。
修复:
1. data/store.py 新增写入防线 drop_fixture_duplicate_rows —— 仅当
同源 + 同对阵 + 同日 + 同分且 match_id 不同才判重;比分冲突视为真实冲突两行都留。
索引按日期批量预载,避免退化成 O(N²)。
2. 新增 scripts/dedupe_results.py(默认演练,--apply 才落库),已执行:
赛果 150,365 → 150,310(删 55 行),2 组比分冲突按设计保留待人工确认。
备份用 SQLite 在线 backup API 而非文件复制(WAL 模式下直接 copy 会漏掉未 checkpoint 的内容)。
健康检查口径
- 非法赔率(全表仅 8 条 / 221,553 行 = 0.004%,全为德国杯/国王杯首轮强队客战业余队的
上游客胜赔率触底截断):FAIL → WARN,条数 ≥50 才 FAIL(解析器回归时会飙升,仍能拦住)。
- 重复赛果拆成"同分(可安全清理)/ 比分冲突(需人工确认)"两级,同分 ≥30 组才 FAIL。
结果:九维度全绿,health_check.py 结论「健康 ✅」
六、今日补预测("没有预测的进行预测")
定位过程
今日在售范围去重后 71 场,初筛 5 场方向为 —(无可用源):
26093-47 / 26093-48 / 26093-55(英冠)、26093-40(荷甲)、okooo-3010(英冠)。
根因链(逐层验证)
config.yaml: fusion.league_blacklist = [法乙, 国际友谊, 英冠, 荷甲] ↓ 判据:全量回测 ROI 法乙-7.8% / 国际友谊-7.7% / 英冠-7.2% / 荷甲-6.5% predict_match() 命中黑名单 → 直接返回空 Prediction(无 market_probs / 无 extras) ↓ rule_spf = None;若上游同时缺席 → _fuse_spf 三源全空 ↓ 退化为均匀分布 0.33/0.34/0.33 → top_pick 落成占位「—」 ↓ 预测记录存在但**没有方向**,复盘无从谈起
修复
core/fusion.py 新增:
_market_implied_spf(snapshots)—— 取快照中最新一组"标准胜平负"赔率去水;
让球档的 win/draw/lose 为 0,天然被排除;
_fuse_spf(..., fallback_probs=...)—— 仅当规则/ML/上游/KNN 全部缺席时才回退
市场隐含概率,来源显式标注「市场隐含」。
为什么用市场隐含兜底而不是放宽黑名单:黑名单是投注回避规则,不该顺带剥夺
"给个方向"的能力;而去水后的市场隐含概率正是项目长期结论里最强的基线
(欧赔/亚盘市场高度有效),用它兜底既给出可复盘的方向,也不冒充规则/ML 判断。
predict_match 的黑名单语义保持不动 —— 兜底只在融合层生效,既有测试全部不受影响。
落库
竞彩此前没有任何独立落库入口(只能等每日流水线)。新增
scripts/persist_predictions.py(--market jingcai|beidan|all、--db-day 历史回补、
--check 只统计)。
已执行并验证:5 场全部恢复方向(26093-47 负 / 26093-48 胜 / 26093-40 胜 /
26093-55 负 / okooo-3010 负)。
今日覆盖复核:75 场,占位方向 0 条 —— 100% 有方向。
方向分布 胜 33 / 负 30 / 平 12 来源分布 规则引擎 56 · 规则引擎+上游共识 14 · 市场隐含 3 · 上游共识 2
prediction_key 含来源与版本,预测值变化时新增行;created_at(见 store._prediction_update_sql)。created_at 最大者,不是 id 最大者 ——26093-40/-55scripts/persist_predictions.py 的统计口径已按此修正。>
--db-day 回补;竞彩历史无法回补七、今日全场复盘
为什么不走 backtest/review.py --start/--end
该路径按 canonical_key = (date, league, home, away) 对齐 —— 联赛名参与键。
实测:同一场比赛赔率侧叫「美职业」、赛果侧叫「美职」,键不同即无法对齐;
2026-09-10 赔率侧 282 个 fixture、赛果侧仅 4 条通过严格过滤,交集 0 → 复盘出 0 场。
改用 AutoReviewPipeline(与每日流水线报告同源:store 路径 + 队名模糊桥接),
并新增 scripts/run_review.py 作为可直接调用的复盘 CLI。
结果(2026-09-10)
| 指标 | 数值 |
|---|---|
| --- | --- |
| 场次总数 | 75 |
| 已比对 | 17 |
| 待回填 | 58(今晚欧战尚未开赛) |
| 胜平负命中率 | 13/17 = 76% |
| 比分 Top5 覆盖率 | 9/17 = 53% |
已比对 17 场全部为竞彩(okooo-3001~3015 与 周四001~007)。逐场命中示例:
欧冠 里斯本 3-1 ✅、那不勒斯 0-1 ✅、利物浦 2-1 ✅、切尔西 6-3 ✅、
拜仁 3-0 ✅、曼联 4-0 ✅;未中:查尔顿 0-0(预测胜)、芝加哥 1-1(预测负)、
费内巴切 4-1(预测负)、阿马多拉 3-0(预测负)。
⚠️ 口径不一致(值得注意)
复盘走的是 predict_match 的旧仓位口径(STAKE_UNITS:标准投注 100 / 减半 50 / 放弃 0),
今日 15/17 判为「放弃」,于是"模拟盈亏"只由 1 场决定(-100 单位),参考价值很低。
而 core/recommender.py 的"强制不放弃"规则下这些场次都有仓位。两套口径不同源,
不可直接对比。建议:复盘报告把"命中率"作为主指标,"模拟盈亏"标注为规则引擎旧口径,
或后续统一到推荐引擎口径(会改变历史可比性,需单独评估)。
八、串关复盘
补结算后重新统计(scripts/settle_parlays.py + scripts/parlay_tracker.py):
| 指标 | 数值 |
|---|---|
| --- | --- |
| 总条数 | 325(已结算 276 / 待结算 49) |
| 命中 | 20 胜 / 256 负,命中率 7.2% |
| 投入 | 2,814 元 |
| 净盈亏 | +12.54 元 |
| ROI | +0.4% |
| 进度 | 325/60 条(542%),17/30 天(57%) |
分组明细
| 市场/玩法 | 条数 | 已结算 | 命中率 | 盈亏 | ROI |
|---|---|---|---|---|---|
| --- | --- | --- | --- | --- | --- |
| beidan/hcap | 40 | 36 | 16.7% | +872.40 | +302.9% |
| beidan/score | 30 | 25 | 4.0% | +259.36 | +129.7% |
| beidan/spf | 63 | 55 | 7.3% | +101.68 | +18.0% |
| jingcai/htft | 3 | 3 | 33.3% | +57.00 | +38.0% |
| jingcai/single | 2 | 2 | 100% | +12.60 | +31.5% |
| jingcai/hcap | 40 | 33 | 15.2% | -76.00 | -28.8% |
| jingcai/spf | 52 | 46 | 2.2% | -486.50 | -84.2% |
| jingcai/goals | 30 | 23 | 0% | -184.00 | -100% |
| jingcai/score | 30 | 23 | 0% | -184.00 | -100% |
| beidan/goals | 30 | 25 | 0% | -200.00 | -100% |
读数:整体靠 beidan 让球盘单点撑起(+872.40,占全部正贡献的绝大部分);
jingcai 侧全线为负,其中 spf/goals/score 三个玩法是主要失血点。
命中率 7.2% 是高倍串关的设计后果,但 276 条样本下 ROI 仅 +0.4% 说明**这套选场尚未
证明有正期望** —— 建议再积累到 30 天/60+ 条门槛后重判,暂不下结论。
九、改动文件清单
新增(8 个脚本/模块 + 3 个测试)
core/keepawake.py 保活核心 core/alerts.py 告警双通道 scripts/web_watchdog.py Web 看门狗 scripts/install_tasks.py 计划任务声明式安装器 scripts/dedupe_results.py 重复赛果清理 scripts/persist_predictions.py 预测落库单次执行器 scripts/run_review.py 全场复盘 CLI scripts/keep_awake_hold.py 限时保活守护(应急) tests/test_keepawake.py 13 项 tests/test_results_dedup.py 11 项 tests/test_fusion_market_fallback.py 10 项
修改
core/fusion.py 市场隐含兜底(_market_implied_spf + _fuse_spf fallback) data/store.py 赛果入库去重防线 + 索引化 health_check.py 非法赔率/重复赛果判定口径 app.py 保活接入 + 文件日志(RotatingFileHandler) automation/run_daily.py 保活接入 automation/install_task.bat 重写为 ASCII 转调
计划任务
新增 WB_WebWatchdog 每 5 分钟探活,不可达自动拉起 Web
重建 WB_WebApp / WB_DailyPipeline / WB_SnapshotLoop / WB_BeidanPersist / WB_Backup
(统一 StartWhenAvailable + 允许电池运行)
产出报告
reports/健康检查报告-2026-09-10.md 九维度体检(含根因证据链) reports/复盘报告-2026-09-10-全场.md 今日 75 场逐场复盘 reports/修复与复盘交付报告-2026-09-10.md 本文件
十、遗留与建议
| 优先级 | 事项 | 说明 |
|---|---|---|
| --- | --- | --- |
| P0 | 重启 Web 与流水线 | 当前进程早于保活代码启动,体内无保活;下次计划任务触发即自动带上(明天 08:30) |
| P1 | 复盘仓位口径不一致 | 复盘走规则引擎旧口径(今日 15/17 判「放弃」),与推荐引擎"强制不放弃"不同源 |
| P1 | alerts.webhook_url 仍为空 | 本地落盘已兜底,但主动推送需要一个机器人 webhook 地址 |
| P2 | 历史占位方向 47 条 | jingcai 21 / beidan 26,09-03~09-08,全为黑名单联赛;北单可按 --db-day 回补,竞彩历史不可回补 |
| P2 | 2 组比分冲突赛果 | 队名为空,疑为已隔离的假比分残留,需人工确认 |
| P3 | 串关选场待观察 | 276 条样本 ROI +0.4%,尚不足以判定正期望;jingcai 侧全线为负值得专项排查 |
*本报告所有结论均附可复现证据;新增/修改代码均配套单元测试。*