PHP 项目分析必发指数变化方案
必发指数(Betfair Index)来自必发交易所(Betfair Exchange)的成交数据,反映资金的真实流向,PHP 项目分析它需要数据采集 → 存储 → 指标体系 → 变化检测 → 可视化几个环节。

数据来源与采集
数据获取渠道
- 官方 API:Betfair Exchange API(NG API),需申请 App Key,用 JSON-RPC 调用
listMarketCatalogue— 获取赛事/盘口listMarketBook— 获取实时赔率、成交量(核心)
- 第三方聚合站(如部分比分/指数网站),需注意反爬与合规
- 抓取频率建议:赛前每 1~5 分钟一次,临场加密到 10~30 秒
采集实现(PHP)
// 伪代码:定时任务采集
$markets = $betfair->listMarketBook($marketIds);
foreach ($markets as $m) {
foreach ($m['runners'] as $runner) {
DB::table('bf_snapshots')->insert([
'market_id' => $m['marketId'],
'selection_id'=> $runner['selectionId'],
'odds_back' => $runner['ex']['availableToBack'][0]['price'] ?? null,
'odds_lay' => $runner['ex']['availableToLay'][0]['price'] ?? null,
'total_matched' => $runner['totalMatched'],
'volume' => $runner['ex']['tradedVolume'] ?? 0,
'snapshot_at' => now(),
]);
}
}
- 用 Laravel Scheduler / 常驻 Worker(Supervisor + 队列) 调度
- 建议 Redis 缓存最新快照,MySQL/时序库(如 InfluxDB)存历史
数据存储设计
| 表 | 关键字段 | 说明 |
|---|---|---|
bf_markets |
market_id, match_id, start_time | 盘口元信息 |
bf_runners |
selection_id, name, market_id | 选项(主胜/平/客胜等) |
bf_snapshots |
runner_id, odds, volume, matched, ts | 时间序列快照,核心表 |
bf_index |
runner_id, index_value, ts | 计算后的指数 |
快照表要建复合索引 (runner_id, ts) 便于时间区间查询,数据量大时按月分区或转时序库。
核心指标计算
必发指数的本质是成交量加权赔率(资金占比),常用几类指标:
成交量占比(资金流向)
$totalVolume = array_sum(array_column($runners, 'volume'));
foreach ($runners as $r) {
$ratio[$r['selection_id']] = $r['volume'] / $totalVolume * 100;
}
必发指数(加权赔率指数)
指数 = Σ(赔率 × 该赔率成交量) / Σ成交量
反映该选项的真实市场定价。
赔率变化(Delta)
$delta = $currentOdds - $prevOdds; $deltaPct = $delta / $prevOdds * 100;
- 赔率下降 + 成交量激增 = 资金流入,倾向热门
- 可计算
Δodds / Δt得到变化速率
资金背离度
比较必发成交量占比与博彩公司初盘隐含概率的差,识别"冷热"。
大额成交监控
Betfair 返回的 tradedVolume 按赔率档位分布,可统计大额挂单/成交集中的赔率区间。
变化检测逻辑
定时比较快照
// 每轮采集后,对比上一快照
$prev = Redis::get("bf:last:{$runnerId}");
$curr = $snapshot;
if ($curr['odds'] && $prev && abs($curr['odds'] - $prev['odds']) / $prev['odds'] > 0.05) {
// 赔率变化 >5%,触发告警
event(new OddsChanged($runnerId, $prev, $curr));
}
Redis::set("bf:last:{$runnerId}", $curr);
阈值告警规则示例
- 赔率 15 分钟内变动 > 8%
- 某选项成交量占比 30 分钟内跃升 > 10 个百分点
- 成交量突增(相对滚动均值 z-score > 3)
趋势分析
- 取最近 N 个快照拟合线性斜率,判断持续单向流入/流出
- 用移动平均平滑噪声,避免单点抖动误报
架构与工程化建议
采集器(Worker) → Redis(实时缓存) → 计算服务(队列) → 时序DB → 分析/API → 前端图表
- 计算与采集解耦:采集只管入库,计算服务异步消费
- 用队列处理每轮快照的指标计算,避免阻塞
- 保留原始快照,指标可重算,便于回溯
- 前端用 ECharts 画赔率/成交量随时间曲线
合规与注意事项
- 数据授权:Betfair API 有使用条款,商业用途需授权;第三方站点数据注意版权与反爬合规。
- 时区与时间对齐:快照时间统一 UTC,避免跨时区错位。
- 缺数据补全:非交易时段、盘口关闭要有状态标记,避免误判"赔率变化"。
- 噪声过滤:开盘初期和临场封盘前波动大,分析时区分时段。
- 不要在 PHP 里做重计算:大规模回溯分析用 Python/Go,或 SQL 聚合。
最小可用实现路线
- 建快照表 + 定时采集(先手工抓几个盘口验证)
- 写一个
calcIndex($runnerId, $from, $to)方法算成交占比/加权赔率 - 加一个 cron 每 5 分钟跑对比,超阈值写告警表
- 前端简单表格 + 折线图展示变化
如果你能说明数据从哪来(官方 API / 某网站)、PHP 框架(原生/Laravel)、以及要监控的指标(赔率变化 / 资金占比 / 大额成交),我可以给出更贴合的服务类代码和 SQL 设计。