1. Введение: фундаментальная поверхность вероятностей в футболе
В количественной торговле на футбол основные рынки (1X2, тоталы голов, азиатские форы, «обе забьют» и точная разница) не являются независимыми статистическими явлениями. Все они производные от одного распределения: совместной поверхности вероятностей точного счета.
Любители часто воспринимают рынки как несвязанные события: ставят «ТБ 2,5» в одной конторе, «победу Арсенала» в другой и «обе забьют» в третьей. Так они платят маржу, накопленную сразу в нескольких производных линиях. Количественные аналитики действуют наоборот: строят единую двумерную сетку вероятностей, матрицу точного счета, и получают справедливые коэффициенты всех связанных рынков, суммируя подмножества ее ячеек.
- Победа хозяев (1):
- Ничья (X):
- Победа гостей (2):
- ТБ 2,5:
- Обе забьют (да):
В этом руководстве показано, как построить матрицу точного счета по пуассоновским ожиданиям голов ( и ). Мы разбираем пороги усечения вероятностной массы, суммы ячеек для каждого производного рынка, поправку Диксона–Коулза для малых счетов, пример матрицы и код на Python.
2. Построение двумерной сетки: матрица вероятностей
Пусть эконометрическая модель задает интенсивности ожидаемых голов для хозяев () и гостей (). В классической модели независимого Пуассона вероятность того, что хозяева забьют ровно голов, а гости ровно , равна произведению маргинальных вероятностей:
Размер матрицы и пороги усечения
У распределения Пуассона бесконечный носитель (), но на практике сетку обрезают на верхней границе . Какой размер выбрать?
Доля вероятности, которую охватывает сетка (счета от до , 49 ячеек), зависит от ожиданий: 99,9% при , 99,1% при , но только 95,2% при . Выбирайте сетку по явному допуску пропущенного хвоста при заданных параметрах. Нормировка усечённой сетки условна на попадание в неё и не восстанавливает отсутствующие счета. Расширьте сетку и укажите остаточный хвост.
3. Производные рынки как разбиения матрицы
Главная практическая сила матрицы точного счета в том, что любой рынок соответствует геометрическому разбиению сетки:
1. Рынок исхода 1X2
49 ячеек счета делятся на три непересекающиеся области относительно главной диагонали:
2. Тоталы голов
Рынки тоталов проверяют, превышает ли суммарный счет дробный порог . Вероятность тотала меньше равна сумме ячеек на антидиагоналях, где :
3. Обе забьют (BTTS)
Исход «Обе забьют: нет» означает, что хотя бы одна команда не забила ( или ). Это объединение первой строки и первого столбца матрицы:
4. Азиатские форы
Для любой азиатской форы вероятность того, что хозяева пройдут фору, равна сумме ячеек, где :
4. Поправка Диксона–Коулза для малых счетов
Диксон и Коулз (1997) показали, что модели независимого Пуассона занижают вероятность ничьих и и завышают счета и . Чтобы исправить это смещение, четыре ячейки малых счетов умножаются на поправочный коэффициент Диксона–Коулза :
Где подбирается по историческим матчам и обычно мал и отрицателен (в коде ниже для примера ). Поправка переносит вероятность со счетов и на ничьи и и немного повышает вероятность ничьей.
5. Пошаговый пример: «Манчестер Сити» против «Ньюкасла»
Рассмотрим гипотетический матч Премьер-лиги с интенсивностями ожидаемых голов («Манчестер Сити» дома) и («Ньюкасл» в гостях).
Центральная сетка (фрагмент)
| Man City \ Newcastle | 0 голов () | 1 гол () | 2 гола () | 3 гола () |
|---|---|---|---|---|
| 0 голов () | 0-0: 4.98% | 0-1: 4.23% | 0-2: 1.80% | 0-3: 0.51% |
| 1 гол () | 1-0: 10.70% | 1-1: 9.10% | 1-2: 3.87% | 1-3: 1.10% |
| 2 гола () | 2-0: 11.51% | 2-1: 9.78% | 2-2: 4.16% | 2-3: 1.18% |
| 3 гола () | 3-0: 8.25% | 3-1: 7.01% | 3-2: 2.98% | 3-3: 0.84% |
Вероятности производных рынков и справедливые коэффициенты
Значения 1X2 суммируют все счета; в этом матче сетка содержит 99,3% вероятностной массы.
- Победа хозяев ():
- Ничья ():
- Победа гостей ():
- ТБ 2,5:
- Обе забьют (да):
6. Реализация на Python: генератор сетки точного счета
Ниже приведен скрипт на Python, который строит полную сетку , применяет поправку Диксона–Коулза и рассчитывает справедливые цены всех производных рынков.
# correct_score_matrix_engine.py
import numpy as np
from scipy.stats import poisson
def generate_correct_score_matrix(lambda_home, mu_away, rho=-0.11, max_goals=6):
# Generates a calibrated 7x7 correct score probability matrix.
grid_size = max_goals + 1
matrix = np.zeros((grid_size, grid_size), dtype=np.float64)
# Compute raw independent Poisson probabilities
for i in range(grid_size):
p_home = poisson.pmf(i, lambda_home)
for j in range(grid_size):
p_away = poisson.pmf(j, mu_away)
matrix[i, j] = p_home * p_away
# Apply Dixon-Coles low-score correction tau
tau_00 = 1.0 - lambda_home * mu_away * rho
tau_01 = 1.0 + lambda_home * rho
tau_10 = 1.0 + mu_away * rho
tau_11 = 1.0 - rho
matrix[0, 0] *= tau_00
matrix[0, 1] *= tau_01
matrix[1, 0] *= tau_10
matrix[1, 1] *= tau_11
# Normalize matrix to 1.0 to absorb truncation error
matrix /= np.sum(matrix)
# Derive Ancillary Markets
p_home_win = np.sum(np.tril(matrix, -1))
p_draw = np.sum(np.diag(matrix))
p_away_win = np.sum(np.triu(matrix, 1))
# Over / Under 2.5
under_25_mask = np.array([[i + j <= 2 for j in range(grid_size)] for i in range(grid_size)])
p_under_25 = np.sum(matrix[under_25_mask])
p_over_25 = 1.0 - p_under_25
# Both Teams To Score (BTTS)
p_btts_yes = np.sum(matrix[1:, 1:])
p_btts_no = 1.0 - p_btts_yes
return {
'matrix': matrix,
'home_win_prob': p_home_win,
'draw_prob': p_draw,
'away_win_prob': p_away_win,
'over_25_prob': p_over_25,
'under_25_prob': p_under_25,
'btts_yes_prob': p_btts_yes,
'fair_1x2_odds': (1.0 / p_home_win, 1.0 / p_draw, 1.0 / p_away_win),
'fair_ou25_odds': (1.0 / p_over_25, 1.0 / p_under_25),
'fair_btts_odds': (1.0 / p_btts_yes, 1.0 / p_btts_no)
}
if __name__ == '__main__':
res = generate_correct_score_matrix(2.15, 0.85)
print("Fair 1X2 Odds:", np.round(res['fair_1x2_odds'], 2))
print("Fair Over/Under 2.5:", np.round(res['fair_ou25_odds'], 2))
print("Fair BTTS Odds:", np.round(res['fair_btts_odds'], 2))
7. Численная устойчивость и нормировка
При расчете совместных пуассоновских матриц точность вычислений с плавающей точкой важна для экстремальных счетов вроде 6-5 или 5-4. Рабочий код накапливает логарифмы вероятностей, , и возвращается к вероятностям через экспоненту, чтобы избежать исчезновения порядка. Деление всей сетки на ее накопленную сумму делает полную вероятность ровно равной 1, поэтому цены 1X2, тоталов, «обе забьют» и фор, полученные из матрицы, согласованы между собой.
