Привет, Хабр! В этой статье я расскажу как я заработал на ставках на спорт, используя Python и базовую математику. Кому интересно, добро пожаловать под кат!
Букмекерская вилка
Есть такой термин в ставках на спорт как букмекерская вилка. Букмекерская вилка — это такая ситуация, когда разница коэффициентов в двух или более конторах позволяет сделать по ставке на каждый взаимоисключающий исход у разных букмекеров и остаться в прибыли при любом результате. Как раз таки поиском этих вилок мы и займёмся .
Как это работает?
Рассмотрим теннисный матч, который проходил 16.07 между Матусевичем А. и Пэрисом Дж. Вот какие коэффициенты предлагала на данный матч контора marathonbet:
А вот какие коэффициенты были в конторе plusminus:
Находится вилка достаточно просто: если выражение 1/K1 +1/K2 меньше 1, то вилка есть, в противном случае, вилки нет, где
K1 — коэффициент на первый исход в первой конторе.
K2 — коэффициент на второй исход во второй конторе.
Рассчитаем для нашего случая. Если мы в конторе marathonbet поставим на Матусевича, а в plusminus на Пэриса, то вилки не будет, так как 1/1.125+ 1/3.92 = 1.1439909297052153. А если мы поставим наоборот, то: 1/5.7 + 1/1.24 = 0.9818902093944539 из этого следует, что вилка есть .
Сколько ставить?
После того, как вилка была найдена, встаёт вопрос: сколько ставить? Воспользуемся простой математической формулой:
summa_min = (K1 x summa_max)/K2, где K1<K2;
summa_max — максимальная сумма, которую вы можете поставить в одной конторе;
summa_min — минимальная сумма, которую придётся поставить в другой конторе.
Рассчитаем для нашего случая. Предположим, что максимальная сумма, которую мы готовы поставить составляет 100$, тогда summa_min = ( 1.24 x100)/5.7; summa_min = 21.75438596491228$. Получается, что на коэффициент 5.7 ставим 21.75438596491228$, а на коэффициент 1.24 ставим 100$, при этом чистый выигрыш составит 2.2456140350877263$. Естественно, 21.75438596491228$ вы не поставите, да и это было бы подозрительно, поэтому желательно округлить до ближайшего целого числа.
Практика
Что ж, теперь, когда основные теоретические аспекты разъяснены, осталось написать код, который будет автоматически находить те самые вилки. Импортируем необходимые библиотеки:
import requests
from bs4 import BeautifulSoup
from difflib import SequenceMatcher
from collections import defaultdict
Получаем html-код исходной страницы:
def get_html(url):
r = requests.get(url)
return r.text
Далее получаем игроков и их коэффициенты всех теннисных матчей в букмекерской конторе marathonbet:
def get_all_event_marathonbet(html):
all_players = []
all_K = []
soup = BeautifulSoup(html, 'lxml')
all_event = soup.find('div',
class_ = "sport-category-content").find_all('div',
class_='bg coupon-row')
for players in all_event:
players = players['data-event-name'].\
replace('- ', '.').split('.')
player_1 = players[1].strip()
player_2 = players[3].strip()
all_players.append(player_1)
all_players.append(player_2)
for g in all_event:
K1 = g.find('td',colspan="1").find('span',
class_="selection-link active-selection").text
K2 = g.find('td', colspan="1").find('span',
class_="selection-link active-selection").\
findNext('span').text
all_K.append(K1)
all_K.append(K2)
return all_players, all_K
Аналогично нужно написать функцию для получения игроков и их коэффициенты в другой букмекерской конторе, код которой вы сможете найти на github. Теперь создадим функцию, которая из списка игроков формирует пары, то есть сами матчи:
def create_arr_couple(arr_players):
arr_couple = []
for i in range(0, len(arr_players), 2):
arr_couple.append(arr_players[i] + ' V '
+ arr_players[i + 1])
return arr_couple
После этого нужно написать функцию, которая формирует словарь вида: {'Матусевич V Пэрис': ['1.24', '3.92']}. Это можно сделать следующим образом:
def create_dict(arr_couple, arr_key):
cat = defaultdict(list)
scet = 0
try:
for i in range(len(arr_couple)):
cat[arr_couple[i]].append(arr_key[scet])
cat[arr_couple[i]].append(arr_key[scet + 1])
scet += 2
return dict(cat)
except IndexError:
print('ERROR!')
Далее осталось написать 4 небольшие функции, которые:
1) находит общие события между двумя конторами:
def similar(a, b):
return SequenceMatcher(None, a, b).ratio()
Данная функция возвращает число от 0 до 1, которое показывает на сколько одна строка похоже на другую, так как бывают такие ситуации, что фамилию одного и того же игрока могут в разных конторах написать по-разному. Например, фамилию Sarmiento в одной конторе транслитерировали как Сармьенто, а в другой как Сармиенто.
2) считает сумму 1/K1 +1/K2 :
def find_vilka(K1, K2):
return 1/float(K1)+1/float(K2)
3) считает, сколько составит чистый выигрыш:
def profit(K, summa_max,summa_min):
print("Выигрыш составит: "+
str((float(K)*summa_max)-summa_min-summa_max))
4) рассчитывает, сколько и на какой коэффициент нужно ставить:
def raschet_vilki(K1,K2,summa_max = 100):
if K1<K2:
summa_min = (float(K1)*summa_max)/float(K2)
print('На коэффициент {}'.format(K1)+
' ставим {} '.format(summa_max))
print('На коэффициент {}'.format(K2) +
' ставим {} '.format(summa_min))
profit(K1, summa_max, summa_min)
else:
summa_min = (float(K2) * summa_max) / float(K1)
print('На коэффициент {}'.format(K1) +
' ставим {} '.format(summa_min))
print('На коэффициент {}'.format(K2) +
' ставим {} '.format(summa_max))
profit(K2, summa_max, summa_min)
Заключение
Таким образом, чуть больше чем за месяц мне удалось заработать 30$ при вложении 120$. Да, это немного, учитывая, что программа была написана для двух букмекерских контор, только для тенниса и я мониторил коэффициенты на матчи 3-5 раз в сутки. В среднем, в день удавалось находить по две вилки. В основном, попадались вилки от 0. 97 и выше, что приносило соответственно лишь пару процентов от поставленного.