DFS_Portfolio_Manager / global_func /large_field_preset.py
James McCool
Enhance large_field_preset function to improve player exposure tracking by implementing a mechanism to remove high-exposure players across iterations, ensuring lineup integrity and preventing excessive ownership. Adjust logic to check for sufficient lineups before finalizing selections.
73d2fb0
raw
history blame
3.71 kB
import pandas as pd
def large_field_preset(portfolio: pd.DataFrame, lineup_target: int, exclude_cols: list):
for slack_var in range(1, 20):
concat_portfolio = pd.DataFrame(columns=portfolio.columns)
# Define player columns (columns that contain player names)
player_columns = [col for col in portfolio.columns if col not in exclude_cols]
# Track players to remove across iterations
remove_list = []
# Iterate until no high-exposure players are found
max_iterations = 10 # Prevent infinite loops
for iteration in range(max_iterations):
concat_portfolio = pd.DataFrame(columns=portfolio.columns)
for team in portfolio['Stack'].unique():
rows_to_drop = []
working_portfolio = portfolio.copy()
# Remove players from previous iteration if any
if remove_list:
remove_mask = working_portfolio[player_columns].apply(
lambda row: not any(player in list(row) for player in remove_list), axis=1
)
working_portfolio = working_portfolio[remove_mask]
working_portfolio = working_portfolio[working_portfolio['Stack'] == team].sort_values(by='Finish_percentile', ascending = True)
working_portfolio = working_portfolio.reset_index(drop=True)
if len(working_portfolio) == 0:
continue
curr_own_type_max = working_portfolio.loc[0, 'Own'] + (slack_var / 20 * working_portfolio.loc[0, 'Own'])
for i in range(1, len(working_portfolio)):
if working_portfolio.loc[i, 'Own'] > curr_own_type_max:
rows_to_drop.append(i)
else:
curr_own_type_max = working_portfolio.loc[i, 'Own'] + (slack_var / 20 * working_portfolio.loc[i, 'Own'])
working_portfolio = working_portfolio.drop(rows_to_drop).reset_index(drop=True)
concat_portfolio = pd.concat([concat_portfolio, working_portfolio])
# Check player exposure
if len(concat_portfolio) == 0:
break
player_exposure = {}
for col in player_columns:
for player in concat_portfolio[col].unique():
if pd.notna(player): # Skip NaN values
player_mask = concat_portfolio[player_columns].apply(
lambda row: player in list(row), axis=1
)
exposure = player_mask.sum() / len(concat_portfolio)
player_exposure[player] = exposure
# Find players with exposure > 35%
high_exposure_players = [player for player, exposure in player_exposure.items() if exposure > 0.35]
# If no high-exposure players, we're done
if not high_exposure_players:
break
# Add high-exposure players to remove list
remove_list.extend(high_exposure_players)
remove_list = list(set(remove_list)) # Remove duplicates
# Check if we have enough lineups and no high-exposure players
if len(concat_portfolio) >= lineup_target and len(high_exposure_players) == 0:
return concat_portfolio.sort_values(by='Finish_percentile', ascending=True).head(lineup_target)
return concat_portfolio.sort_values(by='Finish_percentile', ascending=True)