7.7 构造示例④:用赔率构造市场预期与离散度
构造示例前面三个示例都在讲球队。这一篇讲市场——把数据数值变成可计算的量化指标。
一、第一步:数据数值转隐含概率
def implied_prob(odds):
"""数据数值转隐含概率(未去除服务成本)
欧洲数据趋势:概率 = 1 / 数据数值
"""
if not odds or odds <= 1.0:
return None
return 1.0 / odds
示例
| 数据数值 | 隐含概率 |
|---|---|
| 1.50 | 66.7% |
| 2.00 | 50.0% |
| 3.40 | 29.4% |
二、第二步:去除服务成本(必须做)
三项数据数值的隐含概率之和会超过 100%,超出部分就是机构的服务成本。
def fair_probs(home_odds, draw_odds, away_odds):
"""去除服务成本,得到三项的「公平概率」
思路:先算原始隐含概率,再按比例缩放,使总和等于 1
"""
raw = [implied_prob(home_odds), implied_prob(draw_odds), implied_prob(away_odds)]
if any(p is None for p in raw):
return None
s = sum(raw)
if s <= 0:
return None
# 归一化
fair = [p / s for p in raw]
overround = s - 1.0 # 服务成本比例
return {
'home': round(fair[0], 4),
'draw': round(fair, 4),
'away': round(fair, 4),
'overround': round(overround, 4), # 服务成本率,通常 3%~8%
}
# 示例
print(fair_probs(2.10, 3.40, 3.25))
为什么必须去服务成本?
不去服务成本,你的「模型概率」与「市场概率」比较时会有系统性偏差——你会系统性地认为市场高估了所有结果。
这是很多自建模型最常见的错误之一。
三、第三步:跨机构离散度
把多家机构的数据数值收齐,计算分布的离散程度。
import numpy as np
def market_spread(odds_list):
"""计算同一结果在不同机构间的离散度
odds_list: 各机构对同一个结果的数据数值列表
"""
if not odds_list or len(odds_list) 1.0])
if len(arr) < 3:
return None
mean = arr.mean()
std = arr.std()
if mean <= 0:
return None
return {
'mean': round(float(mean), 3),
'std': round(float(std), 4),
'cv': round(float(std / mean), 4), # 变异系数:消除量纲,可跨场次比较
'spread_pct': round(float((arr.max() - arr.min()) / mean), 4),
'n_sources': len(arr),
}
关键指标:变异系数(CV)
不要直接用标准差比较不同场次——数据数值量级不同(1.5 和 5.0 的标准差不可比)。
用变异系数 = 标准差 / 均值,消除了量纲,可以跨场次比较。
| CV 区间 | 解读 |
|---|---|
| < 0.01 | 机构高度一致,市场定价充分 |
| 0.01 ~ 0.03 | 正常范围 |
| 0.03 ~ 0.06 | 存在分歧,值得关注 |
| > 0.06 | 分歧显著,可能存在信息不对称或重大不确定性 |
四、第四步:数据数值随时间的变化
from datetime import datetime
def odds_drift(history):
"""计算数据数值的变动幅度
history: 含 timestamp 与 odds 的记录列表(按时间正序)
"""
if len(history) < 2:
return None
first = history[0]['odds']
last = history[-1]['odds']
if not first or first 0.01 else ('down' if change_pct < -0.01 else 'flat'),
}
变动的解读
| 变动方向 | 含义 |
|---|---|
| 数据数值上升 | 该结果被认为更不可能发生(或市场流量趋势分布对手) |
| 数据数值下降 | 该结果被认为更可能发生(或市场流量涌入) |
| 平稳 | 市场共识稳定 |
五、第五步:预期差计算(最终目标)
def expected_value_gap(model_prob, market_fair_prob):
"""计算模型概率与市场公平概率的差值
正值 = 模型认为市场低估了这个结果
"""
if model_prob is None or market_fair_prob is None:
return None
gap = model_prob - market_fair_prob
return {
'gap': round(float(gap), 4),
'model_prob': round(float(model_prob), 4),
'market_prob': round(float(market_fair_prob), 4),
# 相对偏离:便于跨场次比较
'relative_gap': round(float(gap / market_fair_prob), 4) if market_fair_prob > 0 else None,
}
判断门槛
| 差值 | 参考判断 |
|---|---|
| < 2% | 无实质优势,不构成信号 |
| 2% ~ 5% | 微弱,需要更多验证 |
| > 5% | 值得深入检查是否存在信息遗漏 |
六、一个重要的合规与技术双重要求
不要把数据数值变动解释为「市场流量流」。
公开数据通常不含成交量。看到数据数值变动就说「大量市场流量涌入」,属于无依据推断。
正确的技术表述是「数据数值出现调整,可能反映市场对某类信息的反应」。
这既是技术严谨性要求,也是合规要求(见 6.6)。
七、完整的市场分析流水线
| 步骤 | 产出 |
|---|---|
| ① 收集多机构数据数值 | 原始数据数值列表 |
| ② 去服务成本 | 公平概率 |
| ③ 计算离散度(CV) | 机构分歧程度 |
| ④ 计算数据数值变化 | 市场信息反应 |
| ⑤ 与模型概率对比 | 预期差 |
足球赛事前瞻 | AI 智能分析 | 足球数据解读 - 球小策