James McCool commited on
Commit
646b1db
·
1 Parent(s): 1bf328a

initial commit on Dockerization update

Browse files
Files changed (3) hide show
  1. .streamlit/secrets.toml +1 -0
  2. Dockerfile +13 -0
  3. src/streamlit_app.py +799 -37
.streamlit/secrets.toml ADDED
@@ -0,0 +1 @@
 
 
1
+ mongo_uri = "mongodb+srv://multichem:[email protected]/?retryWrites=true&w=majority&appName=TestCluster"
Dockerfile CHANGED
@@ -5,11 +5,24 @@ WORKDIR /app
5
  RUN apt-get update && apt-get install -y \
6
  build-essential \
7
  curl \
 
8
  git \
9
  && rm -rf /var/lib/apt/lists/*
10
 
11
  COPY requirements.txt ./
12
  COPY src/ ./src/
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  RUN pip3 install -r requirements.txt
15
 
 
5
  RUN apt-get update && apt-get install -y \
6
  build-essential \
7
  curl \
8
+ software-properties-common \
9
  git \
10
  && rm -rf /var/lib/apt/lists/*
11
 
12
  COPY requirements.txt ./
13
  COPY src/ ./src/
14
+ COPY .streamlit/ ./.streamlit/
15
+
16
+
17
+
18
+ ENV MONGO_URI="mongodb+srv://multichem:[email protected]/?retryWrites=true&w=majority&appName=TestCluster"
19
+ RUN useradd -m -u 1000 user
20
+ USER user
21
+ ENV HOME=/home/user\
22
+ PATH=/home/user/.local/bin:$PATH
23
+ WORKDIR $HOME/app
24
+ RUN pip install --no-cache-dir --upgrade pip
25
+ COPY --chown=user . $HOME/app
26
 
27
  RUN pip3 install -r requirements.txt
28
 
src/streamlit_app.py CHANGED
@@ -1,40 +1,802 @@
1
- import altair as alt
2
  import numpy as np
3
  import pandas as pd
4
- import streamlit as st
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
  import numpy as np
3
  import pandas as pd
4
+ import pymongo
5
+ import re
6
+ import os
7
+ from itertools import combinations
8
+
9
+ st.set_page_config(layout="wide")
10
+
11
+ @st.cache_resource
12
+ def init_conn():
13
+ uri = os.getenv('MONGO_URI')
14
+ if not uri:
15
+ uri = st.secrets['mongo_uri']
16
+ client = pymongo.MongoClient(uri, retryWrites=True, serverSelectionTimeoutMS=500000)
17
+ db = client["NFL_Database"]
18
+
19
+ return db
20
+
21
+ db = init_conn()
22
+
23
+ percentages_format = {'Exposure': '{:.2%}'}
24
+ freq_format = {'Exposure': '{:.2%}', 'Proj Own': '{:.2%}', 'Edge': '{:.2%}'}
25
+ dk_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
26
+ fd_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
27
+
28
+ @st.cache_data(ttl = 600)
29
+ def init_DK_seed_frames(sharp_split):
30
+
31
+ collection = db['DK_NFL_name_map']
32
+ cursor = collection.find()
33
+ raw_data = pd.DataFrame(list(cursor))
34
+ names_dict = dict(zip(raw_data['key'], raw_data['value']))
35
+
36
+ collection = db["DK_NFL_seed_frame"]
37
+ cursor = collection.find().limit(sharp_split)
38
+
39
+ raw_display = pd.DataFrame(list(cursor))
40
+ raw_display = raw_display[['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
41
+ dict_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
42
+ st.write("converting names")
43
+ for col in dict_columns:
44
+ raw_display[col] = raw_display[col].map(names_dict)
45
+ DK_seed = raw_display.to_numpy()
46
+
47
+ return DK_seed
48
+
49
+ @st.cache_data(ttl = 600)
50
+ def init_DK_Secondary_seed_frames(sharp_split):
51
+
52
+ collection = db['DK_NFL_Secondary_name_map']
53
+ cursor = collection.find()
54
+ raw_data = pd.DataFrame(list(cursor))
55
+ names_dict = dict(zip(raw_data['key'], raw_data['value']))
56
+
57
+ collection = db["DK_NFL_Secondary_seed_frame"]
58
+ cursor = collection.find().limit(sharp_split)
59
+
60
+ raw_display = pd.DataFrame(list(cursor))
61
+ raw_display = raw_display[['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
62
+ dict_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
63
+ st.write("converting names")
64
+ for col in dict_columns:
65
+ raw_display[col] = raw_display[col].map(names_dict)
66
+ DK_seed = raw_display.to_numpy()
67
+
68
+ return DK_seed
69
+
70
+ @st.cache_data(ttl = 599)
71
+ def init_FD_seed_frames(sharp_split):
72
+
73
+ collection = db['FD_NFL_name_map']
74
+ cursor = collection.find()
75
+ raw_data = pd.DataFrame(list(cursor))
76
+ names_dict = dict(zip(raw_data['key'], raw_data['value']))
77
+
78
+ collection = db["FD_NFL_seed_frame"]
79
+ cursor = collection.find().limit(sharp_split)
80
+
81
+ raw_display = pd.DataFrame(list(cursor))
82
+ raw_display = raw_display[['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
83
+ dict_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
84
+ st.write("converting names")
85
+ for col in dict_columns:
86
+ raw_display[col] = raw_display[col].map(names_dict)
87
+ FD_seed = raw_display.to_numpy()
88
+
89
+ return FD_seed
90
+
91
+ @st.cache_data(ttl = 599)
92
+ def init_FD_Secondary_seed_frames(sharp_split):
93
+
94
+ collection = db['FD_NFL_Secondary_name_map']
95
+ cursor = collection.find()
96
+ raw_data = pd.DataFrame(list(cursor))
97
+ names_dict = dict(zip(raw_data['key'], raw_data['value']))
98
+
99
+ collection = db["FD_NFL_Secondary_seed_frame"]
100
+ cursor = collection.find().limit(sharp_split)
101
+
102
+ raw_display = pd.DataFrame(list(cursor))
103
+ raw_display = raw_display[['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']]
104
+ dict_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST']
105
+ st.write("converting names")
106
+ for col in dict_columns:
107
+ raw_display[col] = raw_display[col].map(names_dict)
108
+ FD_seed = raw_display.to_numpy()
109
+
110
+ return FD_seed
111
+
112
+ @st.cache_data(ttl = 599)
113
+ def init_baselines(slate_var):
114
+ collection = db["DK_NFL_ROO"]
115
+ cursor = collection.find()
116
+
117
+ raw_display = pd.DataFrame(list(cursor))
118
+ raw_display = raw_display[raw_display['slate'] == slate_var]
119
+ raw_display = raw_display[raw_display['version'] == 'overall']
120
+ dk_raw = raw_display[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%',
121
+ 'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX', 'version', 'slate', 'timestamp', 'player_ID', 'site']]
122
+ dk_raw['STDev'] = (dk_raw['Ceiling'] - dk_raw['Floor']) / 4
123
+
124
+ collection = db["FD_NFL_ROO"]
125
+ cursor = collection.find()
126
+
127
+ raw_display = pd.DataFrame(list(cursor))
128
+ raw_display = raw_display[raw_display['slate'] == slate_var]
129
+ raw_display = raw_display[raw_display['version'] == 'overall']
130
+ fd_raw = raw_display[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%',
131
+ 'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX', 'version', 'slate', 'timestamp', 'player_ID', 'site']]
132
+ fd_raw['STDev'] = (fd_raw['Ceiling'] - fd_raw['Floor']) / 4
133
+
134
+ return dk_raw, fd_raw
135
+
136
+ @st.cache_data
137
+ def convert_df(array):
138
+ array = pd.DataFrame(array, columns=column_names)
139
+ return array.to_csv().encode('utf-8')
140
+
141
+ @st.cache_data
142
+ def calculate_DK_value_frequencies(np_array):
143
+ unique, counts = np.unique(np_array[:, :9], return_counts=True)
144
+ frequencies = counts / len(np_array) # Normalize by the number of rows
145
+ combined_array = np.column_stack((unique, frequencies))
146
+ return combined_array
147
+
148
+ @st.cache_data
149
+ def calculate_FD_value_frequencies(np_array):
150
+ unique, counts = np.unique(np_array[:, :9], return_counts=True)
151
+ frequencies = counts / len(np_array) # Normalize by the number of rows
152
+ combined_array = np.column_stack((unique, frequencies))
153
+ return combined_array
154
+
155
+ @st.cache_data
156
+ def sim_contest(Sim_size, seed_frame, maps_dict, Contest_Size):
157
+ SimVar = 1
158
+ Sim_Winners = []
159
+ fp_array = seed_frame.copy()
160
+ # Pre-vectorize functions
161
+ vec_projection_map = np.vectorize(maps_dict['Projection_map'].__getitem__)
162
+ vec_stdev_map = np.vectorize(maps_dict['STDev_map'].__getitem__)
163
+
164
+ st.write('Simulating contest on frames')
165
+
166
+ while SimVar <= Sim_size:
167
+ fp_random = fp_array[np.random.choice(fp_array.shape[0], Contest_Size)]
168
+
169
+ sample_arrays1 = np.c_[
170
+ fp_random,
171
+ np.sum(np.random.normal(
172
+ loc=vec_projection_map(fp_random[:, :-7]),
173
+ scale=vec_stdev_map(fp_random[:, :-7])),
174
+ axis=1)
175
+ ]
176
+
177
+ sample_arrays = sample_arrays1
178
+
179
+ final_array = sample_arrays[sample_arrays[:, 10].argsort()[::-1]]
180
+ best_lineup = final_array[final_array[:, -1].argsort(kind='stable')[::-1][:1]]
181
+ Sim_Winners.append(best_lineup)
182
+ SimVar += 1
183
+
184
+ return Sim_Winners
185
+
186
+ tab1, tab2 = st.tabs(['Contest Sims', 'Data Export'])
187
+ with tab2:
188
+ col1, col2 = st.columns([1, 7])
189
+ with col1:
190
+ if st.button("Load/Reset Data", key='reset1'):
191
+ st.cache_data.clear()
192
+ for key in st.session_state.keys():
193
+ del st.session_state[key]
194
+ DK_seed = init_DK_seed_frames(10000)
195
+ FD_seed = init_FD_seed_frames(10000)
196
+ dk_raw, fd_raw = init_baselines('Main Slate')
197
+ dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_ID))
198
+ fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_ID))
199
+
200
+ slate_var1 = st.radio("Which data are you loading?", ('Main Slate', 'Secondary Slate'))
201
+ site_var1 = st.radio("What site are you working with?", ('Draftkings', 'Fanduel'))
202
+ sharp_split_var = st.number_input("How many lineups do you want?", value=10000, max_value=500000, min_value=10000, step=10000)
203
+
204
+ if site_var1 == 'Draftkings':
205
+
206
+ team_var1 = st.radio("Do you want a frame with specific teams?", ('Full Slate', 'Specific Teams'), key='team_var1')
207
+ if team_var1 == 'Specific Teams':
208
+ dk_raw, fd_raw = init_baselines('Main Slate')
209
+ team_var2 = st.multiselect('Which teams do you want?', options = dk_raw['Team'].unique())
210
+ elif team_var1 == 'Full Slate':
211
+ dk_raw, fd_raw = init_baselines('Main Slate')
212
+ team_var2 = dk_raw.Team.values.tolist()
213
+
214
+ stack_var1 = st.radio("Do you want a frame with specific stack sizes?", ('Full Slate', 'Specific Stack Sizes'), key='stack_var1')
215
+ if stack_var1 == 'Specific Stack Sizes':
216
+ stack_var2 = st.multiselect('Which stack sizes do you want?', options = [5, 4, 3, 2, 1, 0])
217
+ elif stack_var1 == 'Full Slate':
218
+ stack_var2 = [5, 4, 3, 2, 1, 0]
219
+
220
+ elif site_var1 == 'Fanduel':
221
+
222
+ team_var1 = st.radio("Do you want a frame with specific teams?", ('Full Slate', 'Specific Teams'), key='team_var1')
223
+ if team_var1 == 'Specific Teams':
224
+ dk_raw, fd_raw = init_baselines('Main Slate')
225
+ team_var2 = st.multiselect('Which teams do you want?', options = fd_raw['Team'].unique())
226
+ elif team_var1 == 'Full Slate':
227
+ dk_raw, fd_raw = init_baselines('Main Slate')
228
+ team_var2 = fd_raw.Team.values.tolist()
229
+
230
+ stack_var1 = st.radio("Do you want a frame with specific stack sizes?", ('Full Slate', 'Specific Stack Sizes'), key='stack_var1')
231
+ if stack_var1 == 'Specific Stack Sizes':
232
+ stack_var2 = st.multiselect('Which stack sizes do you want?', options = [5, 4, 3, 2, 1, 0])
233
+ elif stack_var1 == 'Full Slate':
234
+ stack_var2 = [5, 4, 3, 2, 1, 0]
235
+
236
+
237
+ if st.button("Prepare data export", key='data_export'):
238
+ if 'working_seed' in st.session_state:
239
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 11], team_var2)]
240
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 12], stack_var2)]
241
+ elif 'working_seed' not in st.session_state:
242
+ if site_var1 == 'Draftkings':
243
+ if slate_var1 == 'Main Slate':
244
+ st.session_state.working_seed = init_DK_seed_frames(sharp_split_var)
245
+ dk_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_ID))
246
+ elif slate_var1 == 'Secondary Slate':
247
+ st.session_state.working_seed = init_DK_Secondary_seed_frames(sharp_split_var)
248
+ dk_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_ID))
249
+
250
+ raw_baselines = dk_raw
251
+ column_names = dk_columns
252
+
253
+ elif site_var1 == 'Fanduel':
254
+ if slate_var1 == 'Main Slate':
255
+ st.session_state.working_seed = init_FD_seed_frames(sharp_split_var)
256
+ fd_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_ID))
257
+ elif slate_var1 == 'Secondary Slate':
258
+ st.session_state.working_seed = init_FD_Secondary_seed_frames(sharp_split_var)
259
+ fd_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_ID))
260
+
261
+ raw_baselines = fd_raw
262
+ column_names = fd_columns
263
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 11], team_var2)]
264
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 12], stack_var2)]
265
+ data_export = st.session_state.working_seed.copy()
266
+ for col in range(9):
267
+ data_export[:, col] = np.array([dk_id_dict.get(x, x) for x in data_export[:, col]])
268
+ st.download_button(
269
+ label="Export optimals set",
270
+ data=convert_df(data_export),
271
+ file_name='NFL_optimals_export.csv',
272
+ mime='text/csv',
273
+ )
274
+
275
+ with col2:
276
+ if st.button("Load Data", key='load_data'):
277
+ if site_var1 == 'Draftkings':
278
+ if 'working_seed' in st.session_state:
279
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 11], team_var2)]
280
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 12], stack_var2)]
281
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:1000], columns=column_names)
282
+ elif 'working_seed' not in st.session_state:
283
+ if slate_var1 == 'Main Slate':
284
+ st.session_state.working_seed = init_DK_seed_frames(sharp_split_var)
285
+ dk_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_ID))
286
+ dk_raw, fd_raw = init_baselines('Main Slate')
287
+
288
+ elif slate_var1 == 'Secondary Slate':
289
+ st.session_state.working_seed = init_DK_Secondary_seed_frames(sharp_split_var)
290
+ dk_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_ID))
291
+ dk_raw, fd_raw = init_baselines('Secondary Slate')
292
+
293
+ raw_baselines = dk_raw
294
+ column_names = dk_columns
295
+
296
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 11], team_var2)]
297
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 12], stack_var2)]
298
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:1000], columns=column_names)
299
+
300
+ elif site_var1 == 'Fanduel':
301
+ if 'working_seed' in st.session_state:
302
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 11], team_var2)]
303
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 12], stack_var2)]
304
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:1000], columns=column_names)
305
+ elif 'working_seed' not in st.session_state:
306
+ if slate_var1 == 'Main Slate':
307
+ st.session_state.working_seed = init_FD_seed_frames(sharp_split_var)
308
+ fd_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_ID))
309
+ dk_raw, fd_raw = init_baselines('Main Slate')
310
+ elif slate_var1 == 'Secondary Slate':
311
+ st.session_state.working_seed = init_FD_Secondary_seed_frames(sharp_split_var)
312
+ fd_id_dict = dict(zip(st.session_state.working_seed.Player, st.session_state.working_seed.player_ID))
313
+ dk_raw, fd_raw = init_baselines('Secondary Slate')
314
+
315
+ raw_baselines = fd_raw
316
+ column_names = fd_columns
317
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 11], team_var2)]
318
+ st.session_state.working_seed = st.session_state.working_seed[np.isin(st.session_state.working_seed[:, 12], stack_var2)]
319
+ st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:1000], columns=column_names)
320
+
321
+ with st.container():
322
+ if 'data_export_display' in st.session_state:
323
+ st.dataframe(st.session_state.data_export_display.style.format(freq_format, precision=2), use_container_width = True)
324
+
325
+ with tab1:
326
+ col1, col2 = st.columns([1, 7])
327
+ with col1:
328
+ if st.button("Load/Reset Data", key='reset2'):
329
+ st.cache_data.clear()
330
+ for key in st.session_state.keys():
331
+ del st.session_state[key]
332
+ DK_seed = init_DK_seed_frames(10000)
333
+ FD_seed = init_FD_seed_frames(10000)
334
+ dk_raw, fd_raw = init_baselines('Main Slate')
335
+ dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_ID))
336
+ fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_ID))
337
+
338
+ sim_slate_var1 = st.radio("Which data are you loading?", ('Main Slate', 'Secondary Slate'), key='sim_slate_var1')
339
+ sim_site_var1 = st.radio("What site are you working with?", ('Draftkings', 'Fanduel'), key='sim_site_var1')
340
+
341
+ contest_var1 = st.selectbox("What contest size are you simulating?", ('Small', 'Medium', 'Large', 'Custom'))
342
+ if contest_var1 == 'Small':
343
+ Contest_Size = 1000
344
+ elif contest_var1 == 'Medium':
345
+ Contest_Size = 5000
346
+ elif contest_var1 == 'Large':
347
+ Contest_Size = 10000
348
+ elif contest_var1 == 'Custom':
349
+ Contest_Size = st.number_input("Insert contest size", value=100, placeholder="Type a number under 10,000...")
350
+ strength_var1 = st.selectbox("How sharp is the field in the contest?", ('Very', 'Above Average', 'Average', 'Below Average', 'Not Very'))
351
+ if strength_var1 == 'Not Very':
352
+ sharp_split = 500000
353
+ elif strength_var1 == 'Below Average':
354
+ sharp_split = 250000
355
+ elif strength_var1 == 'Average':
356
+ sharp_split = 100000
357
+ elif strength_var1 == 'Above Average':
358
+ sharp_split = 50000
359
+ elif strength_var1 == 'Very':
360
+ sharp_split = 10000
361
+
362
+
363
+ with col2:
364
+ if st.button("Run Contest Sim"):
365
+ if 'working_seed' in st.session_state:
366
+ st.session_state.maps_dict = {
367
+ 'Projection_map':dict(zip(raw_baselines.Player,raw_baselines.Median)),
368
+ 'Salary_map':dict(zip(raw_baselines.Player,raw_baselines.Salary)),
369
+ 'Pos_map':dict(zip(raw_baselines.Player,raw_baselines.Position)),
370
+ 'Own_map':dict(zip(raw_baselines.Player,raw_baselines['Own'])),
371
+ 'Team_map':dict(zip(raw_baselines.Player,raw_baselines.Team)),
372
+ 'STDev_map':dict(zip(raw_baselines.Player,raw_baselines.STDev))
373
+ }
374
+
375
+ Sim_Winners = sim_contest(1000, st.session_state.working_seed, st.session_state.maps_dict, Contest_Size)
376
+ Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners))
377
+
378
+ # Initial setup
379
+ Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners), columns=column_names + ['Fantasy'])
380
+ Sim_Winner_Frame['GPP_Proj'] = (Sim_Winner_Frame['proj'] + Sim_Winner_Frame['Fantasy']) / 2
381
+ 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)
382
+ Sim_Winner_Frame = Sim_Winner_Frame.assign(win_count=Sim_Winner_Frame['unique_id'].map(Sim_Winner_Frame['unique_id'].value_counts()))
383
+
384
+ # Type Casting
385
+ type_cast_dict = {'salary': int, 'proj': np.float16, 'Fantasy': np.float16, 'GPP_Proj': np.float32, 'Own': np.float32}
386
+ Sim_Winner_Frame = Sim_Winner_Frame.astype(type_cast_dict)
387
+
388
+ # Sorting
389
+ 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)
390
+ st.session_state.Sim_Winner_Frame.drop(columns='unique_id', inplace=True)
391
+
392
+ # Data Copying
393
+ st.session_state.Sim_Winner_Export = Sim_Winner_Frame.copy()
394
+
395
+ # Data Copying
396
+ st.session_state.Sim_Winner_Display = Sim_Winner_Frame.copy()
397
+
398
+ else:
399
+ if sim_site_var1 == 'Draftkings':
400
+ if sim_slate_var1 == 'Main Slate':
401
+ st.session_state.working_seed = init_DK_seed_frames(sharp_split)
402
+ dk_raw, fd_raw = init_baselines('Main Slate')
403
+ dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_ID))
404
+ elif sim_slate_var1 == 'Secondary Slate':
405
+ st.session_state.working_seed = init_DK_Secondary_seed_frames(sharp_split)
406
+ dk_raw, fd_raw = init_baselines('Secondary Slate')
407
+ dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_ID))
408
+
409
+ raw_baselines = dk_raw
410
+ column_names = dk_columns
411
+ elif sim_site_var1 == 'Fanduel':
412
+ if sim_slate_var1 == 'Main Slate':
413
+ st.session_state.working_seed = init_FD_seed_frames(sharp_split)
414
+ dk_raw, fd_raw = init_baselines('Main Slate')
415
+ fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_ID))
416
+ elif sim_slate_var1 == 'Secondary Slate':
417
+ st.session_state.working_seed = init_FD_Secondary_seed_frames(sharp_split)
418
+ dk_raw, fd_raw = init_baselines('Secondary Slate')
419
+ fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_ID))
420
+
421
+ raw_baselines = fd_raw
422
+ column_names = fd_columns
423
+ st.session_state.maps_dict = {
424
+ 'Projection_map':dict(zip(raw_baselines.Player,raw_baselines.Median)),
425
+ 'Salary_map':dict(zip(raw_baselines.Player,raw_baselines.Salary)),
426
+ 'Pos_map':dict(zip(raw_baselines.Player,raw_baselines.Position)),
427
+ 'Own_map':dict(zip(raw_baselines.Player,raw_baselines['Own'])),
428
+ 'Team_map':dict(zip(raw_baselines.Player,raw_baselines.Team)),
429
+ 'STDev_map':dict(zip(raw_baselines.Player,raw_baselines.STDev))
430
+ }
431
+
432
+ Sim_Winners = sim_contest(1000, st.session_state.working_seed, st.session_state.maps_dict, Contest_Size)
433
+ Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners))
434
+
435
+ #st.table(Sim_Winner_Frame)
436
+
437
+ # Initial setup
438
+ Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners), columns=column_names + ['Fantasy'])
439
+ Sim_Winner_Frame['GPP_Proj'] = (Sim_Winner_Frame['proj'] + Sim_Winner_Frame['Fantasy']) / 2
440
+ 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)
441
+ Sim_Winner_Frame = Sim_Winner_Frame.assign(win_count=Sim_Winner_Frame['unique_id'].map(Sim_Winner_Frame['unique_id'].value_counts()))
442
+
443
+ # Type Casting
444
+ type_cast_dict = {'salary': int, 'proj': np.float16, 'Fantasy': np.float16, 'GPP_Proj': np.float32, 'Own': np.float32}
445
+ Sim_Winner_Frame = Sim_Winner_Frame.astype(type_cast_dict)
446
+
447
+ # Sorting
448
+ 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)
449
+ st.session_state.Sim_Winner_Frame.drop(columns='unique_id', inplace=True)
450
+
451
+ # Data Copying
452
+ st.session_state.Sim_Winner_Export = Sim_Winner_Frame.copy()
453
+ if sim_site_var1 == 'Draftkings':
454
+ for col in st.session_state.Sim_Winner_Export.iloc[:, 0:9].columns:
455
+ st.session_state.Sim_Winner_Export[col] = st.session_state.Sim_Winner_Export[col].map(dk_id_dict)
456
+ elif sim_site_var1 == 'Fanduel':
457
+ for col in st.session_state.Sim_Winner_Export.iloc[:, 0:9].columns:
458
+ st.session_state.Sim_Winner_Export[col] = st.session_state.Sim_Winner_Export[col].map(fd_id_dict)
459
+
460
+ # Data Copying
461
+ st.session_state.Sim_Winner_Display = Sim_Winner_Frame.copy()
462
+ st.session_state.freq_copy = st.session_state.Sim_Winner_Display
463
+
464
+ if sim_site_var1 == 'Draftkings':
465
+ freq_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,0:9].values, return_counts=True)),
466
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
467
+ elif sim_site_var1 == 'Fanduel':
468
+ freq_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,0:9].values, return_counts=True)),
469
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
470
+ freq_working['Freq'] = freq_working['Freq'].astype(int)
471
+ freq_working['Position'] = freq_working['Player'].map(st.session_state.maps_dict['Pos_map'])
472
+ freq_working['Salary'] = freq_working['Player'].map(st.session_state.maps_dict['Salary_map'])
473
+ freq_working['Proj Own'] = freq_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
474
+ freq_working['Exposure'] = freq_working['Freq']/(1000)
475
+ freq_working['Edge'] = freq_working['Exposure'] - freq_working['Proj Own']
476
+ freq_working['Team'] = freq_working['Player'].map(st.session_state.maps_dict['Team_map'])
477
+ st.session_state.player_freq = freq_working.copy()
478
+
479
+ if sim_site_var1 == 'Draftkings':
480
+ qb_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,0:1].values, return_counts=True)),
481
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
482
+ elif sim_site_var1 == 'Fanduel':
483
+ qb_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,0:1].values, return_counts=True)),
484
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
485
+ qb_working['Freq'] = qb_working['Freq'].astype(int)
486
+ qb_working['Position'] = qb_working['Player'].map(st.session_state.maps_dict['Pos_map'])
487
+ qb_working['Salary'] = qb_working['Player'].map(st.session_state.maps_dict['Salary_map'])
488
+ qb_working['Proj Own'] = qb_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
489
+ qb_working['Exposure'] = qb_working['Freq']/(1000)
490
+ qb_working['Edge'] = qb_working['Exposure'] - qb_working['Proj Own']
491
+ qb_working['Team'] = qb_working['Player'].map(st.session_state.maps_dict['Team_map'])
492
+ st.session_state.qb_freq = qb_working.copy()
493
+
494
+ if sim_site_var1 == 'Draftkings':
495
+ rbwrte_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,1:7].values, return_counts=True)),
496
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
497
+ elif sim_site_var1 == 'Fanduel':
498
+ rbwrte_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,1:7].values, return_counts=True)),
499
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
500
+ rbwrte_working['Freq'] = rbwrte_working['Freq'].astype(int)
501
+ rbwrte_working['Position'] = rbwrte_working['Player'].map(st.session_state.maps_dict['Pos_map'])
502
+ rbwrte_working['Salary'] = rbwrte_working['Player'].map(st.session_state.maps_dict['Salary_map'])
503
+ rbwrte_working['Proj Own'] = rbwrte_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
504
+ rbwrte_working['Exposure'] = rbwrte_working['Freq']/(1000)
505
+ rbwrte_working['Edge'] = rbwrte_working['Exposure'] - rbwrte_working['Proj Own']
506
+ rbwrte_working['Team'] = rbwrte_working['Player'].map(st.session_state.maps_dict['Team_map'])
507
+ st.session_state.rbwrte_freq = rbwrte_working.copy()
508
+
509
+ if sim_site_var1 == 'Draftkings':
510
+ rb_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,1:3].values, return_counts=True)),
511
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
512
+ elif sim_site_var1 == 'Fanduel':
513
+ rb_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,1:3].values, return_counts=True)),
514
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
515
+ rb_working['Freq'] = rb_working['Freq'].astype(int)
516
+ rb_working['Position'] = rb_working['Player'].map(st.session_state.maps_dict['Pos_map'])
517
+ rb_working['Salary'] = rb_working['Player'].map(st.session_state.maps_dict['Salary_map'])
518
+ rb_working['Proj Own'] = rb_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
519
+ rb_working['Exposure'] = rb_working['Freq']/(1000)
520
+ rb_working['Edge'] = rb_working['Exposure'] - rb_working['Proj Own']
521
+ rb_working['Team'] = rb_working['Player'].map(st.session_state.maps_dict['Team_map'])
522
+ st.session_state.rb_freq = rb_working.copy()
523
+
524
+ if sim_site_var1 == 'Draftkings':
525
+ wr_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,3:6].values, return_counts=True)),
526
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
527
+ elif sim_site_var1 == 'Fanduel':
528
+ wr_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,3:6].values, return_counts=True)),
529
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
530
+ wr_working['Freq'] = wr_working['Freq'].astype(int)
531
+ wr_working['Position'] = wr_working['Player'].map(st.session_state.maps_dict['Pos_map'])
532
+ wr_working['Salary'] = wr_working['Player'].map(st.session_state.maps_dict['Salary_map'])
533
+ wr_working['Proj Own'] = wr_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
534
+ wr_working['Exposure'] = wr_working['Freq']/(1000)
535
+ wr_working['Edge'] = wr_working['Exposure'] - wr_working['Proj Own']
536
+ wr_working['Team'] = wr_working['Player'].map(st.session_state.maps_dict['Team_map'])
537
+ st.session_state.wr_freq = wr_working.copy()
538
+
539
+ if sim_site_var1 == 'Draftkings':
540
+ te_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,6:7].values, return_counts=True)),
541
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
542
+ elif sim_site_var1 == 'Fanduel':
543
+ te_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,6:7].values, return_counts=True)),
544
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
545
+ te_working['Freq'] = te_working['Freq'].astype(int)
546
+ te_working['Position'] = te_working['Player'].map(st.session_state.maps_dict['Pos_map'])
547
+ te_working['Salary'] = te_working['Player'].map(st.session_state.maps_dict['Salary_map'])
548
+ te_working['Proj Own'] = te_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
549
+ te_working['Exposure'] = te_working['Freq']/(1000)
550
+ te_working['Edge'] = te_working['Exposure'] - te_working['Proj Own']
551
+ te_working['Team'] = te_working['Player'].map(st.session_state.maps_dict['Team_map'])
552
+ st.session_state.te_freq = te_working.copy()
553
+
554
+ if sim_site_var1 == 'Draftkings':
555
+ flex_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,7:8].values, return_counts=True)),
556
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
557
+ elif sim_site_var1 == 'Fanduel':
558
+ flex_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,7:8].values, return_counts=True)),
559
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
560
+ flex_working['Freq'] = flex_working['Freq'].astype(int)
561
+ flex_working['Position'] = flex_working['Player'].map(st.session_state.maps_dict['Pos_map'])
562
+ flex_working['Salary'] = flex_working['Player'].map(st.session_state.maps_dict['Salary_map'])
563
+ flex_working['Proj Own'] = flex_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
564
+ flex_working['Exposure'] = flex_working['Freq']/(1000)
565
+ flex_working['Edge'] = flex_working['Exposure'] - flex_working['Proj Own']
566
+ flex_working['Team'] = flex_working['Player'].map(st.session_state.maps_dict['Team_map'])
567
+ st.session_state.flex_freq = flex_working.copy()
568
+
569
+ if sim_site_var1 == 'Draftkings':
570
+ dst_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,8:9].values, return_counts=True)),
571
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
572
+ elif sim_site_var1 == 'Fanduel':
573
+ dst_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,8:9].values, return_counts=True)),
574
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
575
+ dst_working['Freq'] = dst_working['Freq'].astype(int)
576
+ dst_working['Position'] = dst_working['Player'].map(st.session_state.maps_dict['Pos_map'])
577
+ dst_working['Salary'] = dst_working['Player'].map(st.session_state.maps_dict['Salary_map'])
578
+ dst_working['Proj Own'] = dst_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
579
+ dst_working['Exposure'] = dst_working['Freq']/(1000)
580
+ dst_working['Edge'] = dst_working['Exposure'] - dst_working['Proj Own']
581
+ dst_working['Team'] = dst_working['Player'].map(st.session_state.maps_dict['Team_map'])
582
+ st.session_state.dst_freq = dst_working.copy()
583
+
584
+ if sim_site_var1 == 'Draftkings':
585
+ team_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,11:12].values, return_counts=True)),
586
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
587
+ elif sim_site_var1 == 'Fanduel':
588
+ team_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,11:12].values, return_counts=True)),
589
+ columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
590
+ team_working['Freq'] = team_working['Freq'].astype(int)
591
+ team_working['Exposure'] = team_working['Freq']/(1000)
592
+ st.session_state.team_freq = team_working.copy()
593
+
594
+ with st.container():
595
+ if st.button("Reset Sim", key='reset_sim'):
596
+ for key in st.session_state.keys():
597
+ del st.session_state[key]
598
+ if 'player_freq' in st.session_state:
599
+ player_split_var2 = st.radio("Are you wanting to isolate any lineups with specific players?", ('Full Players', 'Specific Players'), key='player_split_var2')
600
+ if player_split_var2 == 'Specific Players':
601
+ find_var2 = st.multiselect('Which players must be included in the lineups?', options = st.session_state.player_freq['Player'].unique())
602
+ elif player_split_var2 == 'Full Players':
603
+ find_var2 = st.session_state.player_freq.Player.values.tolist()
604
+
605
+ if player_split_var2 == 'Specific Players':
606
+ 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)]
607
+ if player_split_var2 == 'Full Players':
608
+ st.session_state.Sim_Winner_Display = st.session_state.Sim_Winner_Frame
609
+ if 'Sim_Winner_Display' in st.session_state:
610
+ st.dataframe(st.session_state.Sim_Winner_Display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
611
+ if 'Sim_Winner_Export' in st.session_state:
612
+ st.download_button(
613
+ label="Export Full Frame",
614
+ data=st.session_state.Sim_Winner_Export.to_csv().encode('utf-8'),
615
+ file_name='MLB_consim_export.csv',
616
+ mime='text/csv',
617
+ )
618
+ tab1, tab2 = st.tabs(['Winning Frame Statistics', 'Flex Exposure Statistics'])
619
+
620
+ with tab1:
621
+ if 'Sim_Winner_Display' in st.session_state:
622
+ # Create a new dataframe with summary statistics
623
+ summary_df = pd.DataFrame({
624
+ 'Metric': ['Min', 'Average', 'Max', 'STDdev'],
625
+ 'Salary': [
626
+ st.session_state.Sim_Winner_Display['salary'].min(),
627
+ st.session_state.Sim_Winner_Display['salary'].mean(),
628
+ st.session_state.Sim_Winner_Display['salary'].max(),
629
+ st.session_state.Sim_Winner_Display['salary'].std()
630
+ ],
631
+ 'Proj': [
632
+ st.session_state.Sim_Winner_Display['proj'].min(),
633
+ st.session_state.Sim_Winner_Display['proj'].mean(),
634
+ st.session_state.Sim_Winner_Display['proj'].max(),
635
+ st.session_state.Sim_Winner_Display['proj'].std()
636
+ ],
637
+ 'Own': [
638
+ st.session_state.Sim_Winner_Display['Own'].min(),
639
+ st.session_state.Sim_Winner_Display['Own'].mean(),
640
+ st.session_state.Sim_Winner_Display['Own'].max(),
641
+ st.session_state.Sim_Winner_Display['Own'].std()
642
+ ],
643
+ 'Fantasy': [
644
+ st.session_state.Sim_Winner_Display['Fantasy'].min(),
645
+ st.session_state.Sim_Winner_Display['Fantasy'].mean(),
646
+ st.session_state.Sim_Winner_Display['Fantasy'].max(),
647
+ st.session_state.Sim_Winner_Display['Fantasy'].std()
648
+ ],
649
+ 'GPP_Proj': [
650
+ st.session_state.Sim_Winner_Display['GPP_Proj'].min(),
651
+ st.session_state.Sim_Winner_Display['GPP_Proj'].mean(),
652
+ st.session_state.Sim_Winner_Display['GPP_Proj'].max(),
653
+ st.session_state.Sim_Winner_Display['GPP_Proj'].std()
654
+ ]
655
+ })
656
+
657
+ # Set the index of the summary dataframe as the "Metric" column
658
+ summary_df = summary_df.set_index('Metric')
659
+
660
+ # Display the summary dataframe
661
+ st.subheader("Winning Frame Statistics")
662
+ st.dataframe(summary_df.style.format({
663
+ 'Salary': '{:.2f}',
664
+ 'Proj': '{:.2f}',
665
+ 'Fantasy': '{:.2f}',
666
+ 'GPP_Proj': '{:.2f}'
667
+ }).background_gradient(cmap='RdYlGn', axis=0, subset=['Salary', 'Proj', 'Own', 'Fantasy', 'GPP_Proj']), use_container_width=True)
668
 
669
+ with tab2:
670
+ if 'Sim_Winner_Display' in st.session_state:
671
+ # Apply position mapping to FLEX column
672
+ flex_positions = st.session_state.freq_copy['FLEX'].map(st.session_state.maps_dict['Pos_map'])
673
+
674
+ # Count occurrences of each position in FLEX
675
+ flex_counts = flex_positions.value_counts()
676
+
677
+ # Calculate average statistics for each FLEX position
678
+ flex_stats = st.session_state.freq_copy.groupby(flex_positions).agg({
679
+ 'proj': 'mean',
680
+ 'Own': 'mean',
681
+ 'Fantasy': 'mean',
682
+ 'GPP_Proj': 'mean'
683
+ })
684
+
685
+ # Combine counts and average statistics
686
+ flex_summary = pd.concat([flex_counts, flex_stats], axis=1)
687
+ flex_summary.columns = ['Count', 'Avg Proj', 'Avg Own', 'Avg Fantasy', 'Avg GPP_Proj']
688
+ flex_summary = flex_summary.reset_index()
689
+ flex_summary.columns = ['Position', 'Count', 'Avg Proj', 'Avg Own', 'Avg Fantasy', 'Avg GPP_Proj']
690
+
691
+ # Display the summary dataframe
692
+ st.subheader("FLEX Position Statistics")
693
+ st.dataframe(flex_summary.style.format({
694
+ 'Count': '{:.0f}',
695
+ 'Avg Proj': '{:.2f}',
696
+ 'Avg Fantasy': '{:.2f}',
697
+ 'Avg GPP_Proj': '{:.2f}'
698
+ }).background_gradient(cmap='RdYlGn', axis=0, subset=['Count', 'Avg Proj', 'Avg Own', 'Avg Fantasy', 'Avg GPP_Proj']), use_container_width=True)
699
+
700
+ else:
701
+ st.write("Simulation data or position mapping not available.")
702
+ with st.container():
703
+ tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8, tab9 = st.tabs(['Overall Exposures', 'QB Exposures', 'RB-WR-TE Exposures', 'RB Exposures', 'WR Exposures', 'TE Exposures', 'FLEX Exposures', 'DST Exposures', 'Team Exposures'])
704
+ with tab1:
705
+ if 'player_freq' in st.session_state:
706
+
707
+ 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)
708
+ st.download_button(
709
+ label="Export Exposures",
710
+ data=st.session_state.player_freq.to_csv().encode('utf-8'),
711
+ file_name='player_freq_export.csv',
712
+ mime='text/csv',
713
+ key='overall'
714
+ )
715
+ with tab2:
716
+ if 'qb_freq' in st.session_state:
717
+
718
+ st.dataframe(st.session_state.qb_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
719
+ st.download_button(
720
+ label="Export Exposures",
721
+ data=st.session_state.qb_freq.to_csv().encode('utf-8'),
722
+ file_name='qb_freq.csv',
723
+ mime='text/csv',
724
+ key='qb'
725
+ )
726
+ with tab3:
727
+ if 'rbwrte_freq' in st.session_state:
728
+
729
+ st.dataframe(st.session_state.rbwrte_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
730
+ st.download_button(
731
+ label="Export Exposures",
732
+ data=st.session_state.rbwrte_freq.to_csv().encode('utf-8'),
733
+ file_name='rbwrte_freq.csv',
734
+ mime='text/csv',
735
+ key='rbwrte'
736
+ )
737
+ with tab4:
738
+ if 'rb_freq' in st.session_state:
739
+
740
+ st.dataframe(st.session_state.rb_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
741
+ st.download_button(
742
+ label="Export Exposures",
743
+ data=st.session_state.rb_freq.to_csv().encode('utf-8'),
744
+ file_name='rb_freq.csv',
745
+ mime='text/csv',
746
+ key='rb'
747
+ )
748
+ with tab5:
749
+ if 'wr_freq' in st.session_state:
750
+
751
+ st.dataframe(st.session_state.wr_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
752
+ st.download_button(
753
+ label="Export Exposures",
754
+ data=st.session_state.wr_freq.to_csv().encode('utf-8'),
755
+ file_name='wr_freq.csv',
756
+ mime='text/csv',
757
+ key='wr'
758
+ )
759
+ with tab6:
760
+ if 'te_freq' in st.session_state:
761
+
762
+ st.dataframe(st.session_state.te_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
763
+ st.download_button(
764
+ label="Export Exposures",
765
+ data=st.session_state.te_freq.to_csv().encode('utf-8'),
766
+ file_name='te_freq.csv',
767
+ mime='text/csv',
768
+ key='te'
769
+ )
770
+ with tab7:
771
+ if 'flex_freq' in st.session_state:
772
+
773
+ st.dataframe(st.session_state.flex_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
774
+ st.download_button(
775
+ label="Export Exposures",
776
+ data=st.session_state.flex_freq.to_csv().encode('utf-8'),
777
+ file_name='flex_freq.csv',
778
+ mime='text/csv',
779
+ key='flex'
780
+ )
781
+ with tab8:
782
+ if 'dst_freq' in st.session_state:
783
+
784
+ st.dataframe(st.session_state.dst_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
785
+ st.download_button(
786
+ label="Export Exposures",
787
+ data=st.session_state.dst_freq.to_csv().encode('utf-8'),
788
+ file_name='dst_freq.csv',
789
+ mime='text/csv',
790
+ key='dst'
791
+ )
792
+ with tab9:
793
+ if 'team_freq' in st.session_state:
794
+
795
+ 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)
796
+ st.download_button(
797
+ label="Export Exposures",
798
+ data=st.session_state.team_freq.to_csv().encode('utf-8'),
799
+ file_name='team_freq.csv',
800
+ mime='text/csv',
801
+ key='team'
802
+ )