This program scrapes odds from online sportsbooks in order to determine if there are arbitrage opportunities to generate a risk-free profit.
$Arbitrage\ \%=(\frac{1}{First Odd})*100 + (\frac{1}{Second Odd})*100$ $\begin{cases} \text{<100%}, & \text{arbitrage exists} \\ \text{>100%}, & \text{arbitrage doesn't exist} \end{cases}$
$Amount\ to\ Bet = \frac{Investment Amount}{1+(\frac{First Odd}{Second Odd})}$
$Profitability\ = \frac{Investment Amount}{Arbitrage \%} - \textrm{Investment Amount}$
from seleniumwire import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import pandas as pd
from bs4 import BeautifulSoup as bs
import requests
username = 'Username'
password = 'Password'
entry = ('http://customer-%s:%s@dc.us-pr.oxylabs.io:30000' %
(username, password))
def proxy() -> dict:
wire_options = {"proxy": {"http": f"{entry}",
"https": f"{entry}",
}}
return wire_options
def barstool():
link = 'https://www.barstoolsportsbook.com/sports/ufc_mma/ufc?category=upcoming&subcategory=All'
caps = DesiredCapabilities().CHROME
caps["pageLoadStrategy"] = "none"
options = webdriver.ChromeOptions()
prefs = {"profile.managed_default_content_settings.images": 0}
options.add_experimental_option("prefs", prefs)
proxies = proxy()
driver = webdriver.Chrome(ChromeDriverManager().install(), options=options,desired_capabilities=caps,seleniumwire_options=proxies)
try:
driver.get(link)
wait=WebDriverWait(driver,120)
wait.until(EC.element_to_be_clickable((By.CLASS_NAME,"main-content")))
soup = bs(driver.page_source, 'html.parser')
data = soup.select('div[class*="main-content"]')
names_odds = []
for i in data:
names_odds.append(i.text)
finally:
driver.quit()
names = []
odds = []
df = pd.DataFrame()
for x in names_odds:
x = x.split()
name = x[1] + ' ' + x[0]
if name.__contains__(','):
name = name.replace(',','')
names.append(name)
odds.append(x[2])
df['Names'] = names
df['Barstool'] = odds
return df
def bet_mgm():
link = 'https://sports.va.betmgm.com/en/sports/mma-45/betting/usa-9/ufc-fight-night-77338'
caps = DesiredCapabilities().CHROME
caps["pageLoadStrategy"] = "none"
options = webdriver.ChromeOptions()
prefs = {"profile.managed_default_content_settings.images": 0}
options.add_experimental_option("prefs", prefs)
proxies = proxy()
driver = webdriver.Chrome(ChromeDriverManager().install(), options=options,desired_capabilities=caps,seleniumwire_options=proxies)
try:
driver.get(link)
wait=WebDriverWait(driver,120)
wait.until(EC.element_to_be_clickable((By.CLASS_NAME,"participant")))
soup = bs(driver.page_source, 'html.parser')
participant = soup.select('div[class*="participants-pair-game"]')
odd = soup.select('div[class*="option-indicator"]')
names = []
odds = []
for i in participant:
names.append(i.text)
for x in odd:
odds.append(x.text)
finally:
driver.quit()
odds = odds[4:]
matches = []
for match in names:
match = match.split()
#print (match)
if len(match) == 4:
name1 = match[0]+' '+match[1][:-3]
name2 = match[2]+' '+match[3][:-3]
elif len(match) != 4 and match[2][-1].isupper() == True:
name1 = match[0]+' '+match[1]+' '+match[2][:-3]
name2 = match[3]+' '+match[4][:-3]
elif len(match) != 4 and match[1][-1].isupper() == True:
name1 = match[0]+' '+match[1][:-3]
name2 = match[2]+' '+match[3]+' '+match[4][:-3]
matches.append(name1)
matches.append(name2)
df = pd.DataFrame()
df['Names'] = matches
df['BetMGM'] = odds
return df
def draft_kings():
session = requests.Session()
session.proxies = {"http": "http://customer-u1-cc-us-st-us_new_york-city-brooklyn:12345678Jo@pr.oxylabs.io:7777",
}
URL = 'https://sportsbook.draftkings.com/leagues/mma/ufc'
response = session.get(URL)
data = pd.read_html(response.text)
all_data = []
for date in data:
df = pd.DataFrame(date)
names = []
times = []
for x in df.iloc[:,0]:
if x.__contains__('AM'):
x = x.split('AM')
elif x.__contains__('PM'):
x = x.split('PM')
times.append(x[0])
names.append(x[1])
df.iloc[:,0] = names
df = df.rename(columns={df.columns[0]:'Names','Moneyline':'DraftKings'})
all_data.append(df)
all_data = pd.concat(all_data)
all_data = all_data.drop(columns={'Unnamed: 1', 'O/U Rounds', 'Unnamed: 2','Point Spread'})
df = pd.DataFrame(all_data).reset_index().drop(columns={'index'})
return df
def convert(list):
conversion = []
for odd in list:
if odd.__contains__('+'):
odd = odd.split('+')
dec = (int(odd[1])/100)+1
odd[1] = round(dec,2)
conversion.append(odd[1])
elif odd.__contains__('-'):
odd = odd.split('-')
dec = (100/int(odd[1]))+1
odd[1] = round(dec,2)
conversion.append(odd[1])
else:
odd = odd.split('−')
dec = (100/int(odd[1]))+1
odd[1] = round(dec,2)
conversion.append(odd[1])
return conversion
def test(frame1,frame2):
frame1_test = frame1.copy()
frame2_test = frame2.copy()
frame1_groups = frame1_test.groupby(frame1_test.index // 2)
frame2_groups = frame2_test.groupby(frame2_test.index // 2)
for name,group in frame1_groups:
for frame1_name in group['Names']:
frame1_name = frame1_name.split(' ')
if len(frame1_name) > 2:
frame1_test = frame1_test.drop(frame1_groups.get_group(name).index)
for name,group in frame2_groups:
for frame2_name in group['Names']:
frame2_name = frame2_name.split(' ')
if len(frame2_name) > 2:
frame2_test = frame2_test.drop(frame2_groups.get_group(name).index)
frame2_test = frame2_test.reset_index().drop(columns={'index'})
frame1_test = frame1_test.reset_index().drop(columns={'index'})
frame1_groups = frame1_test.groupby(frame1_test.index // 2)
frame2_groups = frame2_test.groupby(frame2_test.index // 2)
results_df = pd.DataFrame(columns=['Names',f'{frame2_test.columns[1]}',f'{frame1_test.columns[1]}'])
for name,group in frame2_groups:
for name2,group2 in frame1_groups:
if group['Names'].iloc[0] == group2['Names'].iloc[0] or group['Names'].iloc[0] == group2['Names'].iloc[1]:
group = group.sort_values(by='Names',ascending=True)
group2 = group2.sort_values(by='Names',ascending=True)
group[f'{group2.columns[1]}'] = [x for x in group2[f'{group2.columns[1]}']]
results_df.loc[len(results_df)] = group.iloc[0]
results_df.loc[len(results_df)] = group.iloc[1]
break
results_df[f'{results_df.columns[1]} dec'] = convert(results_df[f'{results_df.columns[1]}'])
results_df[f'{results_df.columns[2]} dec'] = convert(results_df[f'{results_df.columns[2]}'])
test_groups = results_df.groupby(results_df.index // 2)
arbs = []
for name,group in test_groups:
t1 = group[group.columns[3]].iloc[0]
t2 = (group[group.columns[4]].iloc[1])
arb = (1/(t1))+(1/t2)
arbs.append(arb)
arbs.append(arb)
results_df['Spread'] = arbs
results_df = results_df.sort_values(by='Spread',ascending=True)
return results_df
#draftkings_sportsbook = draft_kings()
barstool_sportsbook = barstool()
betmgm_sportsbook = bet_mgm()
final = test(barstool_sportsbook,betmgm_sportsbook)
print (final)