Spaces:
Running
Running
James McCool
commited on
Commit
·
37bad99
1
Parent(s):
dbdb1e2
Refactor app.py: Remove Google Sheets integration, simplify connection initialization, and optimize caching. Adjusted data frame initialization and improved contest simulation logic. Updated cache timeouts and enhanced player ID handling for DraftKings and FanDuel. Cleaned up unused variables and streamlined data export functionality.
Browse files
app.py
CHANGED
@@ -2,59 +2,26 @@ import streamlit as st
|
|
2 |
st.set_page_config(layout="wide")
|
3 |
import numpy as np
|
4 |
import pandas as pd
|
5 |
-
import gspread
|
6 |
import pymongo
|
7 |
import time
|
8 |
|
9 |
@st.cache_resource
|
10 |
def init_conn():
|
11 |
-
scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
|
12 |
-
|
13 |
-
credentials = {
|
14 |
-
"type": "service_account",
|
15 |
-
"project_id": "model-sheets-connect",
|
16 |
-
"private_key_id": st.secrets['model_sheets_connect_pk'],
|
17 |
-
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDiu1v/e6KBKOcK\ncx0KQ23nZK3ZVvADYy8u/RUn/EDI82QKxTd/DizRLIV81JiNQxDJXSzgkbwKYEDm\n48E8zGvupU8+Nk76xNPakrQKy2Y8+VJlq5psBtGchJTuUSHcXU5Mg2JhQsB376PJ\nsCw552K6Pw8fpeMDJDZuxpKSkaJR6k9G5Dhf5q8HDXnC5Rh/PRFuKJ2GGRpX7n+2\nhT/sCax0J8jfdTy/MDGiDfJqfQrOPrMKELtsGHR9Iv6F4vKiDqXpKfqH+02E9ptz\nBk+MNcbZ3m90M8ShfRu28ebebsASfarNMzc3dk7tb3utHOGXKCf4tF8yYKo7x8BZ\noO9X4gSfAgMBAAECggEAU8ByyMpSKlTCF32TJhXnVJi/kS+IhC/Qn5JUDMuk4LXr\naAEWsWO6kV/ZRVXArjmuSzuUVrXumISapM9Ps5Ytbl95CJmGDiLDwRL815nvv6k3\nUyAS8EGKjz74RpoIoH6E7EWCAzxlnUgTn+5oP9Flije97epYk3H+e2f1f5e1Nn1d\nYNe8U+1HqJgILcxA1TAUsARBfoD7+K3z/8DVPHI8IpzAh6kTHqhqC23Rram4XoQ6\nzj/ZdVBjvnKuazETfsD+Vl3jGLQA8cKQVV70xdz3xwLcNeHsbPbpGBpZUoF73c65\nkAXOrjYl0JD5yAk+hmYhXr6H9c6z5AieuZGDrhmlFQKBgQDzV6LRXmjn4854DP/J\nI82oX2GcI4eioDZPRukhiQLzYerMQBmyqZIRC+/LTCAhYQSjNgMa+ZKyvLqv48M0\n/x398op/+n3xTs+8L49SPI48/iV+mnH7k0WI/ycd4OOKh8rrmhl/0EWb9iitwJYe\nMjTV/QxNEpPBEXfR1/mvrN/lVQKBgQDuhomOxUhWVRVH6x03slmyRBn0Oiw4MW+r\nrt1hlNgtVmTc5Mu+4G0USMZwYuOB7F8xG4Foc7rIlwS7Ic83jMJxemtqAelwOLdV\nXRLrLWJfX8+O1z/UE15l2q3SUEnQ4esPHbQnZowHLm0mdL14qSVMl1mu1XfsoZ3z\nJZTQb48CIwKBgEWbzQRtKD8lKDupJEYqSrseRbK/ax43DDITS77/DWwHl33D3FYC\nMblUm8ygwxQpR4VUfwDpYXBlklWcJovzamXpSnsfcYVkkQH47NuOXPXPkXQsw+w+\nDYcJzeu7F/vZqk9I7oBkWHUrrik9zPNoUzrfPvSRGtkAoTDSwibhoc5dAoGBAMHE\nK0T/ANeZQLNuzQps6S7G4eqjwz5W8qeeYxsdZkvWThOgDd/ewt3ijMnJm5X05hOn\ni4XF1euTuvUl7wbqYx76Wv3/1ZojiNNgy7ie4rYlyB/6vlBS97F4ZxJdxMlabbCW\n6b3EMWa4EVVXKoA1sCY7IVDE+yoQ1JYsZmq45YzPAoGBANWWHuVueFGZRDZlkNlK\nh5OmySmA0NdNug3G1upaTthyaTZ+CxGliwBqMHAwpkIRPwxUJpUwBTSEGztGTAxs\nWsUOVWlD2/1JaKSmHE8JbNg6sxLilcG6WEDzxjC5dLL1OrGOXj9WhC9KX3sq6qb6\nF/j9eUXfXjAlb042MphoF3ZC\n-----END PRIVATE KEY-----\n",
|
18 |
-
"client_email": "[email protected]",
|
19 |
-
"client_id": "100369174533302798535",
|
20 |
-
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
21 |
-
"token_uri": "https://oauth2.googleapis.com/token",
|
22 |
-
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
23 |
-
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gspread-connection%40model-sheets-connect.iam.gserviceaccount.com"
|
24 |
-
}
|
25 |
-
|
26 |
-
credentials2 = {
|
27 |
-
"type": "service_account",
|
28 |
-
"project_id": "sheets-api-connect-378620",
|
29 |
-
"private_key_id": st.secrets['sheets_api_connect_pk'],
|
30 |
-
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCtKa01beXwc88R\nnPZVQTNPVQuBnbwoOfc66gW3547ja/UEyIGAF112dt/VqHprRafkKGmlg55jqJNt\na4zceLKV+wTm7vBu7lDISTJfGzCf2TrxQYNqwMKE2LOjI69dBM8u4Dcb4k0wcp9v\ntW1ZzLVVuwTvmrg7JBHjiSaB+x5wxm/r3FOiJDXdlAgFlytzqgcyeZMJVKKBQHyJ\njEGg/1720A0numuOCt71w/2G0bDmijuj1e6tH32MwRWcvRNZ19K9ssyDz2S9p68s\nYDhIxX69OWxwScTIHLY6J2t8txf/XMivL/636fPlDADvBEVTdlT606n8CcKUVQeq\npUVdG+lfAgMBAAECggEAP38SUA7B69eTfRpo658ycOs3Amr0JW4H/bb1rNeAul0K\nZhwd/HnU4E07y81xQmey5kN5ZeNrD5EvqkZvSyMJHV0EEahZStwhjCfnDB/cxyix\nZ+kFhv4y9eK+kFpUAhBy5nX6T0O+2T6WvzAwbmbVsZ+X8kJyPuF9m8ldcPlD0sce\ntj8NwVq1ys52eosqs7zi2vjt+eMcaY393l4ls+vNq8Yf27cfyFw45W45CH/97/Nu\n5AmuzlCOAfFF+z4OC5g4rei4E/Qgpxa7/uom+BVfv9G0DIGW/tU6Sne0+37uoGKt\nW6DzhgtebUtoYkG7ZJ05BTXGp2lwgVcNRoPwnKJDxQKBgQDT5wYPUBDW+FHbvZSp\nd1m1UQuXyerqOTA9smFaM8sr/UraeH85DJPEIEk8qsntMBVMhvD3Pw8uIUeFNMYj\naLmZFObsL+WctepXrVo5NB6RtLB/jZYxiKMatMLUJIYtcKIp+2z/YtKiWcLnwotB\nWdCjVnPTxpkurmF2fWP/eewZ+wKBgQDRMtJg7etjvKyjYNQ5fARnCc+XsI3gkBe1\nX9oeXfhyfZFeBXWnZzN1ITgFHplDznmBdxAyYGiQdbbkdKQSghviUQ0igBvoDMYy\n1rWcy+a17Mj98uyNEfmb3X2cC6WpvOZaGHwg9+GY67BThwI3FqHIbyk6Ko09WlTX\nQpRQjMzU7QKBgAfi1iflu+q0LR+3a3vvFCiaToskmZiD7latd9AKk2ocsBd3Woy9\n+hXXecJHPOKV4oUJlJgvAZqe5HGBqEoTEK0wyPNLSQlO/9ypd+0fEnArwFHO7CMF\nycQprAKHJXM1eOOFFuZeQCaInqdPZy1UcV5Szla4UmUZWkk1m24blHzXAoGBAMcA\nyH4qdbxX9AYrC1dvsSRvgcnzytMvX05LU0uF6tzGtG0zVlub4ahvpEHCfNuy44UT\nxRWW/oFFaWjjyFxO5sWggpUqNuHEnRopg3QXx22SRRTGbN45li/+QAocTkgsiRh1\nqEcYZsO4mPCsQqAy6E2p6RcK+Xa+omxvSnVhq0x1AoGAKr8GdkCl4CF6rieLMAQ7\nLNBuuoYGaHoh8l5E2uOQpzwxVy/nMBcAv+2+KqHEzHryUv1owOi6pMLv7A9mTFoS\n18B0QRLuz5fSOsVnmldfC9fpUc6H8cH1SINZpzajqQA74bPwELJjnzrCnH79TnHG\nJuElxA33rFEjbgbzdyrE768=\n-----END PRIVATE KEY-----\n",
|
31 |
-
"client_email": "gspread-connection@sheets-api-connect-378620.iam.gserviceaccount.com",
|
32 |
-
"client_id": "106625872877651920064",
|
33 |
-
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
34 |
-
"token_uri": "https://oauth2.googleapis.com/token",
|
35 |
-
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
36 |
-
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gspread-connection%40sheets-api-connect-378620.iam.gserviceaccount.com"
|
37 |
-
}
|
38 |
|
39 |
uri = st.secrets['mongo_uri']
|
40 |
client = pymongo.MongoClient(uri, retryWrites=True, serverSelectionTimeoutMS=500000)
|
41 |
db = client["NBA_DFS"]
|
42 |
-
|
43 |
-
NBA_Data = st.secrets['NBA_Data']
|
44 |
-
|
45 |
-
gc = gspread.service_account_from_dict(credentials)
|
46 |
-
gc2 = gspread.service_account_from_dict(credentials2)
|
47 |
|
48 |
-
return
|
49 |
|
50 |
-
|
51 |
|
52 |
percentages_format = {'Exposure': '{:.2%}'}
|
53 |
freq_format = {'Proj Own': '{:.2%}', 'Exposure': '{:.2%}', 'Edge': '{:.2%}'}
|
54 |
dk_columns = ['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
|
55 |
fd_columns = ['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C1', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
|
56 |
|
57 |
-
@st.cache_data(ttl =
|
58 |
def init_DK_seed_frames():
|
59 |
|
60 |
collection = db["DK_NBA_seed_frame"]
|
@@ -66,7 +33,7 @@ def init_DK_seed_frames():
|
|
66 |
|
67 |
return DK_seed
|
68 |
|
69 |
-
@st.cache_data(ttl =
|
70 |
def init_DK_secondary_seed_frames():
|
71 |
|
72 |
collection = db["DK_NBA_Secondary_seed_frame"]
|
@@ -78,7 +45,7 @@ def init_DK_secondary_seed_frames():
|
|
78 |
|
79 |
return DK_secondary
|
80 |
|
81 |
-
@st.cache_data(ttl =
|
82 |
def init_FD_seed_frames():
|
83 |
|
84 |
collection = db["FD_NBA_seed_frame"]
|
@@ -90,7 +57,7 @@ def init_FD_seed_frames():
|
|
90 |
|
91 |
return FD_seed
|
92 |
|
93 |
-
@st.cache_data(ttl =
|
94 |
def init_FD_secondary_seed_frames():
|
95 |
|
96 |
collection = db["FD_NBA_Secondary_seed_frame"]
|
@@ -102,13 +69,15 @@ def init_FD_secondary_seed_frames():
|
|
102 |
|
103 |
return FD_secondary
|
104 |
|
105 |
-
@st.cache_resource(ttl =
|
106 |
def init_baselines():
|
107 |
-
|
108 |
-
|
109 |
-
|
|
|
|
|
110 |
load_display.replace('', np.nan, inplace=True)
|
111 |
-
load_display.rename(columns={"Fantasy": "Median", 'Name': 'Player'}, inplace = True)
|
112 |
load_display = load_display[load_display['Median'] > 0]
|
113 |
|
114 |
dk_roo_raw = load_display[load_display['site'] == 'Draftkings']
|
@@ -153,10 +122,9 @@ def calculate_FD_value_frequencies(np_array):
|
|
153 |
return combined_array
|
154 |
|
155 |
@st.cache_data
|
156 |
-
def sim_contest(Sim_size, seed_frame, maps_dict,
|
157 |
SimVar = 1
|
158 |
Sim_Winners = []
|
159 |
-
fp_array = seed_frame[:sharp_split, :]
|
160 |
|
161 |
# Pre-vectorize functions
|
162 |
vec_projection_map = np.vectorize(maps_dict['Projection_map'].__getitem__)
|
@@ -165,7 +133,7 @@ def sim_contest(Sim_size, seed_frame, maps_dict, sharp_split, Contest_Size):
|
|
165 |
st.write('Simulating contest on frames')
|
166 |
|
167 |
while SimVar <= Sim_size:
|
168 |
-
fp_random =
|
169 |
|
170 |
sample_arrays1 = np.c_[
|
171 |
fp_random,
|
@@ -187,6 +155,8 @@ def sim_contest(Sim_size, seed_frame, maps_dict, sharp_split, Contest_Size):
|
|
187 |
return Sim_Winners
|
188 |
|
189 |
dk_raw, fd_raw, dk_secondary, fd_secondary = init_baselines()
|
|
|
|
|
190 |
|
191 |
tab1, tab2 = st.tabs(['Contest Sims', 'Data Export'])
|
192 |
|
@@ -197,25 +167,20 @@ with tab2:
|
|
197 |
st.cache_data.clear()
|
198 |
for key in st.session_state.keys():
|
199 |
del st.session_state[key]
|
200 |
-
DK_seed = init_DK_seed_frames()
|
201 |
-
FD_seed = init_FD_seed_frames()
|
202 |
-
DK_secondary = init_DK_secondary_seed_frames()
|
203 |
-
FD_secondary = init_FD_secondary_seed_frames()
|
204 |
dk_raw, fd_raw, dk_secondary, fd_secondary = init_baselines()
|
|
|
|
|
205 |
|
206 |
slate_var1 = st.radio("Which data are you loading?", ('Main Slate', 'Secondary Slate'), key='slate_var1')
|
207 |
site_var1 = st.radio("What site are you working with?", ('Draftkings', 'Fanduel'), key='site_var1')
|
|
|
208 |
lineup_num_var = st.number_input("How many lineups do you want to display?", min_value=1, max_value=500, value=10, step=1)
|
209 |
|
210 |
if site_var1 == 'Draftkings':
|
211 |
-
if slate_var1 == 'Main Slate':
|
212 |
-
DK_seed = init_DK_seed_frames()
|
213 |
-
raw_baselines = dk_raw
|
214 |
-
column_names = dk_columns
|
215 |
-
elif slate_var1 == 'Secondary Slate':
|
216 |
-
DK_seed = init_DK_secondary_seed_frames()
|
217 |
-
raw_baselines = dk_secondary
|
218 |
-
column_names = dk_columns
|
219 |
|
220 |
player_var1 = st.radio("Do you want a frame with specific Players?", ('Full Slate', 'Specific Players'), key='player_var1')
|
221 |
if player_var1 == 'Specific Players':
|
@@ -223,24 +188,70 @@ with tab2:
|
|
223 |
elif player_var1 == 'Full Slate':
|
224 |
player_var2 = dk_raw.Player.values.tolist()
|
225 |
|
|
|
|
|
|
|
226 |
elif site_var1 == 'Fanduel':
|
227 |
-
if slate_var1 == 'Main Slate':
|
228 |
-
FD_seed = init_FD_seed_frames()
|
229 |
-
raw_baselines = fd_raw
|
230 |
-
column_names = fd_columns
|
231 |
-
elif slate_var1 == 'Secondary Slate':
|
232 |
-
FD_seed = init_FD_secondary_seed_frames()
|
233 |
-
raw_baselines = fd_secondary
|
234 |
-
column_names = fd_columns
|
235 |
|
236 |
player_var1 = st.radio("Do you want a frame with specific Players?", ('Full Slate', 'Specific Players'), key='player_var1')
|
237 |
if player_var1 == 'Specific Players':
|
238 |
player_var2 = st.multiselect('Which players do you want?', options = fd_raw['Player'].unique())
|
239 |
elif player_var1 == 'Full Slate':
|
240 |
player_var2 = fd_raw.Player.values.tolist()
|
|
|
|
|
|
|
241 |
|
242 |
if st.button("Prepare data export", key='data_export'):
|
243 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
244 |
st.download_button(
|
245 |
label="Export optimals set",
|
246 |
data=convert_df(data_export),
|
@@ -255,16 +266,20 @@ with tab2:
|
|
255 |
st.session_state.working_seed = st.session_state.working_seed
|
256 |
if player_var1 == 'Specific Players':
|
257 |
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
|
258 |
-
elif player_var1 == 'Full Slate':
|
259 |
-
st.session_state.working_seed = DK_seed.copy()
|
260 |
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
|
261 |
elif 'working_seed' not in st.session_state:
|
262 |
-
|
263 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
264 |
if player_var1 == 'Specific Players':
|
265 |
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
|
266 |
-
elif player_var1 == 'Full Slate':
|
267 |
-
st.session_state.working_seed = DK_seed.copy()
|
268 |
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
|
269 |
|
270 |
elif site_var1 == 'Fanduel':
|
@@ -272,26 +287,22 @@ with tab2:
|
|
272 |
st.session_state.working_seed = st.session_state.working_seed
|
273 |
if player_var1 == 'Specific Players':
|
274 |
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
|
275 |
-
elif player_var1 == 'Full Slate':
|
276 |
-
st.session_state.working_seed = FD_seed.copy()
|
277 |
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
|
278 |
elif 'working_seed' not in st.session_state:
|
279 |
-
|
280 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
281 |
if player_var1 == 'Specific Players':
|
282 |
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
|
283 |
-
elif player_var1 == 'Full Slate':
|
284 |
-
st.session_state.working_seed = FD_seed.copy()
|
285 |
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
|
286 |
|
287 |
-
with st.container():
|
288 |
-
if st.button("Reset Optimals", key='reset3'):
|
289 |
-
for key in st.session_state.keys():
|
290 |
-
del st.session_state[key]
|
291 |
-
if site_var1 == 'Draftkings':
|
292 |
-
st.session_state.working_seed = DK_seed.copy()
|
293 |
-
elif site_var1 == 'Fanduel':
|
294 |
-
st.session_state.working_seed = FD_seed.copy()
|
295 |
if 'data_export_display' in st.session_state:
|
296 |
st.dataframe(st.session_state.data_export_display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), height=500, use_container_width = True)
|
297 |
|
@@ -302,31 +313,16 @@ with tab1:
|
|
302 |
st.cache_data.clear()
|
303 |
for key in st.session_state.keys():
|
304 |
del st.session_state[key]
|
305 |
-
DK_seed = init_DK_seed_frames()
|
306 |
-
FD_seed = init_FD_seed_frames()
|
307 |
-
DK_secondary = init_DK_secondary_seed_frames()
|
308 |
-
FD_secondary = init_FD_secondary_seed_frames()
|
309 |
dk_raw, fd_raw, dk_secondary, fd_secondary = init_baselines()
|
|
|
|
|
|
|
310 |
sim_slate_var1 = st.radio("Which data are you loading?", ('Main Slate', 'Secondary Slate'), key='sim_slate_var1')
|
311 |
sim_site_var1 = st.radio("What site are you working with?", ('Draftkings', 'Fanduel'), key='sim_site_var1')
|
312 |
-
if sim_site_var1 == 'Draftkings':
|
313 |
-
if sim_slate_var1 == 'Main Slate':
|
314 |
-
DK_seed = init_DK_seed_frames()
|
315 |
-
raw_baselines = dk_raw
|
316 |
-
column_names = dk_columns
|
317 |
-
elif sim_slate_var1 == 'Secondary Slate':
|
318 |
-
DK_seed = init_DK_secondary_seed_frames()
|
319 |
-
raw_baselines = dk_secondary
|
320 |
-
column_names = dk_columns
|
321 |
-
elif sim_site_var1 == 'Fanduel':
|
322 |
-
if sim_slate_var1 == 'Main Slate':
|
323 |
-
FD_seed = init_FD_seed_frames()
|
324 |
-
raw_baselines = fd_raw
|
325 |
-
column_names = fd_columns
|
326 |
-
elif sim_slate_var1 == 'Secondary Slate':
|
327 |
-
FD_seed = init_FD_secondary_seed_frames()
|
328 |
-
raw_baselines = fd_secondary
|
329 |
-
column_names = fd_columns
|
330 |
|
331 |
contest_var1 = st.selectbox("What contest size are you simulating?", ('Small', 'Medium', 'Large', 'Custom'))
|
332 |
if contest_var1 == 'Small':
|
@@ -336,7 +332,7 @@ with tab1:
|
|
336 |
elif contest_var1 == 'Large':
|
337 |
Contest_Size = 10000
|
338 |
elif contest_var1 == 'Custom':
|
339 |
-
Contest_Size = st.number_input("Insert contest size", value=100,
|
340 |
strength_var1 = st.selectbox("How sharp is the field in the contest?", ('Very', 'Above Average', 'Average', 'Below Average', 'Not Very'))
|
341 |
if strength_var1 == 'Not Very':
|
342 |
sharp_split = 500000
|
@@ -361,7 +357,7 @@ with tab1:
|
|
361 |
'Team_map':dict(zip(raw_baselines.Player,raw_baselines.Team)),
|
362 |
'STDev_map':dict(zip(raw_baselines.Player,raw_baselines.STDev))
|
363 |
}
|
364 |
-
Sim_Winners = sim_contest(1000, st.session_state.working_seed, st.session_state.maps_dict,
|
365 |
Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners))
|
366 |
|
367 |
# Initial setup
|
@@ -386,9 +382,25 @@ with tab1:
|
|
386 |
|
387 |
else:
|
388 |
if sim_site_var1 == 'Draftkings':
|
389 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
390 |
elif sim_site_var1 == 'Fanduel':
|
391 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
392 |
st.session_state.maps_dict = {
|
393 |
'Projection_map':dict(zip(raw_baselines.Player,raw_baselines.Median)),
|
394 |
'Salary_map':dict(zip(raw_baselines.Player,raw_baselines.Salary)),
|
@@ -397,7 +409,7 @@ with tab1:
|
|
397 |
'Team_map':dict(zip(raw_baselines.Player,raw_baselines.Team)),
|
398 |
'STDev_map':dict(zip(raw_baselines.Player,raw_baselines.STDev))
|
399 |
}
|
400 |
-
Sim_Winners = sim_contest(1000, st.session_state.working_seed, st.session_state.maps_dict,
|
401 |
Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners))
|
402 |
|
403 |
# Initial setup
|
|
|
2 |
st.set_page_config(layout="wide")
|
3 |
import numpy as np
|
4 |
import pandas as pd
|
|
|
5 |
import pymongo
|
6 |
import time
|
7 |
|
8 |
@st.cache_resource
|
9 |
def init_conn():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
uri = st.secrets['mongo_uri']
|
12 |
client = pymongo.MongoClient(uri, retryWrites=True, serverSelectionTimeoutMS=500000)
|
13 |
db = client["NBA_DFS"]
|
|
|
|
|
|
|
|
|
|
|
14 |
|
15 |
+
return db
|
16 |
|
17 |
+
db = init_conn()
|
18 |
|
19 |
percentages_format = {'Exposure': '{:.2%}'}
|
20 |
freq_format = {'Proj Own': '{:.2%}', 'Exposure': '{:.2%}', 'Edge': '{:.2%}'}
|
21 |
dk_columns = ['PG', 'SG', 'SF', 'PF', 'C', 'G', 'F', 'FLEX', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
|
22 |
fd_columns = ['PG1', 'PG2', 'SG1', 'SG2', 'SF1', 'SF2', 'PF1', 'PF2', 'C1', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
|
23 |
|
24 |
+
@st.cache_data(ttl = 60)
|
25 |
def init_DK_seed_frames():
|
26 |
|
27 |
collection = db["DK_NBA_seed_frame"]
|
|
|
33 |
|
34 |
return DK_seed
|
35 |
|
36 |
+
@st.cache_data(ttl = 60)
|
37 |
def init_DK_secondary_seed_frames():
|
38 |
|
39 |
collection = db["DK_NBA_Secondary_seed_frame"]
|
|
|
45 |
|
46 |
return DK_secondary
|
47 |
|
48 |
+
@st.cache_data(ttl = 60)
|
49 |
def init_FD_seed_frames():
|
50 |
|
51 |
collection = db["FD_NBA_seed_frame"]
|
|
|
57 |
|
58 |
return FD_seed
|
59 |
|
60 |
+
@st.cache_data(ttl = 60)
|
61 |
def init_FD_secondary_seed_frames():
|
62 |
|
63 |
collection = db["FD_NBA_Secondary_seed_frame"]
|
|
|
69 |
|
70 |
return FD_secondary
|
71 |
|
72 |
+
@st.cache_resource(ttl = 60)
|
73 |
def init_baselines():
|
74 |
+
collection = db["Player_Range_Of_Outcomes"]
|
75 |
+
cursor = collection.find()
|
76 |
+
|
77 |
+
load_display = pd.DataFrame(list(cursor))
|
78 |
+
|
79 |
load_display.replace('', np.nan, inplace=True)
|
80 |
+
load_display.rename(columns={"Fantasy": "Median", 'Name': 'Player', 'player_ID': 'player_id'}, inplace = True)
|
81 |
load_display = load_display[load_display['Median'] > 0]
|
82 |
|
83 |
dk_roo_raw = load_display[load_display['site'] == 'Draftkings']
|
|
|
122 |
return combined_array
|
123 |
|
124 |
@st.cache_data
|
125 |
+
def sim_contest(Sim_size, seed_frame, maps_dict, Contest_Size):
|
126 |
SimVar = 1
|
127 |
Sim_Winners = []
|
|
|
128 |
|
129 |
# Pre-vectorize functions
|
130 |
vec_projection_map = np.vectorize(maps_dict['Projection_map'].__getitem__)
|
|
|
133 |
st.write('Simulating contest on frames')
|
134 |
|
135 |
while SimVar <= Sim_size:
|
136 |
+
fp_random = seed_frame[np.random.choice(seed_frame.shape[0], Contest_Size)]
|
137 |
|
138 |
sample_arrays1 = np.c_[
|
139 |
fp_random,
|
|
|
155 |
return Sim_Winners
|
156 |
|
157 |
dk_raw, fd_raw, dk_secondary, fd_secondary = init_baselines()
|
158 |
+
dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_id))
|
159 |
+
fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_id))
|
160 |
|
161 |
tab1, tab2 = st.tabs(['Contest Sims', 'Data Export'])
|
162 |
|
|
|
167 |
st.cache_data.clear()
|
168 |
for key in st.session_state.keys():
|
169 |
del st.session_state[key]
|
170 |
+
DK_seed = init_DK_seed_frames(10000)
|
171 |
+
FD_seed = init_FD_seed_frames(10000)
|
172 |
+
DK_secondary = init_DK_secondary_seed_frames(10000)
|
173 |
+
FD_secondary = init_FD_secondary_seed_frames(10000)
|
174 |
dk_raw, fd_raw, dk_secondary, fd_secondary = init_baselines()
|
175 |
+
dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_id))
|
176 |
+
fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_id))
|
177 |
|
178 |
slate_var1 = st.radio("Which data are you loading?", ('Main Slate', 'Secondary Slate'), key='slate_var1')
|
179 |
site_var1 = st.radio("What site are you working with?", ('Draftkings', 'Fanduel'), key='site_var1')
|
180 |
+
sharp_split_var = st.number_input("How many lineups do you want?", value=10000, max_value=500000, min_value=10000, step=10000)
|
181 |
lineup_num_var = st.number_input("How many lineups do you want to display?", min_value=1, max_value=500, value=10, step=1)
|
182 |
|
183 |
if site_var1 == 'Draftkings':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
184 |
|
185 |
player_var1 = st.radio("Do you want a frame with specific Players?", ('Full Slate', 'Specific Players'), key='player_var1')
|
186 |
if player_var1 == 'Specific Players':
|
|
|
188 |
elif player_var1 == 'Full Slate':
|
189 |
player_var2 = dk_raw.Player.values.tolist()
|
190 |
|
191 |
+
raw_baselines = dk_raw
|
192 |
+
column_names = dk_columns
|
193 |
+
|
194 |
elif site_var1 == 'Fanduel':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
|
196 |
player_var1 = st.radio("Do you want a frame with specific Players?", ('Full Slate', 'Specific Players'), key='player_var1')
|
197 |
if player_var1 == 'Specific Players':
|
198 |
player_var2 = st.multiselect('Which players do you want?', options = fd_raw['Player'].unique())
|
199 |
elif player_var1 == 'Full Slate':
|
200 |
player_var2 = fd_raw.Player.values.tolist()
|
201 |
+
|
202 |
+
raw_baselines = fd_raw
|
203 |
+
column_names = fd_columns
|
204 |
|
205 |
if st.button("Prepare data export", key='data_export'):
|
206 |
+
if site_var1 == 'Draftkings':
|
207 |
+
if 'working_seed' in st.session_state:
|
208 |
+
st.session_state.working_seed = st.session_state.working_seed
|
209 |
+
if player_var1 == 'Specific Players':
|
210 |
+
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
|
211 |
+
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
|
212 |
+
elif 'working_seed' not in st.session_state:
|
213 |
+
if slate_var1 == 'Main Slate':
|
214 |
+
st.session_state.working_seed = init_DK_seed_frames(sharp_split_var)
|
215 |
+
dk_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_id))
|
216 |
+
elif slate_var1 == 'Secondary Slate':
|
217 |
+
st.session_state.working_seed = init_DK_secondary_seed_frames(sharp_split_var)
|
218 |
+
dk_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_id))
|
219 |
+
|
220 |
+
raw_baselines = dk_raw
|
221 |
+
column_names = dk_columns
|
222 |
+
|
223 |
+
if player_var1 == 'Specific Players':
|
224 |
+
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
|
225 |
+
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
|
226 |
+
export_column_var = 8
|
227 |
+
data_export = st.session_state.data_export_display.copy()
|
228 |
+
for col in range(export_column_var):
|
229 |
+
data_export[:, col] = np.array([dk_id_dict.get(x, x) for x in data_export[:, col]])
|
230 |
+
|
231 |
+
elif site_var1 == 'Fanduel':
|
232 |
+
if 'working_seed' in st.session_state:
|
233 |
+
st.session_state.working_seed = st.session_state.working_seed
|
234 |
+
if player_var1 == 'Specific Players':
|
235 |
+
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
|
236 |
+
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
|
237 |
+
elif 'working_seed' not in st.session_state:
|
238 |
+
if slate_var1 == 'Main Slate':
|
239 |
+
st.session_state.working_seed = init_FD_seed_frames(sharp_split_var)
|
240 |
+
fd_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_id))
|
241 |
+
elif slate_var1 == 'Secondary Slate':
|
242 |
+
st.session_state.working_seed = init_FD_secondary_seed_frames(sharp_split_var)
|
243 |
+
fd_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_id))
|
244 |
+
|
245 |
+
raw_baselines = fd_raw
|
246 |
+
column_names = fd_columns
|
247 |
+
|
248 |
+
if player_var1 == 'Specific Players':
|
249 |
+
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
|
250 |
+
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
|
251 |
+
export_column_var = 9
|
252 |
+
data_export = st.session_state.data_export_display.copy()
|
253 |
+
for col in range(export_column_var):
|
254 |
+
data_export[:, col] = np.array([fd_id_dict.get(x, x) for x in fd_id_dict[:, col]])
|
255 |
st.download_button(
|
256 |
label="Export optimals set",
|
257 |
data=convert_df(data_export),
|
|
|
266 |
st.session_state.working_seed = st.session_state.working_seed
|
267 |
if player_var1 == 'Specific Players':
|
268 |
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
|
|
|
|
|
269 |
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
|
270 |
elif 'working_seed' not in st.session_state:
|
271 |
+
if slate_var1 == 'Main Slate':
|
272 |
+
st.session_state.working_seed = init_DK_seed_frames(sharp_split_var)
|
273 |
+
dk_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_id))
|
274 |
+
elif slate_var1 == 'Secondary Slate':
|
275 |
+
st.session_state.working_seed = init_DK_secondary_seed_frames(sharp_split_var)
|
276 |
+
dk_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_id))
|
277 |
+
|
278 |
+
raw_baselines = dk_raw
|
279 |
+
column_names = dk_columns
|
280 |
+
|
281 |
if player_var1 == 'Specific Players':
|
282 |
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
|
|
|
|
|
283 |
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
|
284 |
|
285 |
elif site_var1 == 'Fanduel':
|
|
|
287 |
st.session_state.working_seed = st.session_state.working_seed
|
288 |
if player_var1 == 'Specific Players':
|
289 |
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
|
|
|
|
|
290 |
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
|
291 |
elif 'working_seed' not in st.session_state:
|
292 |
+
if slate_var1 == 'Main Slate':
|
293 |
+
st.session_state.working_seed = init_FD_seed_frames(sharp_split_var)
|
294 |
+
fd_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_id))
|
295 |
+
elif slate_var1 == 'Secondary Slate':
|
296 |
+
st.session_state.working_seed = init_FD_secondary_seed_frames(sharp_split_var)
|
297 |
+
fd_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_id))
|
298 |
+
|
299 |
+
raw_baselines = fd_raw
|
300 |
+
column_names = fd_columns
|
301 |
+
|
302 |
if player_var1 == 'Specific Players':
|
303 |
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
|
|
|
|
|
304 |
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
|
305 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
306 |
if 'data_export_display' in st.session_state:
|
307 |
st.dataframe(st.session_state.data_export_display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), height=500, use_container_width = True)
|
308 |
|
|
|
313 |
st.cache_data.clear()
|
314 |
for key in st.session_state.keys():
|
315 |
del st.session_state[key]
|
316 |
+
DK_seed = init_DK_seed_frames(10000)
|
317 |
+
FD_seed = init_FD_seed_frames(10000)
|
318 |
+
DK_secondary = init_DK_secondary_seed_frames(10000)
|
319 |
+
FD_secondary = init_FD_secondary_seed_frames(10000)
|
320 |
dk_raw, fd_raw, dk_secondary, fd_secondary = init_baselines()
|
321 |
+
dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_id))
|
322 |
+
fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_id))
|
323 |
+
|
324 |
sim_slate_var1 = st.radio("Which data are you loading?", ('Main Slate', 'Secondary Slate'), key='sim_slate_var1')
|
325 |
sim_site_var1 = st.radio("What site are you working with?", ('Draftkings', 'Fanduel'), key='sim_site_var1')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
326 |
|
327 |
contest_var1 = st.selectbox("What contest size are you simulating?", ('Small', 'Medium', 'Large', 'Custom'))
|
328 |
if contest_var1 == 'Small':
|
|
|
332 |
elif contest_var1 == 'Large':
|
333 |
Contest_Size = 10000
|
334 |
elif contest_var1 == 'Custom':
|
335 |
+
Contest_Size = st.number_input("Insert contest size", value=100, min_value=100, max_value=100000, step=50)
|
336 |
strength_var1 = st.selectbox("How sharp is the field in the contest?", ('Very', 'Above Average', 'Average', 'Below Average', 'Not Very'))
|
337 |
if strength_var1 == 'Not Very':
|
338 |
sharp_split = 500000
|
|
|
357 |
'Team_map':dict(zip(raw_baselines.Player,raw_baselines.Team)),
|
358 |
'STDev_map':dict(zip(raw_baselines.Player,raw_baselines.STDev))
|
359 |
}
|
360 |
+
Sim_Winners = sim_contest(1000, st.session_state.working_seed, st.session_state.maps_dict, Contest_Size)
|
361 |
Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners))
|
362 |
|
363 |
# Initial setup
|
|
|
382 |
|
383 |
else:
|
384 |
if sim_site_var1 == 'Draftkings':
|
385 |
+
if sim_slate_var1 == 'Main Slate':
|
386 |
+
DK_seed = init_DK_seed_frames(sharp_split)
|
387 |
+
raw_baselines = dk_raw
|
388 |
+
column_names = dk_columns
|
389 |
+
elif sim_slate_var1 == 'Secondary Slate':
|
390 |
+
DK_seed = init_DK_secondary_seed_frames(sharp_split)
|
391 |
+
raw_baselines = dk_secondary
|
392 |
+
column_names = dk_columns
|
393 |
+
|
394 |
elif sim_site_var1 == 'Fanduel':
|
395 |
+
if sim_slate_var1 == 'Main Slate':
|
396 |
+
FD_seed = init_FD_seed_frames(sharp_split)
|
397 |
+
raw_baselines = fd_raw
|
398 |
+
column_names = fd_columns
|
399 |
+
elif sim_slate_var1 == 'Secondary Slate':
|
400 |
+
FD_seed = init_FD_secondary_seed_frames(sharp_split)
|
401 |
+
raw_baselines = fd_secondary
|
402 |
+
column_names = fd_columns
|
403 |
+
|
404 |
st.session_state.maps_dict = {
|
405 |
'Projection_map':dict(zip(raw_baselines.Player,raw_baselines.Median)),
|
406 |
'Salary_map':dict(zip(raw_baselines.Player,raw_baselines.Salary)),
|
|
|
409 |
'Team_map':dict(zip(raw_baselines.Player,raw_baselines.Team)),
|
410 |
'STDev_map':dict(zip(raw_baselines.Player,raw_baselines.STDev))
|
411 |
}
|
412 |
+
Sim_Winners = sim_contest(1000, st.session_state.working_seed, st.session_state.maps_dict, Contest_Size)
|
413 |
Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners))
|
414 |
|
415 |
# Initial setup
|