预测维度 · 因子链 · 实时 / 赛前 · 客户端

功能

从 λ 到概率到 edge,一条链上的每一步都能在源码里找到对应实现; 每个市场都标了「是否优于公开盘口」,不优于的地方原样写出来。

一、预测维度

1X2 胜平负

赛前 λ 加 Dixon-Coles 低比分修正 ρ 生成精确比分矩阵,再对矩阵求和得到主胜 / 平局 / 客胜三路概率。 回测中 ρ 只在训练集上网格搜索得到,本次取值 −0.06;因子路径单独拟合 factor_rho = −0.05, 不复用 Poisson λ 的 ρ。

来源:reports/baseline.md「模型定义」 来源:reports/metrics.json → config.rho / config.factor_rho 来源:reports/CHANGES.md「M-07/M-08 Dixon-Coles 口径」

大小球 OU(1.5 / 2.5 / 3.5)

同一条比分矩阵求总进球超过指定线之和。市场对比只固定用 2.5:1.5 与 3.5 没有公开的两路报价, 所以只报告模型自身指标,不虚构市场基准。

线测试集 nBrierLogLossECE方向命中率(95% CI)市场基准
1.564980.17030.52210.007577.73% (76.70–78.73)无公开两路报价
2.564980.24420.68150.010256.79% (55.58–57.99)不优于公开盘口
3.564980.20830.60620.013669.31% (68.18–70.42)无公开两路报价
来源:reports/MULTI_MARKET.md「测试集 → 大小球」

亚洲让球 AH(9 档网格)

网格覆盖 −1.00 / −0.75 / −0.50 / −0.25 / ±0.00 / +0.25 / +0.50 / +0.75 / +1.00。 半线以下按四分之一球结算,走水从命中率分母中剔除并单列 push_rate。 收盘线市场对比用每场 AHh 实际报价,没有该报价的场次不进入对比(n = 6489 而非 6498)。

线n已决走水率Brier方向命中率(95% CI)
−1.006498510521.44%0.146175.42% (74.22–76.58)
−0.75649864980.00%0.172464.22% (63.05–65.38)
−0.50649864980.00%0.219564.47% (63.29–65.62)
−0.25649864980.00%0.177062.73% (61.54–63.89)
±0.006498482325.78%0.158268.21% (66.89–69.51)
+0.25649864980.00%0.163271.51% (70.40–72.60)
+0.50649864980.00%0.192070.61% (69.49–71.70)
+0.75649864980.00%0.146370.11% (68.99–71.21)
+1.006498539716.94%0.117683.44% (82.42–84.40)

亚盘收盘线的模型 Brier 0.2113 vs 公开盘口去水 0.2062, ΔBrier +0.005108(95% CI 0.003522–0.006801)→ 不优于公开盘口。 客户端对该市场标注「仅供参考,不优于公开盘口」。

来源:reports/MULTI_MARKET.md「测试集 → 亚洲让球(收盘线,模型 vs 市场)」 来源:reports/MULTI_MARKET.md「结论」

双方进球 BTTS

测试集 n = 6498,Brier 0.2460、LogLoss 0.6851、ECE 0.0100,方向命中率 55.40%(95% CI 54.19%–56.61%)。该数据源没有公开 BTTS 赔率,因此只报告模型指标。

来源:reports/MULTI_MARKET.md「测试集 → 双方进球」

比分矩阵 / 下一进球(客户端高级分析)

L3 除 1X2 与总进球外,还输出精确比分矩阵与「下一个进球归属」概率; 月卡(advanced)可见比分矩阵、亚洲让球、风险因子,周卡(basic)只有基础分析。

来源:factors/probability.py(final_score_matrix / next_goal_probabilities) 来源:README.md「会员与功能」表 来源:docs/ARCHITECTURE.md §2.7

二、因子链:L0 → L4

引擎与 FastAPI 服务解耦,因此同一套因子既能跑在模型工作进程里,也能跑在离线回测里。 层级规则由注册表在 导入时校验,因子不允许读到同层或更高层。

L0 原始事实

只读数据源事实:比分、分钟、红牌、射门/射正、当前赔率。缺失即缺失,不默认补 0。

L1 单场速率

由 L0 派生单场速率(射门/射正/进攻节奏等),带时间衰减权重。

L2 剩余进球强度 λ

lam_rem_home / lam_rem_away —— 这是唯一允许流向 L3 的输入。 Elo、滚动 10 场 xG 代理、休息天数、联赛均值、红牌修正全部在这一层收敛。

L3 概率

只消费两个 λ(加上 L0 的当前比分/分钟),产出 1X2、总进球、亚盘、下一进球概率。

L4 决策

把概率与价格变成 edge 与四分之一 Kelly 仓位(上限 2%)。这些字段永不通过 API 下发。

校验机制

  • 注册表在导入时校验 DAG 层级依赖
  • 共线性检查只作用于 L1/L2 解释型因子
  • 方向单调性探针把输入扫 100 个分位,要求输出概率单调不减/不增
  • 任一必需输入缺失 → abort 并置 degraded
来源:factors/registry.py 模块文档 来源:factors/__init__.py 来源:reports/CHANGES.md「M-04 缺失不静默」

L2 的魔法数字集中放在 factors/params.py,每个常数带来源标签: 拟合(只在训练集拟合)/ 手调(领域判断,没有拟合证据)/ 文献。 手调值不得被说成「学出来的」。

来源:factors/params.py 模块文档

三、实时与赛前:两条通路,验证程度不同

实时通路(生产)

  • 3 秒 tick 遍历进行中赛事,单场独立协程 + 锁
  • 采集超时 2.0 s,推理硬超时 2.5 s;超时则杀死并重建模型进程池
  • 状态哈希(状态/分钟/比分/统计/赔率)不变则跳过推理
  • 连续失败达到阈值 → 单场熔断,冷却后半开重试
  • SSE 按服务端 tier 裁剪后推送,连接建立时先回放最近事件
来源:docs/ARCHITECTURE.md §2.2–§2.3、§2.9 来源:config.ini [scheduler]

赛前通路(可回测)

  • 用 prematch_lambdas() 把赛前聚合输入灌进同一套 λ 函数
  • ρ 只在训练窗口内拟合,测试年份不参与任何拟合
  • 切分按日历日期分组,整日归入同一侧,并剔除两个边界日期(共 32 场)
  • 只有可用 1X2 赔率的比赛才进入评估,所有模型在同一批行上比较
来源:factors/layers.py :: prematch_lambdas 文档字符串 来源:docs/ACCURACY.md「切分方式」 来源:backtest/config.py(TRAIN/VAL/TEST_RATIO、ODDS_*)

实时通路没有回测验证。上游数据源只有赛前与赛后统计,没有分钟级比赛快照, 所以回测只能验证赛前分支。任何「实时因子链已经过回测」的说法都是错的。

来源:docs/ACCURACY.md 第 36 行 来源:reports/MULTI_MARKET.md「范围与口径」第 11 行

四、客户端能力(Windows PC)

技术栈:Python + PySide6 + PyInstaller,暗色主题,无边框窗口。下面按周卡 basic / 月卡 advanced 分档。

功能周卡 ¥40 / 7 天月卡 ¥300 / 30 天
赛事列表、实时比分✓✓
全部进行中赛事原始数据✓✓
基础分析(胜平负、按实时盘口的大小球、双方进球)✓✓
基础数据完整度与趋势摘要✓✓
高级分析与多盘口矩阵—✓
比分矩阵、亚洲让球、风险因子—✓
深度历史与整场回放—✓
多维度面板与动量分析—✓
来源:README.md「会员与功能」表 来源:config.ini [pricing](week_price_cents = 4000 / month_price_cents = 30000)

页面与模块

赛事

列表、联赛/状态筛选、实时比分、基础与高级预测展示

单场详情

多维度面板、趋势、比分矩阵、比赛事件(3 个 tab)

历史回放

深度历史与整场回放;真实源缺历史帧时只用运行期快照

订阅与账户

套餐、内嵌收银台、会员到期时间、设备信息、退出登录

来源:docs/ARCHITECTURE.md §3 来源:使用说明.md §5「功能说明」

明确未实现项(项目自己写明的)

  • 客户端不是强混淆黑盒:Python + PyInstaller,有能力的本机用户可以还原客户端代码。
  • 原生反调试、代码虚拟化、EXE 自更新均未实现。
  • 证书固定仅在局域网 / HTTPS 模式启用(默认回环 HTTP 无证书可固定)。
  • 白标只改变显示层;EXE 内嵌图标/描述、安装器快捷方式、数字签名需重新构建,当前没有自更新服务器。
  • 不是多机集群 / 主从复制 / K8s 高可用方案;断电或进程被强杀会中断服务。
来源:README.md「重要限制」第 6、7 条 来源:docs/ARCHITECTURE.md §6「非目标与已知限制」 来源:docs/ANTI_TAMPER.md

五、订阅与支付链路

默认:个人二维码 + 人工核账

payment.provider = qr。管理后台上传本人支付宝/微信收款码,用户扫码付款后提交交易单号(4–64 位), 订单进入「待人工确认」,管理员核对账单金额/时间/单号后才发放会员。 同一交易单号只能使用一次。

  • 未上传任何收款码时下单返回 payment_unavailable,不生成无法支付的订单
  • pending 订单 15 分钟过期;claimed 待确认订单不自动过期
  • 被驳回可重新提交,获得新的 15 分钟窗口
  • 收银台明确显示「付款后等待人工确认(通常 10 分钟内)」,不假装自动到账
来源:config.ini [payment] 来源:使用说明.md §4.1

可选:商户网关异步回调

payment.provider = custom_webhook。需配置 custom_webhook_url 与 custom_webhook_secret_file;回调必须带 X-Webhook-Timestamp 与 X-Webhook-Signature,服务端按 HMAC-SHA256(secret, timestamp + "." + raw_body) 验签。

  • 校验时间窗、金额、币种、订单号与流水唯一性
  • 重复回调幂等,不重复发放
  • wechat_native / alipay_face 未接入官方 SDK 时 fail-closed,不生成假二维码
  • sandbox 仅用于功能验收,不能收取真实款项
来源:README.md「一键启动」段 来源:docs/PAYMENT_INTEGRATION.md