因为我个人喜欢看足球,就一直以娱乐心态在小额投资。直到前年AI Coding工具越来越成熟,某一日突发念头想记录下自己的投资记录,用来沉淀数据和分析洞察。当开始着手做出第一版后,功能就从纯为记录慢慢演化为大小球分析。截止今日,已演进了三个阶段:从人工判断到AI辅助,再到回测量化。收益情况也能整体上有所盈利,但胜率还是未能保持长期稳定,某一个策略可以连续5、6轮均盈利,但在某轮开始失效出现亏损。
上周欧洲五大联赛均已收官,那就趁有空了,记录下演进迭代过程,也算是一个阶段性总结。
同时,接下来我将在赛前发布量化分析框架对中超赛事大小球分析结果,也欢迎有兴趣的朋友一起讨论、优化量化框架。
第一阶段:纯记录和人工分析
项目刚开始那会儿,大小球怎么判断?全靠人肉看。每场比赛前打开几个网页,扫一遍:
- 基本面:两队最近踢得怎么样、历史交锋谁占优、排名大概在哪个位置
- 盘口与指数:主流公司的大小球盘口线开到多少,指数在往哪个方向走
- 情报信息:谁伤了谁停赛、球队战意如何、赛程紧不紧、天气怎样
然后就拍脑袋和凭直觉决定了。在系统上记录比赛信息、盘口和指数、去水后的隐含概率、我的信心概率、理由依据等,用于后续统计自己判断的胜率和ROI等。
这一阶段的问题不是准确率高低的问题——是根本没法全面复盘。赢了不知道是真看准了还是蒙的,输了也说不清是哪个环节判断错了。更麻烦的是,分析能力完全绑定在个人状态上,今天心情好和心情差,看同一场比赛可能得出完全不同的结论。
第二阶段:AI辅助分析
大模型能力上来之后,我开始试着把AI塞进分析流程里。这个阶段前后改了五次。
2.1 初探:比赛信息 + 盘口指数(XL策略)
最简单粗暴的做法:把比赛基本信息(谁打谁、什么联赛、第几轮)和盘口指数扔给大模型,让它自己联网搜情报,然后给结论。
输入数据:
- 比赛基本信息(主队、客队、联赛、时间)
- 大小球盘口和指数
- 模型联网搜索能力(伤病、天气、战术信息)
方法特点:
- 完全依赖大模型的推理和搜索能力
- 没有任何结构化历史数据支撑
- 提示词就一句话的事:"预测下列比赛的大小球"
效果:
- 好处:模型能快速整合多源信息,输出看着像模像样的分析报告
- 坏处:模型会编数据,分析缺乏量化依据,结论可信度没法验证
这一轮至少验证了一件事:大模型确实能理解足球分析需要的那套推理逻辑。但"裸调"的方式太糙了,分析质量和抛硬币的区别没那么大。
2.2 引入统计数据(ML策略)
把数据采集从模型的"黑盒"里拿出来。系统先爬好结构化数据,模型只负责分析,不负责找数据。
新增输入:
- 主客队近期比赛的数据(交锋记录、近期战绩、积分榜排名)
- 球队技术统计(射门、射正、控球率、危险进攻等指标)
方法演进:
- 从"让模型自己搜索一切"变成"系统预采集 + 模型分析"
- 提示词拆成三块:比赛信息 → 联网搜索指令 → 结构化统计数据
- 大模型强制开联网搜索,确保情报是最新的
关键进步:
数据采集不再交给模型"黑盒"处理了。系统预先爬好结构化数据再喂给模型,幻觉空间小了很多。模型的分析好歹建立在真实数据上,不至于凭空编造。
还是没解决的问题:
- 所有分析还是靠一次模型调用,分析准确性没法验证。而且,同样的输入,大模型多次分析的结果可能是不一样的。
- 没有历史投资数据做反馈,同样的坑可能反复踩
2.3 联赛数据洞察与历史投资数据(SL策略)
这次把视野从"单场比赛"拉到了"整个联赛",并且开始用历史投资数据说话了。
新增能力:
-
联赛级别的大小球洞察:
- 统计同联赛所有赛事在不同盘口区间的大小球分布
- 计算各盘口档位的大球率、小球率
- 给出联赛倾向性(比如"中超本赛季大球倾向55%")
-
历史投资数据反馈:
- 读取历史投资记录,按主客队筛选
- 生成CSV格式的历史投资明细让模型参考
- 分析相同盘口区间的历史命中率
-
盘口变动分析(市场微观结构):
- 对比初盘与即时盘口的变化方向(升盘/降盘)
- 对比初盘指数与即时指数的变化(升水/降水)
- 解读市场资金流向——所谓"聪明钱"在往哪边走
-
进阶价值模型:
- 从抓取到的联赛的历史记录计算ROI、期望值(EV)
- 用Z-Score评估统计显著性
- 凯利公式(Kelly Criterion)算最优投资比例
- 威尔逊下界(Wilson Lower Bound)给保守胜率估计
方法架构:
┌─────────────────────┐
│ 大模型(LLM) │
│ enable_thinking=True │
│ enable_search=True │
└──────────┬──────────┘
│
┌───────────────┼───────────────┐
│ │ │
┌──────▼──────┐ ┌─────▼─────┐ ┌──────▼──────┐
│ 爬取的比赛 │ │ 联赛洞察 │ │ 历史投资 │
│ 统计数据 │ │ 分析报告 │ │ CSV数据 │
│ (crawl) │ │ (analysis │ │ (bet_csv) │
│ │ │ _md) │ │ │
└─────────────┘ └───────────┘ └─────────────┘
关键进步:
这是第一次把分析从"单场视角"升级为"系统视角"。模型不再孤立地看一场比赛,能看到这场比赛在联赛中的位置、类似盘口的历史分布、以及之前投资的成败记录。
还是没解决的问题:
- 所有数据最终汇入单一模型调用,信息量太大模型容易顾此失彼
- 不同分析维度的权重全由模型自己掂量,没有标准
- 联网搜索结果质量不稳定,如伤停情报、士气、天气等数据时好时坏
- 同一数据输入,多次分析的结果存在差异
2.4 多Agent协作模式(MAG策略)
一个模型处理所有信息不行,那就拆成多个专业Agent各管一摊。
Agent架构:
| Agent | 模型 | 职责 | 配置 |
|---|---|---|---|
| 情报总监 (Chief Intelligence Officer) | qwen3.5-plus | 联网搜索实时情报(伤病、天气、战术) | search=enabled, temperature=0.3 |
| 高级数据分析师 (Senior Data Analyst) | qwen3.5-plus | 分析统计数据、联赛洞察、历史投资 | search=disabled, temperature=0.1 |
| 首席投资策略师 (Lead Betting Strategist) | qwen3-max | 综合前两个Agent输出做最终决策 | thinking=enabled, temperature=0.3 |
执行流程:
情报总监(联网搜索) ────┐
├─── 并行执行 ───┐
数据分析师(数据处理) ────┘ │
▼
首席投资策略师(综合决策)
│
▼
最终预测输出
编码到提示词中的决策原则:
- 每个结论必须标注数据来源,没来源的别说
- 冲突处理规则:实时情报与历史数据矛盾时——伤病/战术因素优先采信实时情报,统计规律优先采信历史数据
- 盘口阈值规则:盘口≥3球且有防守信号 → 倾向小球;盘口≤2.25且战意低 → 倾向小球
关键进步:
- Agent各司其职:搜信息的、做数据的、拍板的,不同模型实例干不同事,各自用最适合的配置
- 情报搜集和数据分析并行跑,省时间
- 明确的决策规则减少了模型瞎发挥的空间,分析一致性提高不少
- 用CrewAI框架编排,分析过程完整记录到AnalysisLog表,后面复盘方便
还是没解决的问题:
- 多Agent协调带来了新的不确定性——Agent之间传话可能漏掉关键细节
- 定量计算(期望值、概率估计)还是模型在做,精确度没保证
- 各维度权重仍然由模型隐式决定,没法验证和优化
2.5 权重量化分析框架(KL策略)
这一版思路彻底变了。之前是"把数据给模型,让它自己判断",现在是"系统能算的全部算好,模型只填系统算不了的空白"。
A-F模块框架:
| 模块 | 权重 | 内容 | 计算方式 |
|---|---|---|---|
| A 攻防能力 | 35% | 进攻质量、防守开放性、过程-结果修正 | 技术统计与联赛均值对比,加权指数化 |
| B 节奏机会 | 20% | 比赛节奏、有效终结、转换威胁、定位球 | 射门/射正/快攻/角球等指标加权评分 |
| C 伤停战术 | 15% | 伤病、停赛、战术阵型、球队新闻 | 只有这个模块由模型联网搜索评分 |
| D 赛程战意 | 10% | 赛程负荷、积分榜紧迫度 | 7天/10天窗口赛程密度 + 排名位置打分 |
| E 指数定价 | 15% | 同盘口历史分布、初盘EV分析、盘路变化 | MatchOddsData历史回测 + 分层衰减模型 |
| F 外部因素 | 5% | 天气影响、外部稳定性 | 模型联网搜索评估 |
评分机制(以Module A为例):
每项技术统计与联赛均值比较,计算偏离百分比,映射到五档标准分:
| 偏离幅度 | 得分 |
|---|---|
| ≥ +15% | 100 |
| +5% ~ +15% | 75 |
| -5% ~ +5% | 50 |
| -15% ~ -5% | 25 |
| ≤ -15% | 0 |
子指标计算举例(按权重加权求和):
- A模块中的 A1(进攻质量)= 0.40×射正指数 + 0.30×关键传球指数 + 0.20×危险进攻指数 + 0.10×进球指数
提示词结构:
┌──────────────────────────────────────┐
│ 1. 比赛基本信息(含时区转换) │
├──────────────────────────────────────┤
│ 2. A-F框架说明(~60行评分规则和公式) │
├──────────────────────────────────────┤
│ 3. 综合技术统计(match_team_technical │
│ _stats表) │
├──────────────────────────────────────┤
│ 4. 预计算的A/B/D/E/F模块得分表 │
├──────────────────────────────────────┤
│ 5. 过滤后的市场分析(MatchOddsData) │
├──────────────────────────────────────┤
│ 6. 赛程密度(从爬取数据解析) │
├──────────────────────────────────────┤
│ 7. 积分榜和近期战绩(爬取数据) │
├──────────────────────────────────────┤
│ 8. 模型联网搜索(填充Module C + F) │
└──────────────────────────────────────┘
这一版的意义:
模型的角色从"全权分析师"缩小为"情报研究员 + 综合研判者"。量化评分有了明确公式和权重,每一项都可以独立验证和调优。模型的幻觉被关进了Module C(伤停情报)的笼子里,不再污染其他模块。这套框架后来成了第三阶段的底座。
第三阶段:回测量化分析(QX策略)
设计动机
KL策略有个别扭的地方:系统明明已经算出了所有模块的量化得分,但最后还是模型说了算。模型可能完全忽略量化信号,或者对得分的理解跑偏。这就让人想一个问题:
如果我们已经用精确公式算出了A/B/D/E/F模块得分,为什么还需要模型来做最终判断?
答案是可以不需要。用历史数据训练一个校准层,直接把模块得分映射为概率预测就行了。
方法架构
┌─────────────────────────────────────────────────────┐
│ QX策略架构 │
├─────────────────────────────────────────────────────┤
│ 输入:联赛、赛季、轮次、主客队、盘口、大小球指数 │
├─────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐│
│ │ Module A │ │ Module B │ │ Module D │ │Module E ││
│ │ 攻防能力 │ │ 节奏机会 │ │ 赛程战意 │ │指数定价 ││
│ │ (同KL) │ │ (同KL) │ │ (同KL) │ │ (同KL) ││
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬────┘│
│ │ │ │ │ │
│ └────────────┴────────────┴────────────┘ │
│ │ │
│ Optuna优化权重 │
│ (每联赛独立配置) │
│ │ │
│ ▼ │
│ 加权综合得分 │
│ │ │
│ ▼ │
│ Walk-forward Platt校准 │
│ (将原始得分映射为校准概率) │
│ │ │
│ ▼ │
│ 决策引擎 │
│ over_edge > margin → 大球 │
│ under_edge > margin → 小球 │
│ 否则 → 不投 │
└─────────────────────────────────────────────────────┘
核心组件
1. Optuna超参优化
每个联赛独立训练一套最优权重配置。Optuna在历史数据上搜索最佳超参数组合,包括各模块权重、子模块内部权重(比如A模块里射正/关键传球/危险进攻/进球的比例)、采样窗口大小、决策阈值(value_margin)。
目前已覆盖的联赛:中超、韩K联、英超、西甲、德甲、法甲、意甲、巴甲、挪超、瑞典超。
2. Walk-forward Platt校准
用sigmoid函数把模块综合得分校准为概率估计:
$$P(over) = \frac{1}{1 + e^{-(\alpha \cdot score + \beta)}}$$
其中 α(斜率)和 β(截距)通过同联赛同赛季历史赛事的模块得分与实际大小球结果拟合得出。采用Walk-forward方式——只用当前轮次之前的数据拟合参数,防止未来信息泄露。
3. 决策引擎
over_edge = predicted_prob - implied_prob
if over_edge > value_margin:
推荐大球
elif under_edge > value_margin:
推荐小球
else:
不投资
置信度分级:
- edge ≥ 0.10 → 高置信度
- edge ≥ 0.05 → 中高置信度
- edge ≥ 0.02 → 中低置信度
- edge < 0.02 → 低置信度
与第二阶段的关键差异
| 维度 | 第二阶段(KL策略) | 第三阶段(QX策略) |
|---|---|---|
| 决策主体 | 大模型 | 确定性算法 |
| Module C(伤停情报) | 模型联网搜索评分 | 不使用(无模型) |
| 权重来源 | 人工设定 | Optuna历史数据优化 |
| 概率估计 | 模型主观判断 | Platt统计校准 |
| 可回测性 | 有限(依赖模型输出) | 完全可回测 |
| 稳定性 | 受模型版本影响 | 完全确定 |
| 运行成本 | API调用费用 | 几乎为零 |
关于第三阶段的实话
第三阶段不是否定第二阶段。说实话,没有第二阶段那些折腾,根本到不了这里。正是通过KL/AL框架的实践,我们发现了三件事:
- A-F模块的量化得分其实已经包含了大小球预测所需的大部分信息
- 大模型在量化得分基础上做的"综合判断",并没有比统计校准强多少
- 模型的不确定性(温度、版本更新、提示词敏感性)反而在往里加噪声
所以第三阶段做的事情本质上就是:把第二阶段真正有效的部分(A-F量化框架)留下来,把引入噪声的部分(大模型主观判断)扔掉,然后用历史回测系统性地把权重调对。
总结
三个阶段走下来,简单来说是:
| 阶段 | 核心方法 | 关键突破 |
|---|---|---|
| 一 | 纯人工分析 | 建立了分析的基本维度认知 |
| 二 | AI辅助分析(5次迭代) | 从裸调模型 → 结构化数据 → 联赛级洞察 → 多Agent协作 → 量化框架约束模型 |
| 三 | 回测量化分析 | 移除模型,Optuna优化 + Platt校准,全自动可回测决策 |
每一次改动都不是为了追求技术上的花哨,说到底就是在反复回答一个问题:什么信息真正有预测价值?什么信息采取怎样的方法组合在一起能确保单轮胜率>亏损点?
第三阶段并不是终点,我准备使用中超继续跑一段时间,来验证下当前回测量化框架的准确率是否能一直保持?若当失效了,要怎样进行回测调整?