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
Files changed (1) hide show
  1. app.py +127 -115
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 gc, gc2, db, NBA_Data
49
 
50
- gcservice_account, gcservice_account2, db, NBA_Data = init_conn()
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 = 300)
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 = 300)
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 = 300)
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 = 300)
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 = 301)
106
  def init_baselines():
107
- sh = gcservice_account.open_by_url('https://docs.google.com/spreadsheets/d/1Yq0vGriWK-bS79e-bD6_u9pqrYE6Yrlbb_wEkmH-ot0/edit#gid=172632260')
108
- worksheet = sh.worksheet('Player_Level_ROO')
109
- load_display = pd.DataFrame(worksheet.get_all_records())
 
 
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, sharp_split, Contest_Size):
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 = fp_array[np.random.choice(fp_array.shape[0], Contest_Size)]
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
- data_export = st.session_state.working_seed.copy()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- st.session_state.working_seed = DK_seed.copy()
263
- st.session_state.working_seed = st.session_state.working_seed
 
 
 
 
 
 
 
 
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
- st.session_state.working_seed = FD_seed.copy()
280
- st.session_state.working_seed = st.session_state.working_seed
 
 
 
 
 
 
 
 
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, placeholder="Type a number under 10,000...")
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, sharp_split, Contest_Size)
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
- st.session_state.working_seed = DK_seed.copy()
 
 
 
 
 
 
 
 
390
  elif sim_site_var1 == 'Fanduel':
391
- st.session_state.working_seed = FD_seed.copy()
 
 
 
 
 
 
 
 
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, sharp_split, Contest_Size)
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