James McCool commited on
Commit
b107789
·
1 Parent(s): 3a010ef

Initial Commit

Browse files
Files changed (3) hide show
  1. app.py +766 -0
  2. app.yaml +10 -0
  3. requirements.txt +10 -0
app.py ADDED
@@ -0,0 +1,766 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ st.set_page_config(layout="wide")
3
+ import numpy as np
4
+ import pandas as pd
5
+ import pymongo
6
+
7
+ @st.cache_resource
8
+ def init_conn():
9
+
10
+ uri = st.secrets['mongo_uri']
11
+ client = pymongo.MongoClient(uri, retryWrites=True, serverSelectionTimeoutMS=500000)
12
+ db = client["MLB_Database"]
13
+
14
+ return db
15
+
16
+ db = init_conn()
17
+
18
+ percentages_format = {'Exposure': '{:.2%}'}
19
+ freq_format = {'Exposure': '{:.2%}', 'Proj Own': '{:.2%}', 'Edge': '{:.2%}'}
20
+ dk_columns = ['SP1', 'SP2', 'C', '1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
21
+ fd_columns = ['P', 'C_1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3', 'UTIL', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
22
+
23
+ st.markdown("""
24
+ <style>
25
+ /* Tab styling */
26
+ .stTabs [data-baseweb="tab-list"] {
27
+ gap: 8px;
28
+ padding: 4px;
29
+ }
30
+ .stTabs [data-baseweb="tab"] {
31
+ height: 50px;
32
+ white-space: pre-wrap;
33
+ background-color: #FFD700;
34
+ color: white;
35
+ border-radius: 10px;
36
+ gap: 1px;
37
+ padding: 10px 20px;
38
+ font-weight: bold;
39
+ transition: all 0.3s ease;
40
+ }
41
+ .stTabs [aria-selected="true"] {
42
+ background-color: #DAA520;
43
+ color: white;
44
+ }
45
+ .stTabs [data-baseweb="tab"]:hover {
46
+ background-color: #DAA520;
47
+ cursor: pointer;
48
+ }
49
+ </style>""", unsafe_allow_html=True)
50
+
51
+ @st.cache_data(ttl = 60)
52
+ def init_DK_seed_frames(sharp_split):
53
+
54
+ collection = db['DK_MLB_name_map']
55
+ cursor = collection.find()
56
+ raw_data = pd.DataFrame(list(cursor))
57
+ names_dict = dict(zip(raw_data['key'], raw_data['value']))
58
+
59
+ # Get the valid players from the Range of Outcomes collection
60
+ collection = db["Player_Range_Of_Outcomes"]
61
+ cursor = collection.find({"Site": "Draftkings", "Slate": "main_slate"})
62
+ valid_players = set(pd.DataFrame(list(cursor))['Player'].unique())
63
+
64
+ collection = db["DK_MLB_seed_frame"]
65
+ cursor = collection.find().limit(sharp_split)
66
+
67
+ raw_display = pd.DataFrame(list(cursor))
68
+ raw_display = raw_display[['SP1', 'SP2', 'C', '1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
69
+ dict_columns = ['SP1', 'SP2', 'C', '1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3']
70
+ # Map names
71
+ raw_display[dict_columns] = raw_display[dict_columns].apply(lambda x: x.map(names_dict))
72
+
73
+ # Validate lineups against valid players
74
+ raw_display = validate_lineup_players(raw_display, valid_players, dict_columns)
75
+
76
+ # Remove any remaining NaN values
77
+ raw_display = raw_display.dropna()
78
+ DK_seed = raw_display.to_numpy()
79
+
80
+ return DK_seed
81
+
82
+ @st.cache_data(ttl = 60)
83
+ def init_DK_secondary_seed_frames(sharp_split):
84
+
85
+ collection = db['DK_MLB_secondary_name_map']
86
+ cursor = collection.find()
87
+ raw_data = pd.DataFrame(list(cursor))
88
+ names_dict = dict(zip(raw_data['key'], raw_data['value']))
89
+
90
+ # Get the valid players from the Range of Outcomes collection
91
+ collection = db["Player_Range_Of_Outcomes"]
92
+ cursor = collection.find({"Site": "Draftkings", "Slate": "secondary_slate"})
93
+ valid_players = set(pd.DataFrame(list(cursor))['Player'].unique())
94
+
95
+ collection = db["DK_MLB_secondary_seed_frame"]
96
+ cursor = collection.find().limit(sharp_split)
97
+
98
+ raw_display = pd.DataFrame(list(cursor))
99
+ raw_display = raw_display[['SP1', 'SP2', 'C', '1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
100
+ dict_columns = ['SP1', 'SP2', 'C', '1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3']
101
+ # Map names
102
+ raw_display[dict_columns] = raw_display[dict_columns].apply(lambda x: x.map(names_dict))
103
+
104
+ # Validate lineups against valid players
105
+ raw_display = validate_lineup_players(raw_display, valid_players, dict_columns)
106
+
107
+ # Remove any remaining NaN values
108
+ raw_display = raw_display.dropna()
109
+ DK_seed = raw_display.to_numpy()
110
+
111
+ return DK_seed
112
+
113
+ @st.cache_data(ttl = 60)
114
+ def init_FD_seed_frames(sharp_split):
115
+
116
+ collection = db['FD_MLB_name_map']
117
+ cursor = collection.find()
118
+ raw_data = pd.DataFrame(list(cursor))
119
+ names_dict = dict(zip(raw_data['key'], raw_data['value']))
120
+
121
+ # Get the valid players from the Range of Outcomes collection
122
+ collection = db["Player_Range_Of_Outcomes"]
123
+ cursor = collection.find({"Site": "Fanduel", "Slate": "main_slate"})
124
+ valid_players = set(pd.DataFrame(list(cursor))['Player'].unique())
125
+
126
+ collection = db["FD_MLB_seed_frame"]
127
+ cursor = collection.find().limit(sharp_split)
128
+
129
+ raw_display = pd.DataFrame(list(cursor))
130
+ raw_display = raw_display[['P', 'C_1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3', 'UTIL', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
131
+ dict_columns = ['P', 'C_1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3', 'UTIL']
132
+ # Map names
133
+ raw_display[dict_columns] = raw_display[dict_columns].apply(lambda x: x.map(names_dict))
134
+
135
+ # Validate lineups against valid players
136
+ raw_display = validate_lineup_players(raw_display, valid_players, dict_columns)
137
+
138
+ # Remove any remaining NaN values
139
+ raw_display = raw_display.dropna()
140
+ FD_seed = raw_display.to_numpy()
141
+
142
+ return FD_seed
143
+
144
+ @st.cache_data(ttl = 60)
145
+ def init_FD_secondary_seed_frames(sharp_split):
146
+
147
+ collection = db['FD_MLB_secondary_name_map']
148
+ cursor = collection.find()
149
+ raw_data = pd.DataFrame(list(cursor))
150
+ names_dict = dict(zip(raw_data['key'], raw_data['value']))
151
+
152
+ # Get the valid players from the Range of Outcomes collection
153
+ collection = db["Player_Range_Of_Outcomes"]
154
+ cursor = collection.find({"Site": "Fanduel", "Slate": "secondary_slate"})
155
+ valid_players = set(pd.DataFrame(list(cursor))['Player'].unique())
156
+
157
+ collection = db["FD_MLB_secondary_seed_frame"]
158
+ cursor = collection.find().limit(sharp_split)
159
+
160
+ raw_display = pd.DataFrame(list(cursor))
161
+ raw_display = raw_display[['P', 'C_1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3', 'UTIL', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
162
+ dict_columns = ['P', 'C_1B', '2B', '3B', 'SS', 'OF1', 'OF2', 'OF3', 'UTIL']
163
+ # Map names
164
+ raw_display[dict_columns] = raw_display[dict_columns].apply(lambda x: x.map(names_dict))
165
+
166
+ # Validate lineups against valid players
167
+ raw_display = validate_lineup_players(raw_display, valid_players, dict_columns)
168
+
169
+ # Remove any remaining NaN values
170
+ raw_display = raw_display.dropna()
171
+ FD_seed = raw_display.to_numpy()
172
+
173
+ return FD_seed
174
+
175
+ @st.cache_data(ttl = 599)
176
+ def init_baselines():
177
+ collection = db["Player_Range_Of_Outcomes"]
178
+ cursor = collection.find()
179
+
180
+ load_display = pd.DataFrame(list(cursor))
181
+
182
+ load_display.replace('', np.nan, inplace=True)
183
+ load_display.rename(columns={"Fantasy": "Median", 'Name': 'Player', 'player_ID': 'player_id'}, inplace = True)
184
+ load_display = load_display[load_display['Median'] > 0]
185
+
186
+ dk_roo_raw = load_display[load_display['Site'] == 'Draftkings']
187
+ dk_roo_raw = dk_roo_raw[dk_roo_raw['Slate'] == 'main_slate']
188
+ dk_roo_raw['STDev'] = dk_roo_raw['Median'] / 3
189
+ dk_raw = dk_roo_raw.dropna(subset=['Median'])
190
+ dk_raw = dk_raw.rename(columns={'Own%': 'Own'})
191
+
192
+ fd_roo_raw = load_display[load_display['Site'] == 'Fanduel']
193
+ fd_roo_raw = fd_roo_raw[fd_roo_raw['Slate'] == 'main_slate']
194
+ fd_roo_raw['STDev'] = fd_roo_raw['Median'] / 3
195
+ fd_raw = fd_roo_raw.dropna(subset=['Median'])
196
+ fd_raw = fd_raw.rename(columns={'Own%': 'Own'})
197
+
198
+ dk_secondary_roo_raw = load_display[load_display['Site'] == 'Draftkings']
199
+ dk_secondary_roo_raw = dk_secondary_roo_raw[dk_secondary_roo_raw['Slate'] == 'secondary_slate']
200
+ dk_secondary_roo_raw['STDev'] = dk_secondary_roo_raw['Median'] / 3
201
+ dk_secondary = dk_secondary_roo_raw.dropna(subset=['Median'])
202
+ dk_secondary = dk_secondary.rename(columns={'Own%': 'Own'})
203
+
204
+ fd_secondary_roo_raw = load_display[load_display['Site'] == 'Fanduel']
205
+ fd_secondary_roo_raw = fd_secondary_roo_raw[fd_secondary_roo_raw['Slate'] == 'secondary_slate']
206
+ fd_secondary_roo_raw['STDev'] = fd_secondary_roo_raw['Median'] / 3
207
+ fd_secondary = fd_secondary_roo_raw.dropna(subset=['Median'])
208
+ fd_secondary = fd_secondary.rename(columns={'Own%': 'Own'})
209
+
210
+ teams_playing_count = len(dk_raw.Team.unique())
211
+
212
+ return dk_raw, fd_raw, dk_secondary, fd_secondary, teams_playing_count
213
+
214
+ @st.cache_data
215
+ def validate_lineup_players(df, valid_players, player_columns):
216
+ """
217
+ Validates that all players in specified columns exist in valid_players set
218
+
219
+ Args:
220
+ df: DataFrame containing lineups
221
+ valid_players: Set of valid player names
222
+ player_columns: List of columns containing player names
223
+
224
+ Returns:
225
+ DataFrame with only valid lineups
226
+ """
227
+ valid_rows = df[player_columns].apply(lambda x: x.isin(valid_players)).all(axis=1)
228
+ return df[valid_rows]
229
+
230
+ @st.cache_data
231
+ def convert_df(array):
232
+ array = pd.DataFrame(array, columns=column_names)
233
+ return array.to_csv().encode('utf-8')
234
+
235
+ @st.cache_data
236
+ def calculate_DK_value_frequencies(np_array):
237
+ unique, counts = np.unique(np_array[:, :10], return_counts=True)
238
+ frequencies = counts / len(np_array) # Normalize by the number of rows
239
+ combined_array = np.column_stack((unique, frequencies))
240
+ return combined_array
241
+
242
+ @st.cache_data
243
+ def calculate_FD_value_frequencies(np_array):
244
+ unique, counts = np.unique(np_array[:, :9], return_counts=True)
245
+ frequencies = counts / len(np_array) # Normalize by the number of rows
246
+ combined_array = np.column_stack((unique, frequencies))
247
+ return combined_array
248
+
249
+ @st.cache_data
250
+ def sim_contest(Sim_size, seed_frame, maps_dict, Contest_Size, teams_playing_count, site):
251
+ SimVar = 1
252
+ Sim_Winners = []
253
+ fp_array = seed_frame.copy()
254
+ # Pre-vectorize functions
255
+ vec_projection_map = np.vectorize(maps_dict['Projection_map'].__getitem__)
256
+ vec_stdev_map = np.vectorize(maps_dict['STDev_map'].__getitem__)
257
+
258
+ st.write('Simulating contest on frames')
259
+
260
+ while SimVar <= Sim_size:
261
+ fp_random = fp_array[np.random.choice(fp_array.shape[0], Contest_Size)]
262
+
263
+ if site == 'Draftkings':
264
+ # Calculate stack multipliers first
265
+ stack_multiplier = np.ones(fp_random.shape[0]) # Start with no bonus
266
+ stack_multiplier += np.minimum(0.10, np.where(fp_random[:, 13] == 4, 0.025 * (teams_playing_count - 8), 0))
267
+ stack_multiplier += np.minimum(0.15, np.where(fp_random[:, 13] >= 5, 0.025 * (teams_playing_count - 12), 0))
268
+ elif site == 'Fanduel':
269
+ # Calculate stack multipliers first
270
+ stack_multiplier = np.ones(fp_random.shape[0]) # Start with no bonus
271
+ stack_multiplier += np.minimum(0.10, np.where(fp_random[:, 12] == 4, 0.025 * (teams_playing_count - 8), 0))
272
+ stack_multiplier += np.minimum(0.15, np.where(fp_random[:, 12] >= 5, 0.025 * (teams_playing_count - 12), 0))
273
+
274
+ # Apply multipliers to both loc and scale in the normal distribution
275
+ base_projections = np.sum(np.random.normal(
276
+ loc=vec_projection_map(fp_random[:, :-7]) * stack_multiplier[:, np.newaxis],
277
+ scale=vec_stdev_map(fp_random[:, :-7]) * stack_multiplier[:, np.newaxis]),
278
+ axis=1)
279
+
280
+ final_projections = base_projections
281
+
282
+ sample_arrays = np.c_[fp_random, final_projections]
283
+ if site == 'Draftkings':
284
+ final_array = sample_arrays[sample_arrays[:, 10].argsort()[::-1]]
285
+ elif site == 'Fanduel':
286
+ final_array = sample_arrays[sample_arrays[:, 9].argsort()[::-1]]
287
+ best_lineup = final_array[final_array[:, -1].argsort(kind='stable')[::-1][:1]]
288
+ Sim_Winners.append(best_lineup)
289
+ SimVar += 1
290
+
291
+ return Sim_Winners
292
+
293
+ dk_raw, fd_raw, dk_secondary, fd_secondary, teams_playing_count = init_baselines()
294
+ dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_id))
295
+ fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_id))
296
+
297
+ tab1, tab2 = st.tabs(['Contest Sims', 'Data Export'])
298
+
299
+ with tab1:
300
+ with st.expander("Info and Filters"):
301
+ if st.button("Load/Reset Data", key='reset2'):
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(10000)
306
+ FD_seed = init_FD_seed_frames(10000)
307
+ dk_raw, fd_raw, dk_secondary, fd_secondary, teams_playing_count = init_baselines()
308
+ dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_id))
309
+ fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_id))
310
+
311
+ sim_slate_var1 = st.radio("Which data are you loading?", ('Main Slate', 'Other Main Slate'), key='sim_slate_var1')
312
+ sim_site_var1 = st.radio("What site are you working with?", ('Draftkings', 'Fanduel'), key='sim_site_var1')
313
+
314
+ contest_var1 = st.selectbox("What contest size are you simulating?", ('Small', 'Medium', 'Large', 'Custom'))
315
+ if contest_var1 == 'Small':
316
+ Contest_Size = 1000
317
+ elif contest_var1 == 'Medium':
318
+ Contest_Size = 5000
319
+ elif contest_var1 == 'Large':
320
+ Contest_Size = 10000
321
+ elif contest_var1 == 'Custom':
322
+ Contest_Size = st.number_input("Insert contest size", value=100, placeholder="Type a number under 10,000...")
323
+ strength_var1 = st.selectbox("How sharp is the field in the contest?", ('Very', 'Above Average', 'Average', 'Below Average', 'Not Very'))
324
+ if strength_var1 == 'Not Very':
325
+ sharp_split = 500000
326
+ elif strength_var1 == 'Below Average':
327
+ sharp_split = 250000
328
+ elif strength_var1 == 'Average':
329
+ sharp_split = 100000
330
+ elif strength_var1 == 'Above Average':
331
+ sharp_split = 50000
332
+ elif strength_var1 == 'Very':
333
+ sharp_split = 10000
334
+
335
+ if st.button("Run Contest Sim"):
336
+ if 'working_seed' in st.session_state:
337
+ st.session_state.maps_dict = {
338
+ 'Projection_map':dict(zip(raw_baselines.Player,raw_baselines.Median)),
339
+ 'Salary_map':dict(zip(raw_baselines.Player,raw_baselines.Salary)),
340
+ 'Pos_map':dict(zip(raw_baselines.Player,raw_baselines.Position)),
341
+ 'Own_map':dict(zip(raw_baselines.Player,raw_baselines['Own'])),
342
+ 'Team_map':dict(zip(raw_baselines.Player,raw_baselines.Team)),
343
+ 'STDev_map':dict(zip(raw_baselines.Player,raw_baselines.STDev))
344
+ }
345
+ Sim_Winners = sim_contest(1000, st.session_state.working_seed, st.session_state.maps_dict, Contest_Size, teams_playing_count, sim_site_var1)
346
+ Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners))
347
+
348
+ #st.table(Sim_Winner_Frame)
349
+
350
+ # Initial setup
351
+ Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners), columns=column_names + ['Fantasy'])
352
+ Sim_Winner_Frame['GPP_Proj'] = (Sim_Winner_Frame['proj'] + Sim_Winner_Frame['Fantasy']) / 2
353
+ Sim_Winner_Frame['unique_id'] = Sim_Winner_Frame['proj'].astype(str) + Sim_Winner_Frame['salary'].astype(str) + Sim_Winner_Frame['Team'].astype(str) + Sim_Winner_Frame['Secondary'].astype(str)
354
+ Sim_Winner_Frame = Sim_Winner_Frame.assign(win_count=Sim_Winner_Frame['unique_id'].map(Sim_Winner_Frame['unique_id'].value_counts()))
355
+
356
+ # Type Casting
357
+ type_cast_dict = {'salary': int, 'proj': np.float16, 'Fantasy': np.float16, 'GPP_Proj': np.float32, 'Own': np.float32}
358
+ Sim_Winner_Frame = Sim_Winner_Frame.astype(type_cast_dict)
359
+
360
+ # Sorting
361
+ st.session_state.Sim_Winner_Frame = Sim_Winner_Frame.sort_values(by=['win_count', 'GPP_Proj'], ascending= [False, False]).copy().drop_duplicates(subset='unique_id').head(100)
362
+ st.session_state.Sim_Winner_Frame.drop(columns='unique_id', inplace=True)
363
+
364
+ # Data Copying
365
+ st.session_state.Sim_Winner_Export = Sim_Winner_Frame.copy()
366
+ for col in st.session_state.Sim_Winner_Export.iloc[:, 0:9].columns:
367
+ st.session_state.Sim_Winner_Export[col] = st.session_state.Sim_Winner_Export[col].map(dk_id_dict)
368
+ st.session_state.Sim_Winner_Export = st.session_state.Sim_Winner_Export.drop_duplicates(subset=['Team', 'Secondary', 'salary', 'unique_id'])
369
+
370
+ # Data Copying
371
+ st.session_state.Sim_Winner_Display = Sim_Winner_Frame.copy()
372
+
373
+ else:
374
+ if sim_site_var1 == 'Draftkings':
375
+ if sim_slate_var1 == 'Main Slate':
376
+ st.session_state.working_seed = init_DK_seed_frames(sharp_split)
377
+ dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_id))
378
+ raw_baselines = dk_raw
379
+ column_names = dk_columns
380
+ elif sim_site_var1 == 'Fanduel':
381
+ if sim_slate_var1 == 'Main Slate':
382
+ st.session_state.working_seed = init_FD_seed_frames(sharp_split)
383
+ fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_id))
384
+ raw_baselines = fd_raw
385
+ column_names = fd_columns
386
+
387
+ st.session_state.maps_dict = {
388
+ 'Projection_map':dict(zip(raw_baselines.Player,raw_baselines.Median)),
389
+ 'Salary_map':dict(zip(raw_baselines.Player,raw_baselines.Salary)),
390
+ 'Pos_map':dict(zip(raw_baselines.Player,raw_baselines.Position)),
391
+ 'Own_map':dict(zip(raw_baselines.Player,raw_baselines['Own'])),
392
+ 'Team_map':dict(zip(raw_baselines.Player,raw_baselines.Team)),
393
+ 'STDev_map':dict(zip(raw_baselines.Player,raw_baselines.STDev))
394
+ }
395
+ Sim_Winners = sim_contest(1000, st.session_state.working_seed, st.session_state.maps_dict, Contest_Size, teams_playing_count, sim_site_var1)
396
+ Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners))
397
+
398
+ #st.table(Sim_Winner_Frame)
399
+
400
+ # Initial setup
401
+ Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners), columns=column_names + ['Fantasy'])
402
+ Sim_Winner_Frame['GPP_Proj'] = (Sim_Winner_Frame['proj'] + Sim_Winner_Frame['Fantasy']) / 2
403
+ Sim_Winner_Frame['unique_id'] = Sim_Winner_Frame['proj'].astype(str) + Sim_Winner_Frame['salary'].astype(str) + Sim_Winner_Frame['Team'].astype(str) + Sim_Winner_Frame['Secondary'].astype(str)
404
+ Sim_Winner_Frame = Sim_Winner_Frame.assign(win_count=Sim_Winner_Frame['unique_id'].map(Sim_Winner_Frame['unique_id'].value_counts()))
405
+
406
+ # Type Casting
407
+ type_cast_dict = {'salary': int, 'proj': np.float16, 'Fantasy': np.float16, 'GPP_Proj': np.float32, 'Own': np.float32}
408
+ Sim_Winner_Frame = Sim_Winner_Frame.astype(type_cast_dict)
409
+
410
+ # Sorting
411
+ st.session_state.Sim_Winner_Frame = Sim_Winner_Frame.sort_values(by=['win_count', 'GPP_Proj'], ascending= [False, False]).copy().drop_duplicates(subset='unique_id').head(100)
412
+ st.session_state.Sim_Winner_Frame.drop(columns='unique_id', inplace=True)
413
+
414
+ # Data Copying
415
+ st.session_state.Sim_Winner_Export = Sim_Winner_Frame.copy()
416
+ for col in st.session_state.Sim_Winner_Export.iloc[:, 0:9].columns:
417
+ st.session_state.Sim_Winner_Export[col] = st.session_state.Sim_Winner_Export[col].map(dk_id_dict)
418
+ st.session_state.Sim_Winner_Export = st.session_state.Sim_Winner_Export.drop_duplicates(subset=['Team', 'Secondary', 'salary', 'unique_id'])
419
+
420
+ # Data Copying
421
+ st.session_state.Sim_Winner_Display = Sim_Winner_Frame.copy()
422
+ st.session_state.freq_copy = st.session_state.Sim_Winner_Display
423
+
424
+ if sim_site_var1 == 'Draftkings':
425
+ freq_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,0:10].values, return_counts=True)),
426
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
427
+ elif sim_site_var1 == 'Fanduel':
428
+ freq_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,0:9].values, return_counts=True)),
429
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
430
+ freq_working['Freq'] = freq_working['Freq'].astype(int)
431
+ freq_working['Position'] = freq_working['Player'].map(st.session_state.maps_dict['Pos_map'])
432
+ freq_working['Salary'] = freq_working['Player'].map(st.session_state.maps_dict['Salary_map'])
433
+ freq_working['Proj Own'] = freq_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
434
+ freq_working['Exposure'] = freq_working['Freq']/(1000)
435
+ freq_working['Edge'] = freq_working['Exposure'] - freq_working['Proj Own']
436
+ freq_working['Team'] = freq_working['Player'].map(st.session_state.maps_dict['Team_map'])
437
+ st.session_state.player_freq = freq_working.copy()
438
+
439
+ if sim_site_var1 == 'Draftkings':
440
+ sp_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,0:2].values, return_counts=True)),
441
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
442
+ elif sim_site_var1 == 'Fanduel':
443
+ sp_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,0:1].values, return_counts=True)),
444
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
445
+ sp_working['Freq'] = sp_working['Freq'].astype(int)
446
+ sp_working['Position'] = sp_working['Player'].map(st.session_state.maps_dict['Pos_map'])
447
+ sp_working['Salary'] = sp_working['Player'].map(st.session_state.maps_dict['Salary_map'])
448
+ sp_working['Proj Own'] = sp_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
449
+ sp_working['Exposure'] = sp_working['Freq']/(1000)
450
+ sp_working['Edge'] = sp_working['Exposure'] - sp_working['Proj Own']
451
+ sp_working['Team'] = sp_working['Player'].map(st.session_state.maps_dict['Team_map'])
452
+ st.session_state.sp_freq = sp_working.copy()
453
+
454
+ if sim_site_var1 == 'Draftkings':
455
+ team_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,12:13].values, return_counts=True)),
456
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
457
+ elif sim_site_var1 == 'Fanduel':
458
+ team_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,11:12].values, return_counts=True)),
459
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
460
+ team_working['Freq'] = team_working['Freq'].astype(int)
461
+ team_working['Exposure'] = team_working['Freq']/(1000)
462
+ st.session_state.team_freq = team_working.copy()
463
+
464
+ if sim_site_var1 == 'Draftkings':
465
+ stack_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,13:14].values, return_counts=True)),
466
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
467
+ elif sim_site_var1 == 'Fanduel':
468
+ stack_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,12:13].values, return_counts=True)),
469
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
470
+ stack_working['Freq'] = stack_working['Freq'].astype(int)
471
+ stack_working['Exposure'] = stack_working['Freq']/(1000)
472
+ st.session_state.stack_freq = stack_working.copy()
473
+
474
+ with st.container():
475
+ if st.button("Reset Sim", key='reset_sim'):
476
+ for key in st.session_state.keys():
477
+ del st.session_state[key]
478
+ if 'player_freq' in st.session_state:
479
+ player_split_var2 = st.radio("Are you wanting to isolate any lineups with specific players?", ('Full Players', 'Specific Players'), key='player_split_var2')
480
+ if player_split_var2 == 'Specific Players':
481
+ find_var2 = st.multiselect('Which players must be included in the lineups?', options = st.session_state.player_freq['Player'].unique())
482
+ elif player_split_var2 == 'Full Players':
483
+ find_var2 = st.session_state.player_freq.Player.values.tolist()
484
+
485
+ if player_split_var2 == 'Specific Players':
486
+ st.session_state.Sim_Winner_Display = st.session_state.Sim_Winner_Frame[np.equal.outer(st.session_state.Sim_Winner_Frame.to_numpy(), find_var2).any(axis=1).all(axis=1)]
487
+ if player_split_var2 == 'Full Players':
488
+ st.session_state.Sim_Winner_Display = st.session_state.Sim_Winner_Frame
489
+ if 'Sim_Winner_Display' in st.session_state:
490
+ st.dataframe(st.session_state.Sim_Winner_Display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
491
+ if 'Sim_Winner_Export' in st.session_state:
492
+ st.download_button(
493
+
494
+ label="Export Full Frame",
495
+ data=st.session_state.Sim_Winner_Export.to_csv().encode('utf-8'),
496
+ file_name='MLB_consim_export.csv',
497
+ mime='text/csv',
498
+ )
499
+ tab1, tab2 = st.tabs(['Winning Frame Statistics', 'Stack Type Statistics'])
500
+
501
+ with tab1:
502
+ if 'Sim_Winner_Display' in st.session_state:
503
+ # Create a new dataframe with summary statistics
504
+ summary_df = pd.DataFrame({
505
+ 'Metric': ['Min', 'Average', 'Max', 'STDdev'],
506
+ 'Salary': [
507
+ st.session_state.Sim_Winner_Display['salary'].min(),
508
+ st.session_state.Sim_Winner_Display['salary'].mean(),
509
+ st.session_state.Sim_Winner_Display['salary'].max(),
510
+ st.session_state.Sim_Winner_Display['salary'].std()
511
+ ],
512
+ 'Proj': [
513
+ st.session_state.Sim_Winner_Display['proj'].min(),
514
+ st.session_state.Sim_Winner_Display['proj'].mean(),
515
+ st.session_state.Sim_Winner_Display['proj'].max(),
516
+ st.session_state.Sim_Winner_Display['proj'].std()
517
+ ],
518
+ 'Own': [
519
+ st.session_state.Sim_Winner_Display['Own'].min(),
520
+ st.session_state.Sim_Winner_Display['Own'].mean(),
521
+ st.session_state.Sim_Winner_Display['Own'].max(),
522
+ st.session_state.Sim_Winner_Display['Own'].std()
523
+ ],
524
+ 'Fantasy': [
525
+ st.session_state.Sim_Winner_Display['Fantasy'].min(),
526
+ st.session_state.Sim_Winner_Display['Fantasy'].mean(),
527
+ st.session_state.Sim_Winner_Display['Fantasy'].max(),
528
+ st.session_state.Sim_Winner_Display['Fantasy'].std()
529
+ ],
530
+ 'GPP_Proj': [
531
+ st.session_state.Sim_Winner_Display['GPP_Proj'].min(),
532
+ st.session_state.Sim_Winner_Display['GPP_Proj'].mean(),
533
+ st.session_state.Sim_Winner_Display['GPP_Proj'].max(),
534
+ st.session_state.Sim_Winner_Display['GPP_Proj'].std()
535
+ ]
536
+ })
537
+
538
+ # Set the index of the summary dataframe as the "Metric" column
539
+ summary_df = summary_df.set_index('Metric')
540
+
541
+ # Display the summary dataframe
542
+ st.subheader("Winning Frame Statistics")
543
+ st.dataframe(summary_df.style.format({
544
+ 'Salary': '{:.2f}',
545
+ 'Proj': '{:.2f}',
546
+ 'Own': '{:.2f}',
547
+ 'Fantasy': '{:.2f}',
548
+ 'GPP_Proj': '{:.2f}'
549
+ }).background_gradient(cmap='RdYlGn', axis=0, subset=['Salary', 'Proj', 'Own', 'Fantasy', 'GPP_Proj']), use_container_width=True)
550
+
551
+ with tab2:
552
+ if 'Sim_Winner_Display' in st.session_state:
553
+ # Apply position mapping to FLEX column
554
+ stack_counts = st.session_state.freq_copy['Team_count'].value_counts()
555
+
556
+ # Calculate average statistics for each stack size
557
+ stack_stats = st.session_state.freq_copy.groupby('Team_count').agg({
558
+ 'proj': 'mean',
559
+ 'Own': 'mean',
560
+ 'Fantasy': 'mean',
561
+ 'GPP_Proj': 'mean'
562
+ })
563
+
564
+ # Combine counts and average statistics
565
+ stack_summary = pd.concat([stack_counts, stack_stats], axis=1)
566
+ stack_summary.columns = ['Count', 'Avg Proj', 'Avg Own', 'Avg Fantasy', 'Avg GPP_Proj']
567
+ stack_summary = stack_summary.reset_index()
568
+ stack_summary.columns = ['Stack Size', 'Count', 'Avg Proj', 'Avg Own', 'Avg Fantasy', 'Avg GPP_Proj']
569
+ stack_summary = stack_summary.sort_values(by='Stack Size', ascending=True)
570
+ stack_summary = stack_summary.set_index('Stack Size')
571
+
572
+ # Display the summary dataframe
573
+ st.subheader("Stack Type Statistics")
574
+ st.dataframe(stack_summary.style.format({
575
+ 'Count': '{:.0f}',
576
+ 'Avg Proj': '{:.2f}',
577
+ 'Avg Own': '{:.2f}',
578
+ 'Avg Fantasy': '{:.2f}',
579
+ 'Avg GPP_Proj': '{:.2f}'
580
+ }).background_gradient(cmap='RdYlGn', axis=0, subset=['Count', 'Avg Proj', 'Avg Own', 'Avg Fantasy', 'Avg GPP_Proj']), use_container_width=True)
581
+ else:
582
+ st.write("Simulation data or position mapping not available.")
583
+
584
+
585
+ with st.container():
586
+ tab1, tab2, tab3, tab4 = st.tabs(['Overall Exposures', 'SP Exposures', 'Team Exposures', 'Stack Size Exposures'])
587
+ with tab1:
588
+ if 'player_freq' in st.session_state:
589
+
590
+ st.dataframe(st.session_state.player_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
591
+ st.download_button(
592
+ label="Export Exposures",
593
+ data=st.session_state.player_freq.to_csv().encode('utf-8'),
594
+ file_name='player_freq_export.csv',
595
+ mime='text/csv',
596
+ key='overall'
597
+ )
598
+ with tab2:
599
+ if 'sp_freq' in st.session_state:
600
+
601
+ st.dataframe(st.session_state.sp_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
602
+ st.download_button(
603
+ label="Export Exposures",
604
+ data=st.session_state.sp_freq.to_csv().encode('utf-8'),
605
+ file_name='sp_freq.csv',
606
+ mime='text/csv',
607
+ key='sp'
608
+ )
609
+ with tab3:
610
+ if 'team_freq' in st.session_state:
611
+
612
+ st.dataframe(st.session_state.team_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(percentages_format, precision=2), use_container_width = True)
613
+ st.download_button(
614
+ label="Export Exposures",
615
+ data=st.session_state.team_freq.to_csv().encode('utf-8'),
616
+ file_name='team_freq.csv',
617
+ mime='text/csv',
618
+ key='team'
619
+ )
620
+ with tab4:
621
+ if 'stack_freq' in st.session_state:
622
+
623
+ st.dataframe(st.session_state.stack_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(percentages_format, precision=2), use_container_width = True)
624
+ st.download_button(
625
+ label="Export Exposures",
626
+ data=st.session_state.stack_freq.to_csv().encode('utf-8'),
627
+ file_name='stack_freq.csv',
628
+ mime='text/csv',
629
+ key='stack'
630
+ )
631
+
632
+ with tab2:
633
+ with st.expander("Info and Filters"):
634
+ if st.button("Load/Reset Data", key='reset1'):
635
+ st.cache_data.clear()
636
+ for key in st.session_state.keys():
637
+ del st.session_state[key]
638
+ DK_seed = init_DK_seed_frames(10000)
639
+ FD_seed = init_FD_seed_frames(10000)
640
+ dk_raw, fd_raw, dk_secondary, fd_secondary, teams_playing_count = init_baselines()
641
+ dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_id))
642
+ fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_id))
643
+
644
+ slate_var1 = st.radio("Which data are you loading?", ('Main Slate', 'Secondary Slate'))
645
+ site_var1 = st.radio("What site are you working with?", ('Draftkings', 'Fanduel'))
646
+ sharp_split_var = st.number_input("How many lineups do you want?", value=10000, max_value=500000, min_value=10000, step=10000)
647
+ lineup_num_var = st.number_input("How many lineups do you want to display?", min_value=1, max_value=500, value=10, step=1)
648
+
649
+ if site_var1 == 'Draftkings':
650
+
651
+ team_var1 = st.radio("Do you want a frame with specific teams?", ('Full Slate', 'Specific Teams'), key='team_var1')
652
+ if team_var1 == 'Specific Teams':
653
+ team_var2 = st.multiselect('Which teams do you want?', options = dk_raw['Team'].unique())
654
+ elif team_var1 == 'Full Slate':
655
+ team_var2 = dk_raw.Team.values.tolist()
656
+
657
+ stack_var1 = st.radio("Do you want a frame with specific stack sizes?", ('Full Slate', 'Specific Stack Sizes'), key='stack_var1')
658
+ if stack_var1 == 'Specific Stack Sizes':
659
+ stack_var2 = st.multiselect('Which stack sizes do you want?', options = [5, 4, 3, 2, 1, 0])
660
+ elif stack_var1 == 'Full Slate':
661
+ stack_var2 = [5, 4, 3, 2, 1, 0]
662
+
663
+ raw_baselines = dk_raw
664
+ column_names = dk_columns
665
+
666
+ elif site_var1 == 'Fanduel':
667
+
668
+ team_var1 = st.radio("Do you want a frame with specific teams?", ('Full Slate', 'Specific Teams'), key='team_var1')
669
+ if team_var1 == 'Specific Teams':
670
+ team_var2 = st.multiselect('Which teams do you want?', options = fd_raw['Team'].unique())
671
+ elif team_var1 == 'Full Slate':
672
+ team_var2 = fd_raw.Team.values.tolist()
673
+
674
+ stack_var1 = st.radio("Do you want a frame with specific stack sizes?", ('Full Slate', 'Specific Stack Sizes'), key='stack_var1')
675
+ if stack_var1 == 'Specific Stack Sizes':
676
+ stack_var2 = st.multiselect('Which stack sizes do you want?', options = [5, 4, 3, 2, 1, 0])
677
+ elif stack_var1 == 'Full Slate':
678
+ stack_var2 = [5, 4, 3, 2, 1, 0]
679
+
680
+ raw_baselines = fd_raw
681
+ column_names = fd_columns
682
+
683
+
684
+ if st.button("Prepare data export", key='data_export'):
685
+ if 'working_seed' in st.session_state:
686
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 11], team_var2)]
687
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 10], stack_var2)]
688
+ st.session_state.data_export_display = st.session_state.working_seed[0:lineup_num_var]
689
+ elif 'working_seed' not in st.session_state:
690
+ if site_var1 == 'Draftkings':
691
+ if slate_var1 == 'Main Slate':
692
+ st.session_state.working_seed = init_DK_seed_frames(sharp_split_var)
693
+
694
+ dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_id))
695
+ raw_baselines = dk_raw
696
+ column_names = dk_columns
697
+ elif slate_var1 == 'Secondary Slate':
698
+ st.session_state.working_seed = init_DK_secondary_seed_frames(sharp_split_var)
699
+
700
+ dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_id))
701
+ raw_baselines = dk_raw
702
+ column_names = dk_columns
703
+
704
+ elif site_var1 == 'Fanduel':
705
+ if slate_var1 == 'Main Slate':
706
+ st.session_state.working_seed = init_FD_seed_frames(sharp_split_var)
707
+
708
+ fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_id))
709
+ raw_baselines = fd_raw
710
+ column_names = fd_columns
711
+ elif slate_var1 == 'Secondary Slate':
712
+ st.session_state.working_seed = init_FD_secondary_seed_frames(sharp_split_var)
713
+
714
+ fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_id))
715
+ raw_baselines = fd_raw
716
+ column_names = fd_columns
717
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 11], team_var2)]
718
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 10], stack_var2)]
719
+ st.session_state.data_export_display = st.session_state.working_seed[0:lineup_num_var]
720
+ data_export = st.session_state.working_seed.copy()
721
+ st.download_button(
722
+ label="Export optimals set",
723
+ data=convert_df(data_export),
724
+ file_name='MLB_optimals_export.csv',
725
+ mime='text/csv',
726
+ )
727
+ for key in st.session_state.keys():
728
+ del st.session_state[key]
729
+
730
+ if st.button("Load Data", key='load_data'):
731
+ if site_var1 == 'Draftkings':
732
+ if 'working_seed' in st.session_state:
733
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 11], team_var2)]
734
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 10], stack_var2)]
735
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
736
+ elif 'working_seed' not in st.session_state:
737
+ if slate_var1 == 'Main Slate':
738
+ st.session_state.working_seed = init_DK_seed_frames(sharp_split_var)
739
+ dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_id))
740
+
741
+ raw_baselines = dk_raw
742
+ column_names = dk_columns
743
+
744
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 11], team_var2)]
745
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 10], stack_var2)]
746
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
747
+
748
+ elif site_var1 == 'Fanduel':
749
+ if 'working_seed' in st.session_state:
750
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 11], team_var2)]
751
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 10], stack_var2)]
752
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
753
+ elif 'working_seed' not in st.session_state:
754
+ if slate_var1 == 'Main Slate':
755
+ st.session_state.working_seed = init_FD_seed_frames(sharp_split_var)
756
+ fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_id))
757
+
758
+ raw_baselines = fd_raw
759
+ column_names = fd_columns
760
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 11], team_var2)]
761
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 10], stack_var2)]
762
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
763
+
764
+ with st.container():
765
+ if 'data_export_display' in st.session_state:
766
+ st.dataframe(st.session_state.data_export_display.style.format(freq_format, precision=2), use_container_width = True)
app.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ runtime: python
2
+ env: flex
3
+
4
+ runtime_config:
5
+ python_version: 3
6
+
7
+ entrypoint: streamlit run streamlit-app.py --server.port $PORT
8
+
9
+ automatic_scaling:
10
+ max_num_instances: 1000
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ gspread
3
+ openpyxl
4
+ matplotlib
5
+ pymongo
6
+ pulp
7
+ docker
8
+ plotly
9
+ scipy
10
+ polars