James McCool
commited on
Commit
·
42c2829
1
Parent(s):
63139f0
Enhance predict_dupes function by adding max_salary parameter for improved salary handling and adjusting sample range slider step in app.py for better user experience.
Browse files- app.py +2 -2
- global_func/predict_dupes.py +106 -247
app.py
CHANGED
@@ -1093,7 +1093,7 @@ with tab2:
|
|
1093 |
st.session_state['working_frame']['median'] = st.session_state['working_frame']['median'].astype('float32')
|
1094 |
st.session_state['working_frame']['salary'] = st.session_state['working_frame']['salary'].astype('uint16')
|
1095 |
|
1096 |
-
st.session_state['base_frame'] = predict_dupes(st.session_state['working_frame'], st.session_state['map_dict'], site_var, type_var, Contest_Size, strength_var, sport_var)
|
1097 |
st.session_state['working_frame'] = st.session_state['base_frame'].copy()
|
1098 |
# st.session_state['highest_owned_teams'] = st.session_state['projections_df'][~st.session_state['projections_df']['position'].isin(['P', 'SP'])].groupby('team')['ownership'].sum().sort_values(ascending=False).head(3).index.tolist()
|
1099 |
# st.session_state['highest_owned_pitchers'] = st.session_state['projections_df'][st.session_state['projections_df']['position'].isin(['P', 'SP'])]['player_names'].sort_values(by='ownership', ascending=False).head(3).tolist()
|
@@ -1441,7 +1441,7 @@ with tab2:
|
|
1441 |
with st.form(key='Stratification'):
|
1442 |
sorting_choice = st.selectbox("Stat Choice", options=['median', 'Own', 'Weighted Own', 'Geomean', 'Lineup Edge', 'Finish_percentile', 'Diversity'], index=0)
|
1443 |
lineup_target = st.number_input("Lineups to produce", value=150, min_value=1, step=1)
|
1444 |
-
strat_sample = st.slider("Sample range", value=[0.0, 100.0], min_value=0.0, max_value=100.0, step=0
|
1445 |
submitted_col, export_col = st.columns(2)
|
1446 |
st.info("Portfolio Button applies to your overall Portfolio, Export button applies to your Custom Export")
|
1447 |
with submitted_col:
|
|
|
1093 |
st.session_state['working_frame']['median'] = st.session_state['working_frame']['median'].astype('float32')
|
1094 |
st.session_state['working_frame']['salary'] = st.session_state['working_frame']['salary'].astype('uint16')
|
1095 |
|
1096 |
+
st.session_state['base_frame'] = predict_dupes(st.session_state['working_frame'], st.session_state['map_dict'], site_var, type_var, Contest_Size, strength_var, sport_var, salary_max)
|
1097 |
st.session_state['working_frame'] = st.session_state['base_frame'].copy()
|
1098 |
# st.session_state['highest_owned_teams'] = st.session_state['projections_df'][~st.session_state['projections_df']['position'].isin(['P', 'SP'])].groupby('team')['ownership'].sum().sort_values(ascending=False).head(3).index.tolist()
|
1099 |
# st.session_state['highest_owned_pitchers'] = st.session_state['projections_df'][st.session_state['projections_df']['position'].isin(['P', 'SP'])]['player_names'].sort_values(by='ownership', ascending=False).head(3).tolist()
|
|
|
1441 |
with st.form(key='Stratification'):
|
1442 |
sorting_choice = st.selectbox("Stat Choice", options=['median', 'Own', 'Weighted Own', 'Geomean', 'Lineup Edge', 'Finish_percentile', 'Diversity'], index=0)
|
1443 |
lineup_target = st.number_input("Lineups to produce", value=150, min_value=1, step=1)
|
1444 |
+
strat_sample = st.slider("Sample range", value=[0.0, 100.0], min_value=0.0, max_value=100.0, step=1.0)
|
1445 |
submitted_col, export_col = st.columns(2)
|
1446 |
st.info("Portfolio Button applies to your overall Portfolio, Export button applies to your Custom Export")
|
1447 |
with submitted_col:
|
global_func/predict_dupes.py
CHANGED
@@ -4,7 +4,6 @@ import pandas as pd
|
|
4 |
import time
|
5 |
import math
|
6 |
from difflib import SequenceMatcher
|
7 |
-
import heapq
|
8 |
|
9 |
def calculate_weighted_ownership_vectorized(ownership_array):
|
10 |
"""
|
@@ -106,182 +105,8 @@ def calculate_player_similarity_score_vectorized(portfolio, player_columns):
|
|
106 |
|
107 |
return similarity_scores
|
108 |
|
109 |
-
def predict_dupes_vectorized(portfolio, maps_dict, site_var, type_var, Contest_Size, strength_var, sport_var):
|
110 |
-
"""
|
111 |
-
Vectorized version of predict_dupes using NumPy arrays for better performance.
|
112 |
-
"""
|
113 |
-
# Set multipliers based on strength
|
114 |
-
if strength_var == 'Weak':
|
115 |
-
dupes_multiplier = 0.75
|
116 |
-
percentile_multiplier = 0.90
|
117 |
-
elif strength_var == 'Average':
|
118 |
-
dupes_multiplier = 1.00
|
119 |
-
percentile_multiplier = 1.00
|
120 |
-
elif strength_var == 'Sharp':
|
121 |
-
dupes_multiplier = 1.25
|
122 |
-
percentile_multiplier = 1.10
|
123 |
-
|
124 |
-
max_ownership = max(maps_dict['own_map'].values()) / 100
|
125 |
-
average_ownership = np.mean(list(maps_dict['own_map'].values())) / 100
|
126 |
-
|
127 |
-
# Convert portfolio to NumPy arrays for faster operations
|
128 |
-
portfolio_values = portfolio.values
|
129 |
-
n_rows = len(portfolio)
|
130 |
-
|
131 |
-
# Pre-allocate arrays for ownership data
|
132 |
-
if site_var == 'Fanduel':
|
133 |
-
if type_var == 'Showdown':
|
134 |
-
num_players = 5
|
135 |
-
salary_cap = 60000
|
136 |
-
player_cols = list(range(5)) # First 5 columns are players
|
137 |
-
elif type_var == 'Classic':
|
138 |
-
if sport_var == 'WNBA':
|
139 |
-
num_players = len([col for col in portfolio.columns if col not in ['salary', 'median', 'Own']])
|
140 |
-
salary_cap = 40000
|
141 |
-
player_cols = list(range(num_players))
|
142 |
-
else:
|
143 |
-
num_players = len([col for col in portfolio.columns if col not in ['salary', 'median', 'Own']])
|
144 |
-
salary_cap = 60000
|
145 |
-
player_cols = list(range(num_players))
|
146 |
-
elif site_var == 'Draftkings':
|
147 |
-
if type_var == 'Showdown':
|
148 |
-
num_players = 6
|
149 |
-
salary_cap = 50000
|
150 |
-
player_cols = list(range(6))
|
151 |
-
elif type_var == 'Classic':
|
152 |
-
if sport_var == 'CS2':
|
153 |
-
num_players = 6
|
154 |
-
salary_cap = 50000
|
155 |
-
player_cols = list(range(6))
|
156 |
-
elif sport_var == 'LOL':
|
157 |
-
num_players = 7
|
158 |
-
salary_cap = 50000
|
159 |
-
player_cols = list(range(7))
|
160 |
-
else:
|
161 |
-
num_players = len([col for col in portfolio.columns if col not in ['salary', 'median', 'Own']])
|
162 |
-
salary_cap = 50000
|
163 |
-
player_cols = list(range(num_players))
|
164 |
-
|
165 |
-
# Pre-allocate ownership arrays
|
166 |
-
ownership_array = np.zeros((n_rows, num_players), dtype=np.float32)
|
167 |
-
ownership_rank_array = np.zeros((n_rows, num_players), dtype=np.float32)
|
168 |
-
|
169 |
-
# Vectorized ownership mapping
|
170 |
-
for i, col_idx in enumerate(player_cols):
|
171 |
-
if i == 0 and type_var == 'Showdown': # Captain
|
172 |
-
ownership_array[:, i] = np.vectorize(lambda x: maps_dict['cpt_own_map'].get(x, 0))(portfolio_values[:, col_idx]) / 100
|
173 |
-
ownership_rank_array[:, i] = np.vectorize(lambda x: maps_dict['cpt_own_map'].get(x, 0))(portfolio_values[:, col_idx])
|
174 |
-
else: # Flex players
|
175 |
-
ownership_array[:, i] = np.vectorize(lambda x: maps_dict['own_map'].get(x, 0))(portfolio_values[:, col_idx]) / 100
|
176 |
-
ownership_rank_array[:, i] = np.vectorize(lambda x: maps_dict['own_map'].get(x, 0))(portfolio_values[:, col_idx])
|
177 |
-
|
178 |
-
# Calculate ranks for flex players (excluding captain)
|
179 |
-
if type_var == 'Showdown':
|
180 |
-
flex_ownerships = ownership_rank_array[:, 1:].flatten()
|
181 |
-
flex_rank = pd.Series(flex_ownerships).rank(pct=True).values.reshape(n_rows, -1)
|
182 |
-
ownership_rank_array[:, 1:] = flex_rank
|
183 |
-
|
184 |
-
# Convert to percentile ranks
|
185 |
-
ownership_rank_array = ownership_rank_array / 100
|
186 |
-
|
187 |
-
# Vectorized calculations
|
188 |
-
own_product = np.prod(ownership_array, axis=1)
|
189 |
-
own_average = (portfolio_values[:, portfolio.columns.get_loc('Own')].max() * 0.33) / 100
|
190 |
-
own_sum = np.sum(ownership_array, axis=1)
|
191 |
-
avg_own_rank = np.mean(ownership_rank_array, axis=1)
|
192 |
-
|
193 |
-
# Calculate dupes formula vectorized
|
194 |
-
salary_col = portfolio.columns.get_loc('salary')
|
195 |
-
own_col = portfolio.columns.get_loc('Own')
|
196 |
-
|
197 |
-
dupes_calc = (own_product * avg_own_rank) * Contest_Size + \
|
198 |
-
((portfolio_values[:, salary_col] - (salary_cap - portfolio_values[:, own_col])) / 100) - \
|
199 |
-
((salary_cap - portfolio_values[:, salary_col]) / 100)
|
200 |
-
|
201 |
-
dupes_calc *= dupes_multiplier
|
202 |
-
|
203 |
-
# Round and handle negative values
|
204 |
-
dupes = np.where(np.round(dupes_calc, 0) <= 0, 0, np.round(dupes_calc, 0) - 1)
|
205 |
-
|
206 |
-
# Calculate own_ratio vectorized
|
207 |
-
max_own_mask = np.any(ownership_array == max_ownership, axis=1)
|
208 |
-
own_ratio = np.where(max_own_mask,
|
209 |
-
own_sum / own_average,
|
210 |
-
(own_sum - max_ownership) / own_average)
|
211 |
-
|
212 |
-
# Calculate Finish_percentile vectorized
|
213 |
-
percentile_cut_scalar = portfolio_values[:, portfolio.columns.get_loc('median')].max()
|
214 |
-
|
215 |
-
if type_var == 'Classic':
|
216 |
-
own_ratio_nerf = 2 if sport_var == 'CS2' or sport_var == 'LOL' else 1.5
|
217 |
-
elif type_var == 'Showdown':
|
218 |
-
own_ratio_nerf = 1.5
|
219 |
-
|
220 |
-
median_col = portfolio.columns.get_loc('median')
|
221 |
-
finish_percentile = (own_ratio - own_ratio_nerf) / ((5 * (portfolio_values[:, median_col] / percentile_cut_scalar)) / 3)
|
222 |
-
finish_percentile = np.where(finish_percentile < 0.0005, 0.0005, finish_percentile / 2)
|
223 |
-
|
224 |
-
# Calculate other metrics vectorized
|
225 |
-
ref_proj = portfolio_values[:, median_col].max()
|
226 |
-
max_proj = ref_proj + 10
|
227 |
-
min_proj = ref_proj - 10
|
228 |
-
avg_ref = (max_proj + min_proj) / 2
|
229 |
-
|
230 |
-
win_percent = (((portfolio_values[:, median_col] / avg_ref) - (0.1 + ((ref_proj - portfolio_values[:, median_col])/100))) / (Contest_Size / 1000)) / 10
|
231 |
-
max_allowed_win = (1 / Contest_Size) * 5
|
232 |
-
win_percent = win_percent / win_percent.max() * max_allowed_win
|
233 |
-
|
234 |
-
finish_percentile = finish_percentile + 0.005 + (0.005 * (Contest_Size / 10000))
|
235 |
-
finish_percentile *= percentile_multiplier
|
236 |
-
win_percent *= (1 - finish_percentile)
|
237 |
-
|
238 |
-
# Calculate low ownership count vectorized
|
239 |
-
low_own_count = np.sum(ownership_array < 0.10, axis=1)
|
240 |
-
finish_percentile = np.where(low_own_count <= 0,
|
241 |
-
finish_percentile,
|
242 |
-
finish_percentile / low_own_count)
|
243 |
-
|
244 |
-
# Calculate Lineup Edge vectorized
|
245 |
-
lineup_edge = win_percent * ((0.5 - finish_percentile) * (Contest_Size / 2.5))
|
246 |
-
lineup_edge = np.where(dupes > 0, lineup_edge / (dupes + 1), lineup_edge)
|
247 |
-
lineup_edge = lineup_edge - lineup_edge.mean()
|
248 |
-
|
249 |
-
# Calculate Weighted Own vectorized
|
250 |
-
weighted_own = calculate_weighted_ownership_vectorized(ownership_array)
|
251 |
-
|
252 |
-
# Calculate Geomean vectorized
|
253 |
-
geomean = np.power(np.prod(ownership_array * 100, axis=1), 1 / num_players)
|
254 |
-
|
255 |
-
# Calculate Diversity vectorized
|
256 |
-
diversity = calculate_player_similarity_score_vectorized(portfolio, player_cols)
|
257 |
-
|
258 |
-
# Create result DataFrame with optimized data types
|
259 |
-
result_data = {
|
260 |
-
'Dupes': dupes.astype('uint16'),
|
261 |
-
'median': portfolio_values[:, portfolio.columns.get_loc('median')].astype('float32'),
|
262 |
-
'Own': portfolio_values[:, portfolio.columns.get_loc('Own')].astype('float32'),
|
263 |
-
'salary': portfolio_values[:, portfolio.columns.get_loc('salary')].astype('uint16'),
|
264 |
-
'Finish_percentile': finish_percentile.astype('float32'),
|
265 |
-
'Win%': win_percent.astype('float32'),
|
266 |
-
'Lineup Edge': lineup_edge.astype('float32'),
|
267 |
-
'Weighted Own': weighted_own.astype('float32'),
|
268 |
-
'Geomean': geomean.astype('float32'),
|
269 |
-
'Diversity': diversity.astype('float32')
|
270 |
-
}
|
271 |
-
|
272 |
-
# Add Size column if it exists
|
273 |
-
if 'Size' in portfolio.columns:
|
274 |
-
result_data['Size'] = portfolio_values[:, portfolio.columns.get_loc('Size')].astype('uint16')
|
275 |
-
|
276 |
-
# Add player columns back
|
277 |
-
for i, col_name in enumerate(portfolio.columns[:num_players]):
|
278 |
-
result_data[col_name] = portfolio_values[:, i]
|
279 |
-
|
280 |
-
return pd.DataFrame(result_data)
|
281 |
-
|
282 |
# Keep the original function for backward compatibility
|
283 |
-
def predict_dupes(portfolio, maps_dict, site_var, type_var, Contest_Size, strength_var, sport_var):
|
284 |
-
player_columns = [col for col in portfolio.columns[:5] if col not in ['salary', 'median', 'Own']]
|
285 |
if strength_var == 'Weak':
|
286 |
dupes_multiplier = .75
|
287 |
percentile_multiplier = .90
|
@@ -292,22 +117,22 @@ def predict_dupes(portfolio, maps_dict, site_var, type_var, Contest_Size, streng
|
|
292 |
dupes_multiplier = 1.25
|
293 |
percentile_multiplier = 1.10
|
294 |
max_ownership = max(maps_dict['own_map'].values()) / 100
|
295 |
-
top_x_ownership_keys = heapq.nlargest(len(player_columns), maps_dict['own_map'], key=maps_dict['own_map'].get)
|
296 |
average_ownership = np.mean(list(maps_dict['own_map'].values())) / 100
|
297 |
if site_var == 'Fanduel':
|
298 |
if type_var == 'Showdown':
|
299 |
dup_count_columns = ['CPT_Own_percent_rank', 'FLEX1_Own_percent_rank', 'FLEX2_Own_percent_rank', 'FLEX3_Own_percent_rank', 'FLEX4_Own_percent_rank']
|
300 |
own_columns = ['CPT_Own', 'FLEX1_Own', 'FLEX2_Own', 'FLEX3_Own', 'FLEX4_Own']
|
301 |
-
calc_columns = ['own_product', 'own_average', 'own_sum', 'avg_own_rank', '
|
302 |
# Get the original player columns (first 5 columns excluding salary, median, Own)
|
303 |
player_columns = [col for col in portfolio.columns[:5] if col not in ['salary', 'median', 'Own']]
|
304 |
|
305 |
flex_ownerships = pd.concat([
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
|
|
311 |
flex_rank = flex_ownerships.rank(pct=True)
|
312 |
|
313 |
# Assign ranks back to individual columns using the same rank scale
|
@@ -325,31 +150,31 @@ def predict_dupes(portfolio, maps_dict, site_var, type_var, Contest_Size, streng
|
|
325 |
portfolio['FLEX4_Own'] = portfolio.iloc[:,4].map(maps_dict['own_map']).astype('float32') / 100
|
326 |
portfolio['FLEX5_Own'] = portfolio.iloc[:,5].map(maps_dict['own_map']).astype('float32') / 100
|
327 |
|
328 |
-
portfolio['own_product'] = (portfolio[own_columns].product(axis=1))
|
329 |
portfolio['own_average'] = (portfolio['Own'].max() * .33) / 100
|
330 |
portfolio['own_sum'] = portfolio[own_columns].sum(axis=1)
|
331 |
portfolio['avg_own_rank'] = portfolio[dup_count_columns].mean(axis=1)
|
332 |
-
portfolio['own_rank_percentile'] = portfolio['Own'].rank(pct=True)
|
333 |
-
portfolio['top_x_presence'] = portfolio[player_columns].apply(
|
334 |
-
lambda row: sum(1 for player in row if player in top_x_ownership_keys), axis=1
|
335 |
-
)
|
336 |
|
337 |
# Calculate dupes formula
|
338 |
-
portfolio['dupes_calc'] = (portfolio['
|
339 |
-
portfolio['dupes_calc'] = portfolio['dupes_calc'] * dupes_multiplier * (portfolio['Own'] / (
|
340 |
|
341 |
# Round and handle negative values
|
342 |
portfolio['Dupes'] = np.where(
|
343 |
-
|
|
|
|
|
|
|
|
|
|
|
344 |
0,
|
345 |
-
np.round(
|
346 |
)
|
347 |
-
|
348 |
elif type_var == 'Classic':
|
349 |
num_players = len([col for col in portfolio.columns if col not in ['salary', 'median', 'Own']])
|
350 |
dup_count_columns = [f'player_{i}_percent_rank' for i in range(1, num_players + 1)]
|
351 |
own_columns = [f'player_{i}_own' for i in range(1, num_players + 1)]
|
352 |
-
calc_columns = ['own_product', 'own_average', 'own_sum', 'avg_own_rank', '
|
353 |
# Get the original player columns (first num_players columns excluding salary, median, Own)
|
354 |
player_columns = [col for col in portfolio.columns[:num_players] if col not in ['salary', 'median', 'Own']]
|
355 |
|
@@ -357,22 +182,23 @@ def predict_dupes(portfolio, maps_dict, site_var, type_var, Contest_Size, streng
|
|
357 |
portfolio[f'player_{i}_percent_rank'] = portfolio.iloc[:,i-1].map(maps_dict['own_percent_rank'])
|
358 |
portfolio[f'player_{i}_own'] = portfolio.iloc[:,i-1].map(maps_dict['own_map']).astype('float32') / 100
|
359 |
|
360 |
-
portfolio['own_product'] = (portfolio[own_columns].product(axis=1))
|
361 |
portfolio['own_average'] = (portfolio['Own'].max() * .33) / 100
|
362 |
portfolio['own_sum'] = portfolio[own_columns].sum(axis=1)
|
363 |
portfolio['avg_own_rank'] = portfolio[dup_count_columns].mean(axis=1)
|
364 |
-
portfolio['own_rank_percentile'] = portfolio['Own'].rank(pct=True)
|
365 |
-
portfolio['top_x_presence'] = portfolio[player_columns].apply(
|
366 |
-
lambda row: sum(1 for player in row if player in top_x_ownership_keys), axis=1
|
367 |
-
)
|
368 |
|
369 |
-
portfolio['dupes_calc'] = (portfolio['
|
370 |
-
portfolio['dupes_calc'] = portfolio['dupes_calc'] * dupes_multiplier * (portfolio['Own'] / (
|
371 |
# Round and handle negative values
|
372 |
portfolio['Dupes'] = np.where(
|
373 |
-
|
|
|
|
|
|
|
|
|
|
|
374 |
0,
|
375 |
-
np.round(
|
376 |
)
|
377 |
|
378 |
elif site_var == 'Draftkings':
|
@@ -383,7 +209,7 @@ def predict_dupes(portfolio, maps_dict, site_var, type_var, Contest_Size, streng
|
|
383 |
else:
|
384 |
dup_count_columns = ['CPT_Own_percent_rank', 'FLEX1_Own_percent_rank', 'FLEX2_Own_percent_rank', 'FLEX3_Own_percent_rank', 'FLEX4_Own_percent_rank', 'FLEX5_Own_percent_rank']
|
385 |
own_columns = ['CPT_Own', 'FLEX1_Own', 'FLEX2_Own', 'FLEX3_Own', 'FLEX4_Own', 'FLEX5_Own']
|
386 |
-
calc_columns = ['own_product', 'own_average', 'own_sum', 'avg_own_rank', '
|
387 |
# Get the original player columns (first 6 columns excluding salary, median, Own)
|
388 |
player_columns = [col for col in portfolio.columns[:6] if col not in ['salary', 'median', 'Own']]
|
389 |
if sport_var == 'GOLF':
|
@@ -435,30 +261,31 @@ def predict_dupes(portfolio, maps_dict, site_var, type_var, Contest_Size, streng
|
|
435 |
portfolio['FLEX4_Own'] = portfolio.iloc[:,4].map(maps_dict['own_map']).astype('float32') / 100
|
436 |
portfolio['FLEX5_Own'] = portfolio.iloc[:,5].map(maps_dict['own_map']).astype('float32') / 100
|
437 |
|
438 |
-
portfolio['own_product'] = (portfolio[own_columns].product(axis=1))
|
439 |
portfolio['own_average'] = (portfolio['Own'].max() * .33) / 100
|
440 |
portfolio['own_sum'] = portfolio[own_columns].sum(axis=1)
|
441 |
portfolio['avg_own_rank'] = portfolio[dup_count_columns].mean(axis=1)
|
442 |
-
portfolio['own_rank_percentile'] = portfolio['Own'].rank(pct=True)
|
443 |
-
portfolio['top_x_presence'] = portfolio[player_columns].apply(
|
444 |
-
lambda row: sum(1 for player in row if player in top_x_ownership_keys), axis=1
|
445 |
-
)
|
446 |
|
447 |
# Calculate dupes formula
|
448 |
-
portfolio['dupes_calc'] = (portfolio['
|
449 |
-
portfolio['dupes_calc'] = portfolio['dupes_calc'] * dupes_multiplier * (portfolio['Own'] / (
|
450 |
|
451 |
# Round and handle negative values
|
452 |
portfolio['Dupes'] = np.where(
|
453 |
-
|
|
|
|
|
|
|
|
|
|
|
454 |
0,
|
455 |
-
np.round(
|
456 |
)
|
457 |
elif type_var == 'Classic':
|
458 |
if sport_var == 'CS2':
|
459 |
dup_count_columns = ['CPT_Own_percent_rank', 'FLEX1_Own_percent_rank', 'FLEX2_Own_percent_rank', 'FLEX3_Own_percent_rank', 'FLEX4_Own_percent_rank', 'FLEX5_Own_percent_rank']
|
460 |
own_columns = ['CPT_Own', 'FLEX1_Own', 'FLEX2_Own', 'FLEX3_Own', 'FLEX4_Own', 'FLEX5_Own']
|
461 |
-
calc_columns = ['own_product', 'own_average', 'own_sum', 'avg_own_rank', '
|
462 |
# Get the original player columns (first 6 columns excluding salary, median, Own)
|
463 |
player_columns = [col for col in portfolio.columns[:6] if col not in ['salary', 'median', 'Own']]
|
464 |
|
@@ -486,29 +313,30 @@ def predict_dupes(portfolio, maps_dict, site_var, type_var, Contest_Size, streng
|
|
486 |
portfolio['FLEX4_Own'] = portfolio.iloc[:,4].map(maps_dict['own_map']).astype('float32') / 100
|
487 |
portfolio['FLEX5_Own'] = portfolio.iloc[:,5].map(maps_dict['own_map']).astype('float32') / 100
|
488 |
|
489 |
-
portfolio['own_product'] = (portfolio[own_columns].product(axis=1))
|
490 |
portfolio['own_average'] = (portfolio['Own'].max() * .33) / 100
|
491 |
portfolio['own_sum'] = portfolio[own_columns].sum(axis=1)
|
492 |
portfolio['avg_own_rank'] = portfolio[dup_count_columns].mean(axis=1)
|
493 |
-
portfolio['own_rank_percentile'] = portfolio['Own'].rank(pct=True)
|
494 |
-
portfolio['top_x_presence'] = portfolio[player_columns].apply(
|
495 |
-
lambda row: sum(1 for player in row if player in top_x_ownership_keys), axis=1
|
496 |
-
)
|
497 |
|
498 |
# Calculate dupes formula
|
499 |
-
portfolio['dupes_calc'] = (portfolio['
|
500 |
-
portfolio['dupes_calc'] = portfolio['dupes_calc'] * dupes_multiplier * (portfolio['Own'] / (
|
501 |
|
502 |
# Round and handle negative values
|
503 |
portfolio['Dupes'] = np.where(
|
504 |
-
|
|
|
|
|
|
|
|
|
|
|
505 |
0,
|
506 |
-
np.round(
|
507 |
)
|
508 |
if sport_var == 'LOL':
|
509 |
dup_count_columns = ['CPT_Own_percent_rank', 'TOP_Own_percent_rank', 'JNG_Own_percent_rank', 'MID_Own_percent_rank', 'ADC_Own_percent_rank', 'SUP_Own_percent_rank', 'Team_Own_percent_rank']
|
510 |
own_columns = ['CPT_Own', 'TOP_Own', 'JNG_Own', 'MID_Own', 'ADC_Own', 'SUP_Own', 'Team_Own']
|
511 |
-
calc_columns = ['own_product', 'own_average', 'own_sum', 'avg_own_rank', '
|
512 |
# Get the original player columns (first 6 columns excluding salary, median, Own)
|
513 |
player_columns = [col for col in portfolio.columns[:7] if col not in ['salary', 'median', 'Own']]
|
514 |
|
@@ -539,30 +367,31 @@ def predict_dupes(portfolio, maps_dict, site_var, type_var, Contest_Size, streng
|
|
539 |
portfolio['SUP_Own'] = portfolio.iloc[:,5].map(maps_dict['own_map']).astype('float32') / 100
|
540 |
portfolio['Team_Own'] = portfolio.iloc[:,6].map(maps_dict['own_map']).astype('float32') / 100
|
541 |
|
542 |
-
portfolio['own_product'] = (portfolio[own_columns].product(axis=1))
|
543 |
portfolio['own_average'] = (portfolio['Own'].max() * .33) / 100
|
544 |
portfolio['own_sum'] = portfolio[own_columns].sum(axis=1)
|
545 |
portfolio['avg_own_rank'] = portfolio[dup_count_columns].mean(axis=1)
|
546 |
-
|
547 |
-
portfolio['top_x_presence'] = portfolio[player_columns].apply(
|
548 |
-
lambda row: sum(1 for player in row if player in top_x_ownership_keys), axis=1
|
549 |
-
)
|
550 |
-
|
551 |
# Calculate dupes formula
|
552 |
-
portfolio['dupes_calc'] = (portfolio['
|
553 |
-
portfolio['dupes_calc'] = portfolio['dupes_calc'] * dupes_multiplier * (portfolio['Own'] / (
|
554 |
|
555 |
# Round and handle negative values
|
556 |
portfolio['Dupes'] = np.where(
|
557 |
-
|
|
|
|
|
|
|
|
|
|
|
558 |
0,
|
559 |
-
np.round(
|
560 |
)
|
561 |
-
elif sport_var
|
562 |
num_players = len([col for col in portfolio.columns if col not in ['salary', 'median', 'Own']])
|
563 |
dup_count_columns = [f'player_{i}_percent_rank' for i in range(1, num_players + 1)]
|
564 |
own_columns = [f'player_{i}_own' for i in range(1, num_players + 1)]
|
565 |
-
calc_columns = ['own_product', 'own_average', 'own_sum', 'avg_own_rank', '
|
566 |
# Get the original player columns (first num_players columns excluding salary, median, Own)
|
567 |
player_columns = [col for col in portfolio.columns[:num_players] if col not in ['salary', 'median', 'Own']]
|
568 |
|
@@ -570,23 +399,55 @@ def predict_dupes(portfolio, maps_dict, site_var, type_var, Contest_Size, streng
|
|
570 |
portfolio[f'player_{i}_percent_rank'] = portfolio.iloc[:,i-1].map(maps_dict['own_percent_rank'])
|
571 |
portfolio[f'player_{i}_own'] = portfolio.iloc[:,i-1].map(maps_dict['own_map']).astype('float32') / 100
|
572 |
|
573 |
-
portfolio['own_product'] = (portfolio[own_columns].product(axis=1))
|
574 |
portfolio['own_average'] = (portfolio['Own'].max() * .33) / 100
|
575 |
portfolio['own_sum'] = portfolio[own_columns].sum(axis=1)
|
576 |
portfolio['avg_own_rank'] = portfolio[dup_count_columns].mean(axis=1)
|
577 |
-
|
578 |
-
portfolio['
|
579 |
-
|
|
|
|
|
|
|
|
|
|
|
580 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
581 |
|
582 |
-
|
583 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
584 |
# Round and handle negative values
|
585 |
portfolio['Dupes'] = np.where(
|
586 |
-
|
|
|
|
|
|
|
|
|
|
|
587 |
0,
|
588 |
-
np.round(
|
589 |
)
|
|
|
590 |
|
591 |
portfolio['Dupes'] = np.round(portfolio['Dupes'], 0)
|
592 |
portfolio['own_ratio'] = np.where(
|
@@ -594,7 +455,7 @@ def predict_dupes(portfolio, maps_dict, site_var, type_var, Contest_Size, streng
|
|
594 |
portfolio['own_sum'] / portfolio['own_average'],
|
595 |
(portfolio['own_sum'] - max_ownership) / portfolio['own_average']
|
596 |
)
|
597 |
-
percentile_cut_scalar = portfolio['median'].max()
|
598 |
if type_var == 'Classic':
|
599 |
if sport_var == 'CS2':
|
600 |
own_ratio_nerf = 2
|
@@ -633,8 +494,6 @@ def predict_dupes(portfolio, maps_dict, site_var, type_var, Contest_Size, streng
|
|
633 |
|
634 |
# Calculate similarity score based on actual player selection
|
635 |
portfolio['Diversity'] = calculate_player_similarity_score_vectorized(portfolio, player_columns)
|
636 |
-
|
637 |
-
st.table(portfolio.sort_values(by='Dupes', ascending=False).head(10))
|
638 |
|
639 |
portfolio = portfolio.drop(columns=dup_count_columns)
|
640 |
portfolio = portfolio.drop(columns=own_columns)
|
|
|
4 |
import time
|
5 |
import math
|
6 |
from difflib import SequenceMatcher
|
|
|
7 |
|
8 |
def calculate_weighted_ownership_vectorized(ownership_array):
|
9 |
"""
|
|
|
105 |
|
106 |
return similarity_scores
|
107 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
# Keep the original function for backward compatibility
|
109 |
+
def predict_dupes(portfolio, maps_dict, site_var, type_var, Contest_Size, strength_var, sport_var, max_salary):
|
|
|
110 |
if strength_var == 'Weak':
|
111 |
dupes_multiplier = .75
|
112 |
percentile_multiplier = .90
|
|
|
117 |
dupes_multiplier = 1.25
|
118 |
percentile_multiplier = 1.10
|
119 |
max_ownership = max(maps_dict['own_map'].values()) / 100
|
|
|
120 |
average_ownership = np.mean(list(maps_dict['own_map'].values())) / 100
|
121 |
if site_var == 'Fanduel':
|
122 |
if type_var == 'Showdown':
|
123 |
dup_count_columns = ['CPT_Own_percent_rank', 'FLEX1_Own_percent_rank', 'FLEX2_Own_percent_rank', 'FLEX3_Own_percent_rank', 'FLEX4_Own_percent_rank']
|
124 |
own_columns = ['CPT_Own', 'FLEX1_Own', 'FLEX2_Own', 'FLEX3_Own', 'FLEX4_Own']
|
125 |
+
calc_columns = ['own_product', 'own_average', 'own_sum', 'avg_own_rank', 'dupes_calc', 'low_own_count', 'own_ratio', 'Ref_Proj', 'Max_Proj', 'Min_Proj', 'Avg_Ref', 'own_ratio']
|
126 |
# Get the original player columns (first 5 columns excluding salary, median, Own)
|
127 |
player_columns = [col for col in portfolio.columns[:5] if col not in ['salary', 'median', 'Own']]
|
128 |
|
129 |
flex_ownerships = pd.concat([
|
130 |
+
portfolio.iloc[:,1].map(maps_dict['own_map']),
|
131 |
+
portfolio.iloc[:,2].map(maps_dict['own_map']),
|
132 |
+
portfolio.iloc[:,3].map(maps_dict['own_map']),
|
133 |
+
portfolio.iloc[:,4].map(maps_dict['own_map']),
|
134 |
+
portfolio.iloc[:,5].map(maps_dict['own_map'])
|
135 |
+
])
|
136 |
flex_rank = flex_ownerships.rank(pct=True)
|
137 |
|
138 |
# Assign ranks back to individual columns using the same rank scale
|
|
|
150 |
portfolio['FLEX4_Own'] = portfolio.iloc[:,4].map(maps_dict['own_map']).astype('float32') / 100
|
151 |
portfolio['FLEX5_Own'] = portfolio.iloc[:,5].map(maps_dict['own_map']).astype('float32') / 100
|
152 |
|
153 |
+
portfolio['own_product'] = (portfolio[own_columns].product(axis=1)) * max(Contest_Size / 10000, 1)
|
154 |
portfolio['own_average'] = (portfolio['Own'].max() * .33) / 100
|
155 |
portfolio['own_sum'] = portfolio[own_columns].sum(axis=1)
|
156 |
portfolio['avg_own_rank'] = portfolio[dup_count_columns].mean(axis=1)
|
|
|
|
|
|
|
|
|
157 |
|
158 |
# Calculate dupes formula
|
159 |
+
portfolio['dupes_calc'] = (portfolio['own_product'] * portfolio['avg_own_rank']) * (portfolio['Own'] / 100) * Contest_Size + ((portfolio['salary'] - (max_salary - portfolio['Own'])) / 100) - ((max_salary - portfolio['salary']) / 100)
|
160 |
+
portfolio['dupes_calc'] = portfolio['dupes_calc'] * dupes_multiplier * (portfolio['Own'] / (90 + (Contest_Size / 1000)))
|
161 |
|
162 |
# Round and handle negative values
|
163 |
portfolio['Dupes'] = np.where(
|
164 |
+
portfolio['salary'] == max_salary,
|
165 |
+
portfolio['dupes_calc'] + (portfolio['dupes_calc'] * .10),
|
166 |
+
portfolio['dupes_calc']
|
167 |
+
)
|
168 |
+
portfolio['Dupes'] = np.where(
|
169 |
+
np.round(portfolio['Dupes'], 0) <= 0,
|
170 |
0,
|
171 |
+
np.round(portfolio['Dupes'], 0) - 1
|
172 |
)
|
|
|
173 |
elif type_var == 'Classic':
|
174 |
num_players = len([col for col in portfolio.columns if col not in ['salary', 'median', 'Own']])
|
175 |
dup_count_columns = [f'player_{i}_percent_rank' for i in range(1, num_players + 1)]
|
176 |
own_columns = [f'player_{i}_own' for i in range(1, num_players + 1)]
|
177 |
+
calc_columns = ['own_product', 'own_average', 'own_sum', 'avg_own_rank', 'dupes_calc', 'low_own_count', 'own_ratio', 'Ref_Proj', 'Max_Proj', 'Min_Proj', 'Avg_Ref', 'own_ratio']
|
178 |
# Get the original player columns (first num_players columns excluding salary, median, Own)
|
179 |
player_columns = [col for col in portfolio.columns[:num_players] if col not in ['salary', 'median', 'Own']]
|
180 |
|
|
|
182 |
portfolio[f'player_{i}_percent_rank'] = portfolio.iloc[:,i-1].map(maps_dict['own_percent_rank'])
|
183 |
portfolio[f'player_{i}_own'] = portfolio.iloc[:,i-1].map(maps_dict['own_map']).astype('float32') / 100
|
184 |
|
185 |
+
portfolio['own_product'] = (portfolio[own_columns].product(axis=1)) * max(Contest_Size / 10000, 1)
|
186 |
portfolio['own_average'] = (portfolio['Own'].max() * .33) / 100
|
187 |
portfolio['own_sum'] = portfolio[own_columns].sum(axis=1)
|
188 |
portfolio['avg_own_rank'] = portfolio[dup_count_columns].mean(axis=1)
|
|
|
|
|
|
|
|
|
189 |
|
190 |
+
portfolio['dupes_calc'] = (portfolio['own_product'] * portfolio['avg_own_rank']) * Contest_Size + ((portfolio['salary'] - (max_salary - portfolio['Own'])) / 100) - ((max_salary - portfolio['salary']) / 100)
|
191 |
+
portfolio['dupes_calc'] = portfolio['dupes_calc'] * dupes_multiplier * (portfolio['Own'] / (90 + (Contest_Size / 1000)))
|
192 |
# Round and handle negative values
|
193 |
portfolio['Dupes'] = np.where(
|
194 |
+
portfolio['salary'] == max_salary,
|
195 |
+
portfolio['dupes_calc'] + (portfolio['dupes_calc'] * .10),
|
196 |
+
portfolio['dupes_calc']
|
197 |
+
)
|
198 |
+
portfolio['Dupes'] = np.where(
|
199 |
+
np.round(portfolio['Dupes'], 0) <= 0,
|
200 |
0,
|
201 |
+
np.round(portfolio['Dupes'], 0) - 1
|
202 |
)
|
203 |
|
204 |
elif site_var == 'Draftkings':
|
|
|
209 |
else:
|
210 |
dup_count_columns = ['CPT_Own_percent_rank', 'FLEX1_Own_percent_rank', 'FLEX2_Own_percent_rank', 'FLEX3_Own_percent_rank', 'FLEX4_Own_percent_rank', 'FLEX5_Own_percent_rank']
|
211 |
own_columns = ['CPT_Own', 'FLEX1_Own', 'FLEX2_Own', 'FLEX3_Own', 'FLEX4_Own', 'FLEX5_Own']
|
212 |
+
calc_columns = ['own_product', 'own_average', 'own_sum', 'avg_own_rank', 'dupes_calc', 'low_own_count', 'Ref_Proj', 'Max_Proj', 'Min_Proj', 'Avg_Ref', 'own_ratio']
|
213 |
# Get the original player columns (first 6 columns excluding salary, median, Own)
|
214 |
player_columns = [col for col in portfolio.columns[:6] if col not in ['salary', 'median', 'Own']]
|
215 |
if sport_var == 'GOLF':
|
|
|
261 |
portfolio['FLEX4_Own'] = portfolio.iloc[:,4].map(maps_dict['own_map']).astype('float32') / 100
|
262 |
portfolio['FLEX5_Own'] = portfolio.iloc[:,5].map(maps_dict['own_map']).astype('float32') / 100
|
263 |
|
264 |
+
portfolio['own_product'] = (portfolio[own_columns].product(axis=1)) * max(Contest_Size / 10000, 1)
|
265 |
portfolio['own_average'] = (portfolio['Own'].max() * .33) / 100
|
266 |
portfolio['own_sum'] = portfolio[own_columns].sum(axis=1)
|
267 |
portfolio['avg_own_rank'] = portfolio[dup_count_columns].mean(axis=1)
|
|
|
|
|
|
|
|
|
268 |
|
269 |
# Calculate dupes formula
|
270 |
+
portfolio['dupes_calc'] = (portfolio['own_product'] * portfolio['avg_own_rank']) * Contest_Size + ((portfolio['salary'] - (max_salary - portfolio['Own'])) / 100) - ((max_salary - portfolio['salary']) / 100)
|
271 |
+
portfolio['dupes_calc'] = portfolio['dupes_calc'] * dupes_multiplier * (portfolio['Own'] / (90 + (Contest_Size / 1000)))
|
272 |
|
273 |
# Round and handle negative values
|
274 |
portfolio['Dupes'] = np.where(
|
275 |
+
portfolio['salary'] == max_salary,
|
276 |
+
portfolio['dupes_calc'] + (portfolio['dupes_calc'] * .10),
|
277 |
+
portfolio['dupes_calc']
|
278 |
+
)
|
279 |
+
portfolio['Dupes'] = np.where(
|
280 |
+
np.round(portfolio['Dupes'], 0) <= 0,
|
281 |
0,
|
282 |
+
np.round(portfolio['Dupes'], 0) - 1
|
283 |
)
|
284 |
elif type_var == 'Classic':
|
285 |
if sport_var == 'CS2':
|
286 |
dup_count_columns = ['CPT_Own_percent_rank', 'FLEX1_Own_percent_rank', 'FLEX2_Own_percent_rank', 'FLEX3_Own_percent_rank', 'FLEX4_Own_percent_rank', 'FLEX5_Own_percent_rank']
|
287 |
own_columns = ['CPT_Own', 'FLEX1_Own', 'FLEX2_Own', 'FLEX3_Own', 'FLEX4_Own', 'FLEX5_Own']
|
288 |
+
calc_columns = ['own_product', 'own_average', 'own_sum', 'avg_own_rank', 'dupes_calc', 'low_own_count', 'Ref_Proj', 'Max_Proj', 'Min_Proj', 'Avg_Ref', 'own_ratio']
|
289 |
# Get the original player columns (first 6 columns excluding salary, median, Own)
|
290 |
player_columns = [col for col in portfolio.columns[:6] if col not in ['salary', 'median', 'Own']]
|
291 |
|
|
|
313 |
portfolio['FLEX4_Own'] = portfolio.iloc[:,4].map(maps_dict['own_map']).astype('float32') / 100
|
314 |
portfolio['FLEX5_Own'] = portfolio.iloc[:,5].map(maps_dict['own_map']).astype('float32') / 100
|
315 |
|
316 |
+
portfolio['own_product'] = (portfolio[own_columns].product(axis=1)) * max(Contest_Size / 10000, 1)
|
317 |
portfolio['own_average'] = (portfolio['Own'].max() * .33) / 100
|
318 |
portfolio['own_sum'] = portfolio[own_columns].sum(axis=1)
|
319 |
portfolio['avg_own_rank'] = portfolio[dup_count_columns].mean(axis=1)
|
|
|
|
|
|
|
|
|
320 |
|
321 |
# Calculate dupes formula
|
322 |
+
portfolio['dupes_calc'] = ((portfolio['own_product'] * 10) * portfolio['avg_own_rank']) * Contest_Size + ((portfolio['salary'] - (max_salary - portfolio['Own'])) / 50) - ((max_salary - portfolio['salary']) / 50)
|
323 |
+
portfolio['dupes_calc'] = portfolio['dupes_calc'] * dupes_multiplier * (portfolio['Own'] / (90 + (Contest_Size / 1000)))
|
324 |
|
325 |
# Round and handle negative values
|
326 |
portfolio['Dupes'] = np.where(
|
327 |
+
portfolio['salary'] == max_salary,
|
328 |
+
portfolio['dupes_calc'] + (portfolio['dupes_calc'] * .10),
|
329 |
+
portfolio['dupes_calc']
|
330 |
+
)
|
331 |
+
portfolio['Dupes'] = np.where(
|
332 |
+
np.round(portfolio['Dupes'], 0) <= 0,
|
333 |
0,
|
334 |
+
np.round(portfolio['Dupes'], 0) - 1
|
335 |
)
|
336 |
if sport_var == 'LOL':
|
337 |
dup_count_columns = ['CPT_Own_percent_rank', 'TOP_Own_percent_rank', 'JNG_Own_percent_rank', 'MID_Own_percent_rank', 'ADC_Own_percent_rank', 'SUP_Own_percent_rank', 'Team_Own_percent_rank']
|
338 |
own_columns = ['CPT_Own', 'TOP_Own', 'JNG_Own', 'MID_Own', 'ADC_Own', 'SUP_Own', 'Team_Own']
|
339 |
+
calc_columns = ['own_product', 'own_average', 'own_sum', 'avg_own_rank', 'dupes_calc', 'low_own_count', 'Ref_Proj', 'Max_Proj', 'Min_Proj', 'Avg_Ref', 'own_ratio']
|
340 |
# Get the original player columns (first 6 columns excluding salary, median, Own)
|
341 |
player_columns = [col for col in portfolio.columns[:7] if col not in ['salary', 'median', 'Own']]
|
342 |
|
|
|
367 |
portfolio['SUP_Own'] = portfolio.iloc[:,5].map(maps_dict['own_map']).astype('float32') / 100
|
368 |
portfolio['Team_Own'] = portfolio.iloc[:,6].map(maps_dict['own_map']).astype('float32') / 100
|
369 |
|
370 |
+
portfolio['own_product'] = (portfolio[own_columns].product(axis=1)) * max(Contest_Size / 10000, 1)
|
371 |
portfolio['own_average'] = (portfolio['Own'].max() * .33) / 100
|
372 |
portfolio['own_sum'] = portfolio[own_columns].sum(axis=1)
|
373 |
portfolio['avg_own_rank'] = portfolio[dup_count_columns].mean(axis=1)
|
374 |
+
|
|
|
|
|
|
|
|
|
375 |
# Calculate dupes formula
|
376 |
+
portfolio['dupes_calc'] = ((portfolio['own_product'] * 10) * portfolio['avg_own_rank']) * Contest_Size + ((portfolio['salary'] - (max_salary - portfolio['Own'])) / 50) - ((max_salary - portfolio['salary']) / 50)
|
377 |
+
portfolio['dupes_calc'] = portfolio['dupes_calc'] * dupes_multiplier * (portfolio['Own'] / (90 + (Contest_Size / 1000)))
|
378 |
|
379 |
# Round and handle negative values
|
380 |
portfolio['Dupes'] = np.where(
|
381 |
+
portfolio['salary'] == max_salary,
|
382 |
+
portfolio['dupes_calc'] + (portfolio['dupes_calc'] * .10),
|
383 |
+
portfolio['dupes_calc']
|
384 |
+
)
|
385 |
+
portfolio['Dupes'] = np.where(
|
386 |
+
np.round(portfolio['Dupes'], 0) <= 0,
|
387 |
0,
|
388 |
+
np.round(portfolio['Dupes'], 0) - 1
|
389 |
)
|
390 |
+
elif sport_var == 'GOLF':
|
391 |
num_players = len([col for col in portfolio.columns if col not in ['salary', 'median', 'Own']])
|
392 |
dup_count_columns = [f'player_{i}_percent_rank' for i in range(1, num_players + 1)]
|
393 |
own_columns = [f'player_{i}_own' for i in range(1, num_players + 1)]
|
394 |
+
calc_columns = ['own_product', 'own_average', 'own_sum', 'avg_own_rank', 'dupes_calc', 'low_own_count', 'Ref_Proj', 'Max_Proj', 'Min_Proj', 'Avg_Ref', 'own_ratio']
|
395 |
# Get the original player columns (first num_players columns excluding salary, median, Own)
|
396 |
player_columns = [col for col in portfolio.columns[:num_players] if col not in ['salary', 'median', 'Own']]
|
397 |
|
|
|
399 |
portfolio[f'player_{i}_percent_rank'] = portfolio.iloc[:,i-1].map(maps_dict['own_percent_rank'])
|
400 |
portfolio[f'player_{i}_own'] = portfolio.iloc[:,i-1].map(maps_dict['own_map']).astype('float32') / 100
|
401 |
|
402 |
+
portfolio['own_product'] = (portfolio[own_columns].product(axis=1)) * max(Contest_Size / 10000, 1)
|
403 |
portfolio['own_average'] = (portfolio['Own'].max() * .33) / 100
|
404 |
portfolio['own_sum'] = portfolio[own_columns].sum(axis=1)
|
405 |
portfolio['avg_own_rank'] = portfolio[dup_count_columns].mean(axis=1)
|
406 |
+
|
407 |
+
portfolio['dupes_calc'] = (portfolio['own_product'] * portfolio['avg_own_rank']) * Contest_Size + ((portfolio['salary'] - (max_salary - portfolio['Own'])) / 100) - ((max_salary - portfolio['salary']) / 100)
|
408 |
+
portfolio['dupes_calc'] = portfolio['dupes_calc'] * dupes_multiplier * (portfolio['Own'] / (90 + (Contest_Size / 1000)))
|
409 |
+
# Round and handle negative values
|
410 |
+
portfolio['Dupes'] = np.where(
|
411 |
+
portfolio['salary'] == max_salary,
|
412 |
+
portfolio['dupes_calc'] + (portfolio['dupes_calc'] * .10),
|
413 |
+
portfolio['dupes_calc']
|
414 |
)
|
415 |
+
portfolio['Dupes'] = np.where(
|
416 |
+
np.round(portfolio['Dupes'], 0) <= 0,
|
417 |
+
0,
|
418 |
+
np.round(portfolio['Dupes'], 0) - 1
|
419 |
+
)
|
420 |
+
else:
|
421 |
+
num_players = len([col for col in portfolio.columns if col not in ['salary', 'median', 'Own']])
|
422 |
+
dup_count_columns = [f'player_{i}_percent_rank' for i in range(1, num_players + 1)]
|
423 |
+
own_columns = [f'player_{i}_own' for i in range(1, num_players + 1)]
|
424 |
+
calc_columns = ['own_product', 'own_average', 'own_sum', 'avg_own_rank', 'dupes_calc', 'low_own_count', 'Ref_Proj', 'Max_Proj', 'Min_Proj', 'Avg_Ref', 'own_ratio']
|
425 |
+
# Get the original player columns (first num_players columns excluding salary, median, Own)
|
426 |
+
player_columns = [col for col in portfolio.columns[:num_players] if col not in ['salary', 'median', 'Own']]
|
427 |
|
428 |
+
for i in range(1, num_players + 1):
|
429 |
+
portfolio[f'player_{i}_percent_rank'] = portfolio.iloc[:,i-1].map(maps_dict['own_percent_rank'])
|
430 |
+
portfolio[f'player_{i}_own'] = portfolio.iloc[:,i-1].map(maps_dict['own_map']).astype('float32') / 100
|
431 |
+
|
432 |
+
portfolio['own_product'] = (portfolio[own_columns].product(axis=1)) * max(Contest_Size / 10000, 1)
|
433 |
+
portfolio['own_average'] = (portfolio['Own'].max() * .33) / 100
|
434 |
+
portfolio['own_sum'] = portfolio[own_columns].sum(axis=1)
|
435 |
+
portfolio['avg_own_rank'] = portfolio[dup_count_columns].mean(axis=1)
|
436 |
+
|
437 |
+
portfolio['dupes_calc'] = (portfolio['own_product'] * portfolio['avg_own_rank']) * Contest_Size + ((portfolio['salary'] - (max_salary - portfolio['Own'])) / 100) - ((max_salary - portfolio['salary']) / 100)
|
438 |
+
portfolio['dupes_calc'] = portfolio['dupes_calc'] * dupes_multiplier * (portfolio['Own'] / (90 + (Contest_Size / 1000)))
|
439 |
# Round and handle negative values
|
440 |
portfolio['Dupes'] = np.where(
|
441 |
+
portfolio['salary'] == max_salary,
|
442 |
+
portfolio['dupes_calc'] + (portfolio['dupes_calc'] * .10),
|
443 |
+
portfolio['dupes_calc']
|
444 |
+
)
|
445 |
+
portfolio['Dupes'] = np.where(
|
446 |
+
np.round(portfolio['Dupes'], 0) <= 0,
|
447 |
0,
|
448 |
+
np.round(portfolio['Dupes'], 0) - 1
|
449 |
)
|
450 |
+
|
451 |
|
452 |
portfolio['Dupes'] = np.round(portfolio['Dupes'], 0)
|
453 |
portfolio['own_ratio'] = np.where(
|
|
|
455 |
portfolio['own_sum'] / portfolio['own_average'],
|
456 |
(portfolio['own_sum'] - max_ownership) / portfolio['own_average']
|
457 |
)
|
458 |
+
percentile_cut_scalar = portfolio['median'].max() # Get scalar value
|
459 |
if type_var == 'Classic':
|
460 |
if sport_var == 'CS2':
|
461 |
own_ratio_nerf = 2
|
|
|
494 |
|
495 |
# Calculate similarity score based on actual player selection
|
496 |
portfolio['Diversity'] = calculate_player_similarity_score_vectorized(portfolio, player_columns)
|
|
|
|
|
497 |
|
498 |
portfolio = portfolio.drop(columns=dup_count_columns)
|
499 |
portfolio = portfolio.drop(columns=own_columns)
|