import random import numpy as np import math #### Goal is to choose a player and adjust the amount of lineups that have them #### First thing you need to do is find comparable players in the projections, so any player in the projections that is within $500 of the player and within 10% of the projection #### Take that list of players and create a list that can be accessed for random insertion into the portfolio #### Find the player and the amount of rows that contain them and then find an exposure rate which is the percentage of total rows #### Use the exposure target argument and try to replace the player from as many rows as necessary to be at or just under the target #### makes sure to check if the player is eligible for the position before replacing them def check_nba_position_eligibility(column_name, player_positions): """ Check if a player is eligible for a specific NBA column position. Args: column_name (str): The column name (PG, PG1, PG2, SG, SG1, SG2, etc.) player_positions (list): List of positions the player is eligible for Returns: bool: True if player is eligible for the column """ if any(pos in column_name for pos in ['PG', 'SG', 'SF', 'PF', 'C']): # Extract the base position from the column name base_position = next(pos for pos in ['PG', 'SG', 'SF', 'PF', 'C'] if pos in column_name) return base_position in player_positions elif 'G' in column_name: return any(pos in ['PG', 'SG'] for pos in player_positions) elif 'F' in column_name: return any(pos in ['SF', 'PF'] for pos in player_positions) elif 'UTIL' in column_name: return True # UTIL can be any position return False def check_lol_position_eligibility(column_name, player_positions): """ Check if a player is eligible for a specific LOL column position. Args: column_name (str): The column name (TOP, JNG, MID, ADC, SUP, UTIL) player_positions (list): List of positions the player is eligible for Returns: bool: True if player is eligible for the column """ if any(pos in column_name for pos in ['TOP', 'JNG', 'MID', 'ADC', 'SUP', 'Team']): # Extract the base position from the column name base_position = next(pos for pos in ['TOP', 'JNG', 'MID', 'ADC', 'SUP', 'Team'] if pos in column_name) return base_position in player_positions elif 'CPT' in column_name: return any(pos in ['TOP', 'JNG', 'MID', 'ADC', 'SUP'] for pos in player_positions) return False def check_mlb_position_eligibility(column_name, player_positions): """ Check if a player is eligible for a specific MLB column position. Args: column_name (str): The column name (P, SP, RP, C, 1B, 2B, 3B, SS, OF) player_positions (list): List of positions the player is eligible for Returns: bool: True if player is eligible for the column """ if any(pos in column_name for pos in ['P', 'SP', 'RP']): return any(pos in ['P', 'SP', 'RP'] for pos in player_positions) elif any(pos in column_name for pos in ['C', '1B', '2B', '3B', 'SS', 'OF']): return any(pos in ['C', '1B', '2B', '3B', 'SS', 'OF'] for pos in player_positions) return False def check_nfl_position_eligibility(column_name, player_positions): """ Check if a player is eligible for a specific NFL column position. Args: column_name (str): The column name (QB, RB, WR, TE, FLEX, DST) player_positions (list): List of positions the player is eligible for Returns: bool: True if player is eligible for the column """ if any(pos in column_name for pos in ['QB', 'RB', 'WR', 'TE', 'DST']): return any(pos in ['QB', 'RB', 'WR', 'TE', 'DST'] for pos in player_positions) elif 'FLEX' in column_name: return any(pos in ['RB', 'WR', 'TE'] for pos in player_positions) elif 'UTIL' in column_name: return any(pos in ['RB', 'WR', 'TE'] for pos in player_positions) return False def check_golf_position_eligibility(column_name, player_positions): """ Check if a player is eligible for a specific Golf column position. Args: column_name (str): The column name (G) player_positions (list): List of positions the player is eligible for Returns: bool: True if player is eligible for the column """ return True def check_tennis_position_eligibility(column_name, player_positions): """ Check if a player is eligible for a specific Tennis column position. Args: column_name (str): The column name (TEN) player_positions (list): List of positions the player is eligible for Returns: bool: True if player is eligible for the column """ return True def check_mma_position_eligibility(column_name, player_positions): """ Check if a player is eligible for a specific MMA column position. Args: column_name (str): The column name (MMA) player_positions (list): List of positions the player is eligible for Returns: bool: True if player is eligible for the column """ return True def check_nascar_position_eligibility(column_name, player_positions): """ Check if a player is eligible for a specific NASCAR column position. Args: column_name (str): The column name (NAS) player_positions (list): List of positions the player is eligible for Returns: bool: True if player is eligible for the column """ return True def check_cfb_position_eligibility(column_name, player_positions): """ Check if a player is eligible for a specific CFB column position. Args: column_name (str): The column name (QB, RB, WR, TE, FLEX, DST) player_positions (list): List of positions the player is eligible for Returns: bool: True if player is eligible for the column """ if any(pos in column_name for pos in ['QB', 'RB', 'WR']): return any(pos in ['QB', 'RB', 'WR'] for pos in player_positions) elif 'FLEX' in column_name: return any(pos in ['RB', 'WR'] for pos in player_positions) elif 'SUPERFLEX' in column_name: return any(pos in ['RB', 'WR', 'QB'] for pos in player_positions) return False def check_nhl_position_eligibility(column_name, player_positions): """ Check if a player is eligible for a specific NHL column position. Args: column_name (str): The column name (C, LW, RW, D, G, UTIL) player_positions (list): List of positions the player is eligible for Returns: bool: True if player is eligible for the column """ if any(pos in column_name for pos in ['C', 'W', 'D', 'G']): return any(pos in ['C', 'W', 'D', 'G'] for pos in player_positions) elif 'FLEX' in column_name: return True # UTIL can be any position elif 'UTIL' in column_name: return True # UTIL can be any position return False def check_position_eligibility(sport, column_name, player_positions): """ Main function to check position eligibility based on sport. Args: sport (str): The sport (NBA, MLB, NFL, NHL) column_name (str): The column name player_positions (list): List of positions the player is eligible for Returns: bool: True if player is eligible for the column """ if sport == 'NBA': return check_nba_position_eligibility(column_name, player_positions) elif sport == 'MLB': return check_mlb_position_eligibility(column_name, player_positions) elif sport == 'NFL': return check_nfl_position_eligibility(column_name, player_positions) elif sport == 'NHL': return check_nhl_position_eligibility(column_name, player_positions) elif sport == 'MMA': return check_cfb_position_eligibility(column_name, player_positions) elif sport == 'Golf': return check_golf_position_eligibility(column_name, player_positions) elif sport == 'Tennis': return check_tennis_position_eligibility(column_name, player_positions) elif sport == 'LOL': return check_lol_position_eligibility(column_name, player_positions) else: # Default fallback - assume exact position match return column_name in player_positions def exposure_spread(working_frame, exposure_player, exposure_target, exposure_stack_bool, projections_df, sport_var, type_var): # Find comparable players in the projections comparable_players = projections_df[projections_df['player_names'] == exposure_player] comparable_players = comparable_players.reset_index(drop=True) if exposure_stack_bool == 'Yes': comparable_stack = comparable_players['team'][0] else: comparable_stack = 0 comp_salary_high = comparable_players['salary'][0] comp_salary_low = comparable_players['salary'][0] - 500 comp_projection_high = comparable_players['median'][0] comp_projection_low = comparable_players['median'][0] - (comparable_players['median'][0] * .75) # players can be eligible at multiple positions, so we need to find all the positions the player is eligible at # the position column can have positions designated as 1B/OF which means they are eligible at 1B and OF comp_player_position = comparable_players['position'].tolist() comp_player_position = [pos.split('/') for pos in comp_player_position] comp_player_position = [item for sublist in comp_player_position for item in sublist] comp_player_position = list(set(comp_player_position)) def has_position_overlap(player_positions, target_positions): player_pos_list = player_positions.split('/') return any(pos in target_positions for pos in player_pos_list) comparable_players = projections_df[ (projections_df['salary'] >= comp_salary_low) & (projections_df['salary'] <= comp_salary_high) & (projections_df['median'] >= comp_projection_low) & (projections_df['median'] <= comp_projection_high) & (projections_df['position'].apply(lambda x: has_position_overlap(x, comp_player_position))) ] # Create a list of comparable players comparable_player_list = comparable_players['player_names'].tolist() # find the exposure rate of the player in the working frame player_mask = working_frame[working_frame.columns].apply( lambda row: exposure_player in list(row), axis=1 ) player_exposure = player_mask.sum() / len(working_frame) # find the number of lineups that need to be removed to reach the target exposure lineups_to_remove = (player_exposure - exposure_target) * len(working_frame) # isolate the rows that contain the player player_rows = working_frame[player_mask] print(player_rows.head(10)) if comparable_stack != 0: player_rows = player_rows[player_rows['Stack'] != comparable_stack] print(player_rows.head(10)) print(working_frame.head(10)) change_counter = 0 # for each row to the the number of lineups to remove, replace with random choice from comparable player list for row in player_rows.index: if change_counter < math.ceil(lineups_to_remove): insert_player = random.choice(comparable_player_list) # Find which column contains the exposure_player row_data = working_frame.iloc[row] for col in working_frame.columns: if row_data[col] == exposure_player: # Get the replacement player's positions replacement_player_positions = projections_df[projections_df['player_names'] == insert_player]['position'].iloc[0].split('/') # Check if the replacement player is eligible for this column if type_var == 'Classic': if check_position_eligibility(sport_var, col, replacement_player_positions): working_frame.at[row, col] = insert_player break else: working_frame.at[row, col] = insert_player break change_counter += 1 return working_frame